From 31d6ff6f931696850c348007241195ab3b2eddc7 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 07:47:55 +0200 Subject: Adding upstream version 1.55.0+dfsg. Signed-off-by: Daniel Baumann --- src/1p-filters.html | 68 + src/3p-filters.html | 117 + src/_locales/ar/messages.json | 1290 +++ src/_locales/az/messages.json | 1290 +++ src/_locales/be/messages.json | 1290 +++ src/_locales/bg/messages.json | 1290 +++ src/_locales/bn/messages.json | 1290 +++ src/_locales/br_FR/messages.json | 1290 +++ src/_locales/bs/messages.json | 1290 +++ src/_locales/ca/messages.json | 1290 +++ src/_locales/cs/messages.json | 1290 +++ src/_locales/cv/messages.json | 1290 +++ src/_locales/da/messages.json | 1290 +++ src/_locales/de/messages.json | 1290 +++ src/_locales/el/messages.json | 1290 +++ src/_locales/en/messages.json | 1292 +++ src/_locales/en_GB/messages.json | 1290 +++ src/_locales/eo/messages.json | 1290 +++ src/_locales/es/messages.json | 1290 +++ src/_locales/et/messages.json | 1290 +++ src/_locales/eu/messages.json | 1290 +++ src/_locales/fa/messages.json | 1290 +++ src/_locales/fi/messages.json | 1290 +++ src/_locales/fil/messages.json | 1290 +++ src/_locales/fr/messages.json | 1290 +++ src/_locales/fy/messages.json | 1290 +++ src/_locales/gl/messages.json | 1290 +++ src/_locales/gu/messages.json | 1290 +++ src/_locales/he/messages.json | 1290 +++ src/_locales/hi/messages.json | 1290 +++ src/_locales/hr/messages.json | 1290 +++ src/_locales/hu/messages.json | 1290 +++ src/_locales/hy/messages.json | 1290 +++ src/_locales/id/messages.json | 1290 +++ src/_locales/it/messages.json | 1290 +++ src/_locales/ja/messages.json | 1290 +++ src/_locales/ka/messages.json | 1290 +++ src/_locales/kk/messages.json | 1290 +++ src/_locales/kn/messages.json | 1290 +++ src/_locales/ko/messages.json | 1290 +++ src/_locales/ku/messages.json | 1290 +++ src/_locales/lt/messages.json | 1290 +++ src/_locales/lv/messages.json | 1290 +++ src/_locales/mk/messages.json | 1290 +++ src/_locales/ml/messages.json | 1290 +++ src/_locales/mr/messages.json | 1290 +++ src/_locales/ms/messages.json | 1290 +++ src/_locales/nb/messages.json | 1290 +++ src/_locales/nl/messages.json | 1290 +++ src/_locales/oc/messages.json | 1290 +++ src/_locales/pa/messages.json | 1290 +++ src/_locales/pl/messages.json | 1290 +++ src/_locales/pt_BR/messages.json | 1290 +++ src/_locales/pt_PT/messages.json | 1290 +++ src/_locales/ro/messages.json | 1290 +++ src/_locales/ru/messages.json | 1290 +++ src/_locales/si/messages.json | 1290 +++ src/_locales/sk/messages.json | 1290 +++ src/_locales/sl/messages.json | 1290 +++ src/_locales/so/messages.json | 1290 +++ src/_locales/sq/messages.json | 1290 +++ src/_locales/sr/messages.json | 1290 +++ src/_locales/sv/messages.json | 1290 +++ src/_locales/sw/messages.json | 1290 +++ src/_locales/ta/messages.json | 1290 +++ src/_locales/te/messages.json | 1290 +++ src/_locales/th/messages.json | 1290 +++ src/_locales/tr/messages.json | 1290 +++ src/_locales/uk/messages.json | 1290 +++ src/_locales/ur/messages.json | 1290 +++ src/_locales/vi/messages.json | 1290 +++ src/_locales/zh_CN/messages.json | 1290 +++ src/_locales/zh_TW/messages.json | 1290 +++ src/about.html | 63 + src/advanced-settings.html | 42 + src/asset-viewer.html | 50 + src/background.html | 12 + src/cloud-ui.html | 23 + src/code-viewer.html | 53 + src/css/1p-filters.css | 26 + src/css/3p-filters.css | 250 + src/css/about.css | 3 + src/css/advanced-settings.css | 26 + src/css/asset-viewer.css | 79 + src/css/click2load.css | 53 + src/css/cloud-ui.css | 104 + src/css/code-viewer.css | 67 + src/css/codemirror.css | 327 + src/css/common.css | 347 + src/css/dashboard-common.css | 55 + src/css/dashboard.css | 115 + src/css/devtools.css | 22 + src/css/document-blocked.css | 146 + src/css/dom-inspector.css | 40 + src/css/dyna-rules.css | 79 + src/css/epicker-ui.css | 270 + src/css/fa-icons.css | 149 + src/css/fonts/Inter/Inter-Regular.woff2 | Bin 0 -> 100368 bytes src/css/fonts/Inter/Inter-SemiBold.woff2 | Bin 0 -> 106916 bytes src/css/fonts/Inter/LICENSE.txt | 93 + src/css/fonts/Metropolis/Metropolis-Regular.woff2 | Bin 0 -> 24152 bytes src/css/fonts/Metropolis/Metropolis-SemiBold.woff2 | Bin 0 -> 26564 bytes src/css/fonts/Metropolis/README.md | 25 + src/css/fonts/Metropolis/UNLICENSE | 24 + src/css/logger-ui-inspector.css | 122 + src/css/logger-ui.css | 985 ++ src/css/popup-fenix.css | 778 ++ src/css/settings.css | 74 + src/css/support.css | 110 + src/css/themes/default.css | 526 ++ src/css/whitelist.css | 22 + src/dashboard.html | 47 + src/devtools.html | 59 + src/document-blocked.html | 64 + src/dyna-rules.html | 67 + src/img/cloud.png | Bin 0 -> 5017 bytes src/img/flags-of-the-world/README | 9 + src/img/flags-of-the-world/ad.png | Bin 0 -> 672 bytes src/img/flags-of-the-world/ae.png | Bin 0 -> 115 bytes src/img/flags-of-the-world/af.png | Bin 0 -> 934 bytes src/img/flags-of-the-world/ag.png | Bin 0 -> 603 bytes src/img/flags-of-the-world/ai.png | Bin 0 -> 770 bytes src/img/flags-of-the-world/al.png | Bin 0 -> 508 bytes src/img/flags-of-the-world/am.png | Bin 0 -> 106 bytes src/img/flags-of-the-world/ao.png | Bin 0 -> 430 bytes src/img/flags-of-the-world/aq.png | Bin 0 -> 407 bytes src/img/flags-of-the-world/ar.png | Bin 0 -> 345 bytes src/img/flags-of-the-world/as.png | Bin 0 -> 1035 bytes src/img/flags-of-the-world/at.png | Bin 0 -> 94 bytes src/img/flags-of-the-world/au.png | Bin 0 -> 565 bytes src/img/flags-of-the-world/aw.png | Bin 0 -> 249 bytes src/img/flags-of-the-world/ax.png | Bin 0 -> 178 bytes src/img/flags-of-the-world/az.png | Bin 0 -> 238 bytes src/img/flags-of-the-world/ba.png | Bin 0 -> 385 bytes src/img/flags-of-the-world/bb.png | Bin 0 -> 291 bytes src/img/flags-of-the-world/bd.png | Bin 0 -> 282 bytes src/img/flags-of-the-world/be.png | Bin 0 -> 115 bytes src/img/flags-of-the-world/bf.png | Bin 0 -> 236 bytes src/img/flags-of-the-world/bg.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/bh.png | Bin 0 -> 326 bytes src/img/flags-of-the-world/bi.png | Bin 0 -> 651 bytes src/img/flags-of-the-world/bj.png | Bin 0 -> 122 bytes src/img/flags-of-the-world/bl.png | Bin 0 -> 2087 bytes src/img/flags-of-the-world/bm.png | Bin 0 -> 1336 bytes src/img/flags-of-the-world/bn.png | Bin 0 -> 1201 bytes src/img/flags-of-the-world/bo.png | Bin 0 -> 107 bytes src/img/flags-of-the-world/bq.png | Bin 0 -> 619 bytes src/img/flags-of-the-world/br.png | Bin 0 -> 714 bytes src/img/flags-of-the-world/bs.png | Bin 0 -> 304 bytes src/img/flags-of-the-world/bt.png | Bin 0 -> 1250 bytes src/img/flags-of-the-world/bv.png | Bin 0 -> 122 bytes src/img/flags-of-the-world/bw.png | Bin 0 -> 108 bytes src/img/flags-of-the-world/by.png | Bin 0 -> 454 bytes src/img/flags-of-the-world/bz.png | Bin 0 -> 1303 bytes src/img/flags-of-the-world/ca.png | Bin 0 -> 430 bytes src/img/flags-of-the-world/cc.png | Bin 0 -> 618 bytes src/img/flags-of-the-world/cd.png | Bin 0 -> 489 bytes src/img/flags-of-the-world/cf.png | Bin 0 -> 214 bytes src/img/flags-of-the-world/cg.png | Bin 0 -> 196 bytes src/img/flags-of-the-world/ch.png | Bin 0 -> 124 bytes src/img/flags-of-the-world/ci.png | Bin 0 -> 103 bytes src/img/flags-of-the-world/ck.png | Bin 0 -> 803 bytes src/img/flags-of-the-world/cl.png | Bin 0 -> 207 bytes src/img/flags-of-the-world/cm.png | Bin 0 -> 201 bytes src/img/flags-of-the-world/cn.png | Bin 0 -> 265 bytes src/img/flags-of-the-world/co.png | Bin 0 -> 103 bytes src/img/flags-of-the-world/cr.png | Bin 0 -> 419 bytes src/img/flags-of-the-world/cu.png | Bin 0 -> 439 bytes src/img/flags-of-the-world/cv.png | Bin 0 -> 385 bytes src/img/flags-of-the-world/cw.png | Bin 0 -> 234 bytes src/img/flags-of-the-world/cx.png | Bin 0 -> 750 bytes src/img/flags-of-the-world/cy.png | Bin 0 -> 445 bytes src/img/flags-of-the-world/cz.png | Bin 0 -> 277 bytes src/img/flags-of-the-world/de.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/dj.png | Bin 0 -> 503 bytes src/img/flags-of-the-world/dk.png | Bin 0 -> 139 bytes src/img/flags-of-the-world/dm.png | Bin 0 -> 573 bytes src/img/flags-of-the-world/do.png | Bin 0 -> 392 bytes src/img/flags-of-the-world/dz.png | Bin 0 -> 358 bytes src/img/flags-of-the-world/ec.png | Bin 0 -> 1039 bytes src/img/flags-of-the-world/ee.png | Bin 0 -> 107 bytes src/img/flags-of-the-world/eg.png | Bin 0 -> 286 bytes src/img/flags-of-the-world/eh.png | Bin 0 -> 404 bytes src/img/flags-of-the-world/er.png | Bin 0 -> 649 bytes src/img/flags-of-the-world/es.png | Bin 0 -> 755 bytes src/img/flags-of-the-world/et.png | Bin 0 -> 616 bytes src/img/flags-of-the-world/fi.png | Bin 0 -> 140 bytes src/img/flags-of-the-world/fj.png | Bin 0 -> 1166 bytes src/img/flags-of-the-world/fk.png | Bin 0 -> 1501 bytes src/img/flags-of-the-world/fm.png | Bin 0 -> 254 bytes src/img/flags-of-the-world/fo.png | Bin 0 -> 124 bytes src/img/flags-of-the-world/fr.png | Bin 0 -> 104 bytes src/img/flags-of-the-world/ga.png | Bin 0 -> 102 bytes src/img/flags-of-the-world/gb-eng.png | Bin 0 -> 134 bytes src/img/flags-of-the-world/gb-nir.png | Bin 0 -> 745 bytes src/img/flags-of-the-world/gb-sct.png | Bin 0 -> 428 bytes src/img/flags-of-the-world/gb-wls.png | Bin 0 -> 2076 bytes src/img/flags-of-the-world/gb.png | Bin 0 -> 489 bytes src/img/flags-of-the-world/gd.png | Bin 0 -> 615 bytes src/img/flags-of-the-world/ge.png | Bin 0 -> 311 bytes src/img/flags-of-the-world/gf.png | Bin 0 -> 418 bytes src/img/flags-of-the-world/gg.png | Bin 0 -> 170 bytes src/img/flags-of-the-world/gh.png | Bin 0 -> 228 bytes src/img/flags-of-the-world/gi.png | Bin 0 -> 874 bytes src/img/flags-of-the-world/gl.png | Bin 0 -> 341 bytes src/img/flags-of-the-world/gm.png | Bin 0 -> 131 bytes src/img/flags-of-the-world/gn.png | Bin 0 -> 104 bytes src/img/flags-of-the-world/gp.png | Bin 0 -> 993 bytes src/img/flags-of-the-world/gq.png | Bin 0 -> 547 bytes src/img/flags-of-the-world/gr.png | Bin 0 -> 180 bytes src/img/flags-of-the-world/gs.png | Bin 0 -> 1786 bytes src/img/flags-of-the-world/gt.png | Bin 0 -> 485 bytes src/img/flags-of-the-world/gu.png | Bin 0 -> 691 bytes src/img/flags-of-the-world/gw.png | Bin 0 -> 226 bytes src/img/flags-of-the-world/gy.png | Bin 0 -> 509 bytes src/img/flags-of-the-world/hk.png | Bin 0 -> 398 bytes src/img/flags-of-the-world/hm.png | Bin 0 -> 571 bytes src/img/flags-of-the-world/hn.png | Bin 0 -> 206 bytes src/img/flags-of-the-world/hr.png | Bin 0 -> 707 bytes src/img/flags-of-the-world/ht.png | Bin 0 -> 466 bytes src/img/flags-of-the-world/hu.png | Bin 0 -> 106 bytes src/img/flags-of-the-world/id.png | Bin 0 -> 92 bytes src/img/flags-of-the-world/ie.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/il.png | Bin 0 -> 273 bytes src/img/flags-of-the-world/im.png | Bin 0 -> 819 bytes src/img/flags-of-the-world/in.png | Bin 0 -> 225 bytes src/img/flags-of-the-world/io.png | Bin 0 -> 2064 bytes src/img/flags-of-the-world/iq.png | Bin 0 -> 256 bytes src/img/flags-of-the-world/ir.png | Bin 0 -> 533 bytes src/img/flags-of-the-world/is.png | Bin 0 -> 174 bytes src/img/flags-of-the-world/it.png | Bin 0 -> 104 bytes src/img/flags-of-the-world/je.png | Bin 0 -> 965 bytes src/img/flags-of-the-world/jm.png | Bin 0 -> 351 bytes src/img/flags-of-the-world/jo.png | Bin 0 -> 299 bytes src/img/flags-of-the-world/jp.png | Bin 0 -> 245 bytes src/img/flags-of-the-world/ke.png | Bin 0 -> 523 bytes src/img/flags-of-the-world/kg.png | Bin 0 -> 518 bytes src/img/flags-of-the-world/kh.png | Bin 0 -> 598 bytes src/img/flags-of-the-world/ki.png | Bin 0 -> 1314 bytes src/img/flags-of-the-world/km.png | Bin 0 -> 525 bytes src/img/flags-of-the-world/kn.png | Bin 0 -> 657 bytes src/img/flags-of-the-world/kp.png | Bin 0 -> 360 bytes src/img/flags-of-the-world/kr.png | Bin 0 -> 683 bytes src/img/flags-of-the-world/kw.png | Bin 0 -> 227 bytes src/img/flags-of-the-world/ky.png | Bin 0 -> 1535 bytes src/img/flags-of-the-world/kz.png | Bin 0 -> 626 bytes src/img/flags-of-the-world/la.png | Bin 0 -> 223 bytes src/img/flags-of-the-world/lb.png | Bin 0 -> 361 bytes src/img/flags-of-the-world/lc.png | Bin 0 -> 620 bytes src/img/flags-of-the-world/li.png | Bin 0 -> 403 bytes src/img/flags-of-the-world/lk.png | Bin 0 -> 911 bytes src/img/flags-of-the-world/lr.png | Bin 0 -> 277 bytes src/img/flags-of-the-world/ls.png | Bin 0 -> 297 bytes src/img/flags-of-the-world/lt.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/lu.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/lv.png | Bin 0 -> 107 bytes src/img/flags-of-the-world/ly.png | Bin 0 -> 218 bytes src/img/flags-of-the-world/ma.png | Bin 0 -> 219 bytes src/img/flags-of-the-world/mc.png | Bin 0 -> 93 bytes src/img/flags-of-the-world/md.png | Bin 0 -> 761 bytes src/img/flags-of-the-world/me.png | Bin 0 -> 720 bytes src/img/flags-of-the-world/mf.png | Bin 0 -> 104 bytes src/img/flags-of-the-world/mg.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/mh.png | Bin 0 -> 864 bytes src/img/flags-of-the-world/mk.png | Bin 0 -> 578 bytes src/img/flags-of-the-world/ml.png | Bin 0 -> 103 bytes src/img/flags-of-the-world/mm.png | Bin 0 -> 389 bytes src/img/flags-of-the-world/mn.png | Bin 0 -> 329 bytes src/img/flags-of-the-world/mo.png | Bin 0 -> 440 bytes src/img/flags-of-the-world/mp.png | Bin 0 -> 2196 bytes src/img/flags-of-the-world/mq.png | Bin 0 -> 656 bytes src/img/flags-of-the-world/mr.png | Bin 0 -> 374 bytes src/img/flags-of-the-world/ms.png | Bin 0 -> 981 bytes src/img/flags-of-the-world/mt.png | Bin 0 -> 209 bytes src/img/flags-of-the-world/mu.png | Bin 0 -> 109 bytes src/img/flags-of-the-world/mv.png | Bin 0 -> 201 bytes src/img/flags-of-the-world/mw.png | Bin 0 -> 315 bytes src/img/flags-of-the-world/mx.png | Bin 0 -> 822 bytes src/img/flags-of-the-world/my.png | Bin 0 -> 450 bytes src/img/flags-of-the-world/mz.png | Bin 0 -> 751 bytes src/img/flags-of-the-world/na.png | Bin 0 -> 584 bytes src/img/flags-of-the-world/nc.png | Bin 0 -> 664 bytes src/img/flags-of-the-world/ne.png | Bin 0 -> 190 bytes src/img/flags-of-the-world/nf.png | Bin 0 -> 522 bytes src/img/flags-of-the-world/ng.png | Bin 0 -> 97 bytes src/img/flags-of-the-world/ni.png | Bin 0 -> 336 bytes src/img/flags-of-the-world/nl.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/no.png | Bin 0 -> 122 bytes src/img/flags-of-the-world/np.png | Bin 0 -> 588 bytes src/img/flags-of-the-world/nr.png | Bin 0 -> 205 bytes src/img/flags-of-the-world/nu.png | Bin 0 -> 510 bytes src/img/flags-of-the-world/nz.png | Bin 0 -> 608 bytes src/img/flags-of-the-world/om.png | Bin 0 -> 291 bytes src/img/flags-of-the-world/pa.png | Bin 0 -> 318 bytes src/img/flags-of-the-world/pe.png | Bin 0 -> 97 bytes src/img/flags-of-the-world/pf.png | Bin 0 -> 816 bytes src/img/flags-of-the-world/pg.png | Bin 0 -> 589 bytes src/img/flags-of-the-world/ph.png | Bin 0 -> 616 bytes src/img/flags-of-the-world/pk.png | Bin 0 -> 355 bytes src/img/flags-of-the-world/pl.png | Bin 0 -> 94 bytes src/img/flags-of-the-world/pm.png | Bin 0 -> 2708 bytes src/img/flags-of-the-world/pn.png | Bin 0 -> 1630 bytes src/img/flags-of-the-world/pr.png | Bin 0 -> 456 bytes src/img/flags-of-the-world/ps.png | Bin 0 -> 297 bytes src/img/flags-of-the-world/pt.png | Bin 0 -> 1068 bytes src/img/flags-of-the-world/pw.png | Bin 0 -> 300 bytes src/img/flags-of-the-world/py.png | Bin 0 -> 320 bytes src/img/flags-of-the-world/qa.png | Bin 0 -> 213 bytes src/img/flags-of-the-world/re.png | Bin 0 -> 620 bytes src/img/flags-of-the-world/ro.png | Bin 0 -> 103 bytes src/img/flags-of-the-world/rs.png | Bin 0 -> 1245 bytes src/img/flags-of-the-world/ru.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/rw.png | Bin 0 -> 255 bytes src/img/flags-of-the-world/sa.png | Bin 0 -> 433 bytes src/img/flags-of-the-world/sb.png | Bin 0 -> 574 bytes src/img/flags-of-the-world/sc.png | Bin 0 -> 470 bytes src/img/flags-of-the-world/sd.png | Bin 0 -> 295 bytes src/img/flags-of-the-world/se.png | Bin 0 -> 140 bytes src/img/flags-of-the-world/sg.png | Bin 0 -> 306 bytes src/img/flags-of-the-world/sh.png | Bin 0 -> 925 bytes src/img/flags-of-the-world/si.png | Bin 0 -> 303 bytes src/img/flags-of-the-world/sj.png | Bin 0 -> 122 bytes src/img/flags-of-the-world/sk.png | Bin 0 -> 454 bytes src/img/flags-of-the-world/sl.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/sm.png | Bin 0 -> 1204 bytes src/img/flags-of-the-world/sn.png | Bin 0 -> 233 bytes src/img/flags-of-the-world/so.png | Bin 0 -> 271 bytes src/img/flags-of-the-world/sr.png | Bin 0 -> 247 bytes src/img/flags-of-the-world/ss.png | Bin 0 -> 475 bytes src/img/flags-of-the-world/st.png | Bin 0 -> 351 bytes src/img/flags-of-the-world/sv.png | Bin 0 -> 488 bytes src/img/flags-of-the-world/sx.png | Bin 0 -> 945 bytes src/img/flags-of-the-world/sy.png | Bin 0 -> 237 bytes src/img/flags-of-the-world/sz.png | Bin 0 -> 917 bytes src/img/flags-of-the-world/tc.png | Bin 0 -> 824 bytes src/img/flags-of-the-world/td.png | Bin 0 -> 104 bytes src/img/flags-of-the-world/tf.png | Bin 0 -> 377 bytes src/img/flags-of-the-world/tg.png | Bin 0 -> 292 bytes src/img/flags-of-the-world/th.png | Bin 0 -> 108 bytes src/img/flags-of-the-world/tj.png | Bin 0 -> 330 bytes src/img/flags-of-the-world/tk.png | Bin 0 -> 606 bytes src/img/flags-of-the-world/tl.png | Bin 0 -> 441 bytes src/img/flags-of-the-world/tm.png | Bin 0 -> 1517 bytes src/img/flags-of-the-world/tn.png | Bin 0 -> 306 bytes src/img/flags-of-the-world/to.png | Bin 0 -> 108 bytes src/img/flags-of-the-world/tr.png | Bin 0 -> 317 bytes src/img/flags-of-the-world/tt.png | Bin 0 -> 667 bytes src/img/flags-of-the-world/tv.png | Bin 0 -> 726 bytes src/img/flags-of-the-world/tw.png | Bin 0 -> 259 bytes src/img/flags-of-the-world/tz.png | Bin 0 -> 382 bytes src/img/flags-of-the-world/ua.png | Bin 0 -> 92 bytes src/img/flags-of-the-world/ug.png | Bin 0 -> 388 bytes src/img/flags-of-the-world/um.png | Bin 0 -> 539 bytes src/img/flags-of-the-world/us.png | Bin 0 -> 539 bytes src/img/flags-of-the-world/uy.png | Bin 0 -> 574 bytes src/img/flags-of-the-world/uz.png | Bin 0 -> 310 bytes src/img/flags-of-the-world/va.png | Bin 0 -> 750 bytes src/img/flags-of-the-world/vc.png | Bin 0 -> 317 bytes src/img/flags-of-the-world/ve.png | Bin 0 -> 268 bytes src/img/flags-of-the-world/vg.png | Bin 0 -> 1339 bytes src/img/flags-of-the-world/vi.png | Bin 0 -> 2159 bytes src/img/flags-of-the-world/vn.png | Bin 0 -> 282 bytes src/img/flags-of-the-world/vu.png | Bin 0 -> 662 bytes src/img/flags-of-the-world/wf.png | Bin 0 -> 260 bytes src/img/flags-of-the-world/ws.png | Bin 0 -> 255 bytes src/img/flags-of-the-world/xk.png | Bin 0 -> 453 bytes src/img/flags-of-the-world/ye.png | Bin 0 -> 105 bytes src/img/flags-of-the-world/yt.png | Bin 0 -> 1402 bytes src/img/flags-of-the-world/za.png | Bin 0 -> 387 bytes src/img/flags-of-the-world/zm.png | Bin 0 -> 297 bytes src/img/flags-of-the-world/zw.png | Bin 0 -> 617 bytes src/img/fontawesome/LICENSE.txt | 25 + src/img/fontawesome/fontawesome-defs.svg | 79 + src/img/help16.png | Bin 0 -> 215 bytes src/img/icon_128.png | Bin 0 -> 3552 bytes src/img/icon_16-loading.png | Bin 0 -> 570 bytes src/img/icon_16-off.png | Bin 0 -> 552 bytes src/img/icon_16.png | Bin 0 -> 420 bytes src/img/icon_32-loading.png | Bin 0 -> 1089 bytes src/img/icon_32-off.png | Bin 0 -> 1114 bytes src/img/icon_32.png | Bin 0 -> 1278 bytes src/img/icon_64-loading.png | Bin 0 -> 4406 bytes src/img/icon_64-off.png | Bin 0 -> 4955 bytes src/img/icon_64.png | Bin 0 -> 2655 bytes src/img/material-design.svg | 16 + src/img/photon.svg | 16 + src/img/ublock-defs.svg | 27 + src/img/ublock.svg | 44 + src/js/1p-filters.js | 337 + src/js/3p-filters.js | 861 ++ src/js/about.js | 34 + src/js/advanced-settings.js | 194 + src/js/asset-viewer.js | 112 + src/js/assets.js | 1478 +++ src/js/background.js | 410 + src/js/base64-custom.js | 246 + src/js/benchmarks.js | 421 + src/js/biditrie.js | 947 ++ src/js/broadcast.js | 75 + src/js/cachestorage.js | 533 ++ src/js/click2load.js | 60 + src/js/cloud-ui.js | 238 + src/js/code-viewer.js | 311 + src/js/codemirror/search-thread.js | 199 + src/js/codemirror/search.js | 504 + src/js/codemirror/ubo-dynamic-filtering.js | 239 + src/js/codemirror/ubo-static-filtering.js | 1200 +++ src/js/commands.js | 181 + src/js/console.js | 59 + src/js/contentscript-extra.js | 662 ++ src/js/contentscript.js | 1364 +++ src/js/contextmenu.js | 270 + src/js/cosmetic-filtering.js | 983 ++ src/js/dashboard-common.js | 215 + src/js/dashboard.js | 166 + src/js/devtools.js | 192 + src/js/diff-updater.js | 288 + src/js/document-blocked.js | 230 + src/js/dom-inspector.js | 68 + src/js/dom.js | 213 + src/js/dyna-rules.js | 678 ++ src/js/dynamic-net-filtering.js | 488 + src/js/epicker-ui.js | 900 ++ src/js/fa-icons.js | 129 + src/js/filtering-context.js | 461 + src/js/filtering-engines.js | 50 + src/js/hnswitches.js | 289 + src/js/hntrie.js | 780 ++ src/js/html-filtering.js | 465 + src/js/httpheader-filtering.js | 213 + src/js/i18n.js | 346 + src/js/logger-ui-inspector.js | 710 ++ src/js/logger-ui.js | 3044 ++++++ src/js/logger.js | 88 + src/js/lz4.js | 190 + src/js/messaging.js | 2195 +++++ src/js/mrucache.js | 58 + src/js/pagestore.js | 1140 +++ src/js/popup-fenix.js | 1530 +++ src/js/redirect-engine.js | 494 + src/js/redirect-resources.js | 182 + src/js/reverselookup-worker.js | 287 + src/js/reverselookup.js | 223 + src/js/scriptlet-filtering-core.js | 300 + src/js/scriptlet-filtering.js | 328 + src/js/scriptlets/cosmetic-logger.js | 365 + src/js/scriptlets/cosmetic-off.js | 48 + src/js/scriptlets/cosmetic-on.js | 48 + src/js/scriptlets/cosmetic-report.js | 142 + src/js/scriptlets/dom-inspector.js | 924 ++ src/js/scriptlets/dom-survey-elements.js | 72 + src/js/scriptlets/dom-survey-scripts.js | 126 + src/js/scriptlets/epicker.js | 1356 +++ src/js/scriptlets/load-3p-css.js | 67 + src/js/scriptlets/load-large-media-all.js | 62 + src/js/scriptlets/load-large-media-interactive.js | 299 + src/js/scriptlets/noscript-spoof.js | 89 + src/js/scriptlets/should-inject-contentscript.js | 40 + src/js/scriptlets/subscriber.js | 113 + src/js/scriptlets/updater.js | 118 + src/js/settings.js | 317 + src/js/start.js | 508 + src/js/static-dnr-filtering.js | 497 + src/js/static-ext-filtering-db.js | 171 + src/js/static-ext-filtering.js | 184 + src/js/static-filtering-io.js | 144 + src/js/static-filtering-parser.js | 4461 +++++++++ src/js/static-net-filtering.js | 5651 +++++++++++ src/js/storage.js | 1703 ++++ src/js/support.js | 335 + src/js/tab.js | 1178 +++ src/js/tasks.js | 42 + src/js/text-encode.js | 275 + src/js/text-utils.js | 107 + src/js/theme.js | 151 + src/js/traffic.js | 1261 +++ src/js/ublock.js | 700 ++ src/js/uri-utils.js | 175 + src/js/url-net-filtering.js | 336 + src/js/utils.js | 136 + src/js/wasm/README.md | 24 + src/js/wasm/biditrie.wasm | Bin 0 -> 990 bytes src/js/wasm/biditrie.wat | 728 ++ src/js/wasm/hntrie.wasm | Bin 0 -> 1034 bytes src/js/wasm/hntrie.wat | 724 ++ src/js/whitelist.js | 258 + src/lib/codemirror/LICENSE | 21 + src/lib/codemirror/README.md | 47 + src/lib/codemirror/addon/comment/comment.js | 211 + src/lib/codemirror/addon/display/panel.js | 133 + src/lib/codemirror/addon/edit/closebrackets.js | 201 + src/lib/codemirror/addon/edit/matchbrackets.js | 160 + src/lib/codemirror/addon/fold/foldcode.js | 157 + src/lib/codemirror/addon/fold/foldgutter.css | 20 + src/lib/codemirror/addon/fold/foldgutter.js | 163 + src/lib/codemirror/addon/hint/show-hint.css | 36 + src/lib/codemirror/addon/hint/show-hint.js | 509 + src/lib/codemirror/addon/merge/merge.css | 119 + src/lib/codemirror/addon/merge/merge.js | 1006 ++ .../codemirror/addon/scroll/annotatescrollbar.js | 128 + .../codemirror/addon/search/matchesonscrollbar.css | 8 + src/lib/codemirror/addon/search/searchcursor.js | 296 + src/lib/codemirror/addon/selection/active-line.js | 72 + src/lib/codemirror/lib/codemirror.css | 350 + src/lib/codemirror/lib/codemirror.js | 9800 ++++++++++++++++++++ src/lib/codemirror/mode/css/css.js | 864 ++ src/lib/codemirror/mode/htmlmixed/htmlmixed.js | 153 + src/lib/codemirror/mode/javascript/javascript.js | 942 ++ src/lib/codemirror/mode/xml/xml.js | 413 + src/lib/codemirror/theme/night.css | 27 + src/lib/csstree/LICENSE | 19 + src/lib/csstree/css-tree.js | 17 + src/lib/diff/README.md | 34 + src/lib/diff/swatinem_diff.js | 272 + src/lib/hsluv/LICENSE | 20 + src/lib/hsluv/README | 3 + src/lib/hsluv/hsluv-0.1.0.min.js | 8 + src/lib/js-beautify/LICENSE | 9 + src/lib/js-beautify/README | 5 + src/lib/js-beautify/beautifier.min.js | 2 + src/lib/lz4/README.md | 52 + src/lib/lz4/lz4-block-codec-any.js | 151 + src/lib/lz4/lz4-block-codec-js.js | 297 + src/lib/lz4/lz4-block-codec-wasm.js | 195 + src/lib/lz4/lz4-block-codec.wasm | Bin 0 -> 1226 bytes src/lib/lz4/lz4-block-codec.wat | 745 ++ src/lib/publicsuffixlist/publicsuffixlist.js | 641 ++ src/lib/publicsuffixlist/wasm/README.md | 29 + .../publicsuffixlist/wasm/publicsuffixlist.wasm | Bin 0 -> 408 bytes src/lib/publicsuffixlist/wasm/publicsuffixlist.wat | 322 + src/lib/punycode.js | 493 + src/lib/regexanalyzer/CHANGES.md | 15 + src/lib/regexanalyzer/README.md | 14 + src/lib/regexanalyzer/regex.js | 2276 +++++ src/logger-ui.html | 232 + src/no-dashboard.html | 27 + src/popup-fenix.html | 114 + src/settings.html | 98 + src/support.html | 130 + src/web_accessible_resources/1x1.gif | Bin 0 -> 43 bytes src/web_accessible_resources/2x2.png | Bin 0 -> 68 bytes src/web_accessible_resources/32x32.png | Bin 0 -> 83 bytes src/web_accessible_resources/3x2.png | Bin 0 -> 68 bytes src/web_accessible_resources/README.txt | 11 + src/web_accessible_resources/amazon_ads.js | 70 + src/web_accessible_resources/amazon_apstag.js | 62 + src/web_accessible_resources/ampproject_v0.js | 34 + src/web_accessible_resources/chartbeat.js | 30 + src/web_accessible_resources/click2load.html | 28 + src/web_accessible_resources/dom-inspector.html | 25 + .../doubleclick_instream_ad_status.js | 1 + src/web_accessible_resources/empty | 0 src/web_accessible_resources/epicker-ui.html | 75 + src/web_accessible_resources/fingerprint2.js | 55 + src/web_accessible_resources/fingerprint3.js | 45 + .../google-analytics_analytics.js | 110 + .../google-analytics_cx_api.js | 36 + .../google-analytics_ga.js | 130 + .../google-analytics_inpage_linkid.js | 28 + src/web_accessible_resources/google-ima.js | 855 ++ .../googlesyndication_adsbygoogle.js | 56 + .../googletagmanager_gtm.js | 43 + .../googletagservices_gpt.js | 154 + src/web_accessible_resources/hd-main.js | 46 + src/web_accessible_resources/nobab.js | 87 + src/web_accessible_resources/nobab2.js | 42 + src/web_accessible_resources/noeval-silent.js | 28 + src/web_accessible_resources/noeval.js | 30 + src/web_accessible_resources/nofab.js | 67 + src/web_accessible_resources/noop-0.1s.mp3 | Bin 0 -> 813 bytes src/web_accessible_resources/noop-0.5s.mp3 | Bin 0 -> 2349 bytes src/web_accessible_resources/noop-1s.mp4 | Bin 0 -> 3753 bytes src/web_accessible_resources/noop-vmap1.0.xml | 1 + src/web_accessible_resources/noop.css | 1 + src/web_accessible_resources/noop.html | 5 + src/web_accessible_resources/noop.js | 3 + src/web_accessible_resources/noop.json | 1 + src/web_accessible_resources/noop.txt | 1 + src/web_accessible_resources/outbrain-widget.js | 72 + src/web_accessible_resources/popads-dummy.js | 30 + src/web_accessible_resources/popads.js | 40 + src/web_accessible_resources/prebid-ads.js | 26 + .../scorecardresearch_beacon.js | 31 + src/whitelist.html | 63 + 584 files changed, 174661 insertions(+) create mode 100644 src/1p-filters.html create mode 100644 src/3p-filters.html create mode 100644 src/_locales/ar/messages.json create mode 100644 src/_locales/az/messages.json create mode 100644 src/_locales/be/messages.json create mode 100644 src/_locales/bg/messages.json create mode 100644 src/_locales/bn/messages.json create mode 100644 src/_locales/br_FR/messages.json create mode 100644 src/_locales/bs/messages.json create mode 100644 src/_locales/ca/messages.json create mode 100644 src/_locales/cs/messages.json create mode 100644 src/_locales/cv/messages.json create mode 100644 src/_locales/da/messages.json create mode 100644 src/_locales/de/messages.json create mode 100644 src/_locales/el/messages.json create mode 100644 src/_locales/en/messages.json create mode 100644 src/_locales/en_GB/messages.json create mode 100644 src/_locales/eo/messages.json create mode 100644 src/_locales/es/messages.json create mode 100644 src/_locales/et/messages.json create mode 100644 src/_locales/eu/messages.json create mode 100644 src/_locales/fa/messages.json create mode 100644 src/_locales/fi/messages.json create mode 100644 src/_locales/fil/messages.json create mode 100644 src/_locales/fr/messages.json create mode 100644 src/_locales/fy/messages.json create mode 100644 src/_locales/gl/messages.json create mode 100644 src/_locales/gu/messages.json create mode 100644 src/_locales/he/messages.json create mode 100644 src/_locales/hi/messages.json create mode 100644 src/_locales/hr/messages.json create mode 100644 src/_locales/hu/messages.json create mode 100644 src/_locales/hy/messages.json create mode 100644 src/_locales/id/messages.json create mode 100644 src/_locales/it/messages.json create mode 100644 src/_locales/ja/messages.json create mode 100644 src/_locales/ka/messages.json create mode 100644 src/_locales/kk/messages.json create mode 100644 src/_locales/kn/messages.json create mode 100644 src/_locales/ko/messages.json create mode 100644 src/_locales/ku/messages.json create mode 100644 src/_locales/lt/messages.json create mode 100644 src/_locales/lv/messages.json create mode 100644 src/_locales/mk/messages.json create mode 100644 src/_locales/ml/messages.json create mode 100644 src/_locales/mr/messages.json create mode 100644 src/_locales/ms/messages.json create mode 100644 src/_locales/nb/messages.json create mode 100644 src/_locales/nl/messages.json create mode 100644 src/_locales/oc/messages.json create mode 100644 src/_locales/pa/messages.json create mode 100644 src/_locales/pl/messages.json create mode 100644 src/_locales/pt_BR/messages.json create mode 100644 src/_locales/pt_PT/messages.json create mode 100644 src/_locales/ro/messages.json create mode 100644 src/_locales/ru/messages.json create mode 100644 src/_locales/si/messages.json create mode 100644 src/_locales/sk/messages.json create mode 100644 src/_locales/sl/messages.json create mode 100644 src/_locales/so/messages.json create mode 100644 src/_locales/sq/messages.json create mode 100644 src/_locales/sr/messages.json create mode 100644 src/_locales/sv/messages.json create mode 100644 src/_locales/sw/messages.json create mode 100644 src/_locales/ta/messages.json create mode 100644 src/_locales/te/messages.json create mode 100644 src/_locales/th/messages.json create mode 100644 src/_locales/tr/messages.json create mode 100644 src/_locales/uk/messages.json create mode 100644 src/_locales/ur/messages.json create mode 100644 src/_locales/vi/messages.json create mode 100644 src/_locales/zh_CN/messages.json create mode 100644 src/_locales/zh_TW/messages.json create mode 100644 src/about.html create mode 100644 src/advanced-settings.html create mode 100644 src/asset-viewer.html create mode 100644 src/background.html create mode 100644 src/cloud-ui.html create mode 100644 src/code-viewer.html create mode 100644 src/css/1p-filters.css create mode 100644 src/css/3p-filters.css create mode 100644 src/css/about.css create mode 100644 src/css/advanced-settings.css create mode 100644 src/css/asset-viewer.css create mode 100644 src/css/click2load.css create mode 100644 src/css/cloud-ui.css create mode 100644 src/css/code-viewer.css create mode 100644 src/css/codemirror.css create mode 100644 src/css/common.css create mode 100644 src/css/dashboard-common.css create mode 100644 src/css/dashboard.css create mode 100644 src/css/devtools.css create mode 100644 src/css/document-blocked.css create mode 100644 src/css/dom-inspector.css create mode 100644 src/css/dyna-rules.css create mode 100644 src/css/epicker-ui.css create mode 100644 src/css/fa-icons.css create mode 100644 src/css/fonts/Inter/Inter-Regular.woff2 create mode 100644 src/css/fonts/Inter/Inter-SemiBold.woff2 create mode 100644 src/css/fonts/Inter/LICENSE.txt create mode 100644 src/css/fonts/Metropolis/Metropolis-Regular.woff2 create mode 100644 src/css/fonts/Metropolis/Metropolis-SemiBold.woff2 create mode 100644 src/css/fonts/Metropolis/README.md create mode 100644 src/css/fonts/Metropolis/UNLICENSE create mode 100644 src/css/logger-ui-inspector.css create mode 100644 src/css/logger-ui.css create mode 100644 src/css/popup-fenix.css create mode 100644 src/css/settings.css create mode 100644 src/css/support.css create mode 100644 src/css/themes/default.css create mode 100644 src/css/whitelist.css create mode 100644 src/dashboard.html create mode 100644 src/devtools.html create mode 100644 src/document-blocked.html create mode 100644 src/dyna-rules.html create mode 100644 src/img/cloud.png create mode 100644 src/img/flags-of-the-world/README create mode 100644 src/img/flags-of-the-world/ad.png create mode 100644 src/img/flags-of-the-world/ae.png create mode 100644 src/img/flags-of-the-world/af.png create mode 100644 src/img/flags-of-the-world/ag.png create mode 100644 src/img/flags-of-the-world/ai.png create mode 100644 src/img/flags-of-the-world/al.png create mode 100644 src/img/flags-of-the-world/am.png create mode 100644 src/img/flags-of-the-world/ao.png create mode 100644 src/img/flags-of-the-world/aq.png create mode 100644 src/img/flags-of-the-world/ar.png create mode 100644 src/img/flags-of-the-world/as.png create mode 100644 src/img/flags-of-the-world/at.png create mode 100644 src/img/flags-of-the-world/au.png create mode 100644 src/img/flags-of-the-world/aw.png create mode 100644 src/img/flags-of-the-world/ax.png create mode 100644 src/img/flags-of-the-world/az.png create mode 100644 src/img/flags-of-the-world/ba.png create mode 100644 src/img/flags-of-the-world/bb.png create mode 100644 src/img/flags-of-the-world/bd.png create mode 100644 src/img/flags-of-the-world/be.png create mode 100644 src/img/flags-of-the-world/bf.png create mode 100644 src/img/flags-of-the-world/bg.png create mode 100644 src/img/flags-of-the-world/bh.png create mode 100644 src/img/flags-of-the-world/bi.png create mode 100644 src/img/flags-of-the-world/bj.png create mode 100644 src/img/flags-of-the-world/bl.png create mode 100644 src/img/flags-of-the-world/bm.png create mode 100644 src/img/flags-of-the-world/bn.png create mode 100644 src/img/flags-of-the-world/bo.png create mode 100644 src/img/flags-of-the-world/bq.png create mode 100644 src/img/flags-of-the-world/br.png create mode 100644 src/img/flags-of-the-world/bs.png create mode 100644 src/img/flags-of-the-world/bt.png create mode 100644 src/img/flags-of-the-world/bv.png create mode 100644 src/img/flags-of-the-world/bw.png create mode 100644 src/img/flags-of-the-world/by.png create mode 100644 src/img/flags-of-the-world/bz.png create mode 100644 src/img/flags-of-the-world/ca.png create mode 100644 src/img/flags-of-the-world/cc.png create mode 100644 src/img/flags-of-the-world/cd.png create mode 100644 src/img/flags-of-the-world/cf.png create mode 100644 src/img/flags-of-the-world/cg.png create mode 100644 src/img/flags-of-the-world/ch.png create mode 100644 src/img/flags-of-the-world/ci.png create mode 100644 src/img/flags-of-the-world/ck.png create mode 100644 src/img/flags-of-the-world/cl.png create mode 100644 src/img/flags-of-the-world/cm.png create mode 100644 src/img/flags-of-the-world/cn.png create mode 100644 src/img/flags-of-the-world/co.png create mode 100644 src/img/flags-of-the-world/cr.png create mode 100644 src/img/flags-of-the-world/cu.png create mode 100644 src/img/flags-of-the-world/cv.png create mode 100644 src/img/flags-of-the-world/cw.png create mode 100644 src/img/flags-of-the-world/cx.png create mode 100644 src/img/flags-of-the-world/cy.png create mode 100644 src/img/flags-of-the-world/cz.png create mode 100644 src/img/flags-of-the-world/de.png create mode 100644 src/img/flags-of-the-world/dj.png create mode 100644 src/img/flags-of-the-world/dk.png create mode 100644 src/img/flags-of-the-world/dm.png create mode 100644 src/img/flags-of-the-world/do.png create mode 100644 src/img/flags-of-the-world/dz.png create mode 100644 src/img/flags-of-the-world/ec.png create mode 100644 src/img/flags-of-the-world/ee.png create mode 100644 src/img/flags-of-the-world/eg.png create mode 100644 src/img/flags-of-the-world/eh.png create mode 100644 src/img/flags-of-the-world/er.png create mode 100644 src/img/flags-of-the-world/es.png create mode 100644 src/img/flags-of-the-world/et.png create mode 100644 src/img/flags-of-the-world/fi.png create mode 100644 src/img/flags-of-the-world/fj.png create mode 100644 src/img/flags-of-the-world/fk.png create mode 100644 src/img/flags-of-the-world/fm.png create mode 100644 src/img/flags-of-the-world/fo.png create mode 100644 src/img/flags-of-the-world/fr.png create mode 100644 src/img/flags-of-the-world/ga.png create mode 100644 src/img/flags-of-the-world/gb-eng.png create mode 100644 src/img/flags-of-the-world/gb-nir.png create mode 100644 src/img/flags-of-the-world/gb-sct.png create mode 100644 src/img/flags-of-the-world/gb-wls.png create mode 100644 src/img/flags-of-the-world/gb.png create mode 100644 src/img/flags-of-the-world/gd.png create mode 100644 src/img/flags-of-the-world/ge.png create mode 100644 src/img/flags-of-the-world/gf.png create mode 100644 src/img/flags-of-the-world/gg.png create mode 100644 src/img/flags-of-the-world/gh.png create mode 100644 src/img/flags-of-the-world/gi.png create mode 100644 src/img/flags-of-the-world/gl.png create mode 100644 src/img/flags-of-the-world/gm.png create mode 100644 src/img/flags-of-the-world/gn.png create mode 100644 src/img/flags-of-the-world/gp.png create mode 100644 src/img/flags-of-the-world/gq.png create mode 100644 src/img/flags-of-the-world/gr.png create mode 100644 src/img/flags-of-the-world/gs.png create mode 100644 src/img/flags-of-the-world/gt.png create mode 100644 src/img/flags-of-the-world/gu.png create mode 100644 src/img/flags-of-the-world/gw.png create mode 100644 src/img/flags-of-the-world/gy.png create mode 100644 src/img/flags-of-the-world/hk.png create mode 100644 src/img/flags-of-the-world/hm.png create mode 100644 src/img/flags-of-the-world/hn.png create mode 100644 src/img/flags-of-the-world/hr.png create mode 100644 src/img/flags-of-the-world/ht.png create mode 100644 src/img/flags-of-the-world/hu.png create mode 100644 src/img/flags-of-the-world/id.png create mode 100644 src/img/flags-of-the-world/ie.png create mode 100644 src/img/flags-of-the-world/il.png create mode 100644 src/img/flags-of-the-world/im.png create mode 100644 src/img/flags-of-the-world/in.png create mode 100644 src/img/flags-of-the-world/io.png create mode 100644 src/img/flags-of-the-world/iq.png create mode 100644 src/img/flags-of-the-world/ir.png create mode 100644 src/img/flags-of-the-world/is.png create mode 100644 src/img/flags-of-the-world/it.png create mode 100644 src/img/flags-of-the-world/je.png create mode 100644 src/img/flags-of-the-world/jm.png create mode 100644 src/img/flags-of-the-world/jo.png create mode 100644 src/img/flags-of-the-world/jp.png create mode 100644 src/img/flags-of-the-world/ke.png create mode 100644 src/img/flags-of-the-world/kg.png create mode 100644 src/img/flags-of-the-world/kh.png create mode 100644 src/img/flags-of-the-world/ki.png create mode 100644 src/img/flags-of-the-world/km.png create mode 100644 src/img/flags-of-the-world/kn.png create mode 100644 src/img/flags-of-the-world/kp.png create mode 100644 src/img/flags-of-the-world/kr.png create mode 100644 src/img/flags-of-the-world/kw.png create mode 100644 src/img/flags-of-the-world/ky.png create mode 100644 src/img/flags-of-the-world/kz.png create mode 100644 src/img/flags-of-the-world/la.png create mode 100644 src/img/flags-of-the-world/lb.png create mode 100644 src/img/flags-of-the-world/lc.png create mode 100644 src/img/flags-of-the-world/li.png create mode 100644 src/img/flags-of-the-world/lk.png create mode 100644 src/img/flags-of-the-world/lr.png create mode 100644 src/img/flags-of-the-world/ls.png create mode 100644 src/img/flags-of-the-world/lt.png create mode 100644 src/img/flags-of-the-world/lu.png create mode 100644 src/img/flags-of-the-world/lv.png create mode 100644 src/img/flags-of-the-world/ly.png create mode 100644 src/img/flags-of-the-world/ma.png create mode 100644 src/img/flags-of-the-world/mc.png create mode 100644 src/img/flags-of-the-world/md.png create mode 100644 src/img/flags-of-the-world/me.png create mode 100644 src/img/flags-of-the-world/mf.png create mode 100644 src/img/flags-of-the-world/mg.png create mode 100644 src/img/flags-of-the-world/mh.png create mode 100644 src/img/flags-of-the-world/mk.png create mode 100644 src/img/flags-of-the-world/ml.png create mode 100644 src/img/flags-of-the-world/mm.png create mode 100644 src/img/flags-of-the-world/mn.png create mode 100644 src/img/flags-of-the-world/mo.png create mode 100644 src/img/flags-of-the-world/mp.png create mode 100644 src/img/flags-of-the-world/mq.png create mode 100644 src/img/flags-of-the-world/mr.png create mode 100644 src/img/flags-of-the-world/ms.png create mode 100644 src/img/flags-of-the-world/mt.png create mode 100644 src/img/flags-of-the-world/mu.png create mode 100644 src/img/flags-of-the-world/mv.png create mode 100644 src/img/flags-of-the-world/mw.png create mode 100644 src/img/flags-of-the-world/mx.png create mode 100644 src/img/flags-of-the-world/my.png create mode 100644 src/img/flags-of-the-world/mz.png create mode 100644 src/img/flags-of-the-world/na.png create mode 100644 src/img/flags-of-the-world/nc.png create mode 100644 src/img/flags-of-the-world/ne.png create mode 100644 src/img/flags-of-the-world/nf.png create mode 100644 src/img/flags-of-the-world/ng.png create mode 100644 src/img/flags-of-the-world/ni.png create mode 100644 src/img/flags-of-the-world/nl.png create mode 100644 src/img/flags-of-the-world/no.png create mode 100644 src/img/flags-of-the-world/np.png create mode 100644 src/img/flags-of-the-world/nr.png create mode 100644 src/img/flags-of-the-world/nu.png create mode 100644 src/img/flags-of-the-world/nz.png create mode 100644 src/img/flags-of-the-world/om.png create mode 100644 src/img/flags-of-the-world/pa.png create mode 100644 src/img/flags-of-the-world/pe.png create mode 100644 src/img/flags-of-the-world/pf.png create mode 100644 src/img/flags-of-the-world/pg.png create mode 100644 src/img/flags-of-the-world/ph.png create mode 100644 src/img/flags-of-the-world/pk.png create mode 100644 src/img/flags-of-the-world/pl.png create mode 100644 src/img/flags-of-the-world/pm.png create mode 100644 src/img/flags-of-the-world/pn.png create mode 100644 src/img/flags-of-the-world/pr.png create mode 100644 src/img/flags-of-the-world/ps.png create mode 100644 src/img/flags-of-the-world/pt.png create mode 100644 src/img/flags-of-the-world/pw.png create mode 100644 src/img/flags-of-the-world/py.png create mode 100644 src/img/flags-of-the-world/qa.png create mode 100644 src/img/flags-of-the-world/re.png create mode 100644 src/img/flags-of-the-world/ro.png create mode 100644 src/img/flags-of-the-world/rs.png create mode 100644 src/img/flags-of-the-world/ru.png create mode 100644 src/img/flags-of-the-world/rw.png create mode 100644 src/img/flags-of-the-world/sa.png create mode 100644 src/img/flags-of-the-world/sb.png create mode 100644 src/img/flags-of-the-world/sc.png create mode 100644 src/img/flags-of-the-world/sd.png create mode 100644 src/img/flags-of-the-world/se.png create mode 100644 src/img/flags-of-the-world/sg.png create mode 100644 src/img/flags-of-the-world/sh.png create mode 100644 src/img/flags-of-the-world/si.png create mode 100644 src/img/flags-of-the-world/sj.png create mode 100644 src/img/flags-of-the-world/sk.png create mode 100644 src/img/flags-of-the-world/sl.png create mode 100644 src/img/flags-of-the-world/sm.png create mode 100644 src/img/flags-of-the-world/sn.png create mode 100644 src/img/flags-of-the-world/so.png create mode 100644 src/img/flags-of-the-world/sr.png create mode 100644 src/img/flags-of-the-world/ss.png create mode 100644 src/img/flags-of-the-world/st.png create mode 100644 src/img/flags-of-the-world/sv.png create mode 100644 src/img/flags-of-the-world/sx.png create mode 100644 src/img/flags-of-the-world/sy.png create mode 100644 src/img/flags-of-the-world/sz.png create mode 100644 src/img/flags-of-the-world/tc.png create mode 100644 src/img/flags-of-the-world/td.png create mode 100644 src/img/flags-of-the-world/tf.png create mode 100644 src/img/flags-of-the-world/tg.png create mode 100644 src/img/flags-of-the-world/th.png create mode 100644 src/img/flags-of-the-world/tj.png create mode 100644 src/img/flags-of-the-world/tk.png create mode 100644 src/img/flags-of-the-world/tl.png create mode 100644 src/img/flags-of-the-world/tm.png create mode 100644 src/img/flags-of-the-world/tn.png create mode 100644 src/img/flags-of-the-world/to.png create mode 100644 src/img/flags-of-the-world/tr.png create mode 100644 src/img/flags-of-the-world/tt.png create mode 100644 src/img/flags-of-the-world/tv.png create mode 100644 src/img/flags-of-the-world/tw.png create mode 100644 src/img/flags-of-the-world/tz.png create mode 100644 src/img/flags-of-the-world/ua.png create mode 100644 src/img/flags-of-the-world/ug.png create mode 100644 src/img/flags-of-the-world/um.png create mode 100644 src/img/flags-of-the-world/us.png create mode 100644 src/img/flags-of-the-world/uy.png create mode 100644 src/img/flags-of-the-world/uz.png create mode 100644 src/img/flags-of-the-world/va.png create mode 100644 src/img/flags-of-the-world/vc.png create mode 100644 src/img/flags-of-the-world/ve.png create mode 100644 src/img/flags-of-the-world/vg.png create mode 100644 src/img/flags-of-the-world/vi.png create mode 100644 src/img/flags-of-the-world/vn.png create mode 100644 src/img/flags-of-the-world/vu.png create mode 100644 src/img/flags-of-the-world/wf.png create mode 100644 src/img/flags-of-the-world/ws.png create mode 100644 src/img/flags-of-the-world/xk.png create mode 100644 src/img/flags-of-the-world/ye.png create mode 100644 src/img/flags-of-the-world/yt.png create mode 100644 src/img/flags-of-the-world/za.png create mode 100644 src/img/flags-of-the-world/zm.png create mode 100644 src/img/flags-of-the-world/zw.png create mode 100644 src/img/fontawesome/LICENSE.txt create mode 100644 src/img/fontawesome/fontawesome-defs.svg create mode 100644 src/img/help16.png create mode 100644 src/img/icon_128.png create mode 100644 src/img/icon_16-loading.png create mode 100644 src/img/icon_16-off.png create mode 100644 src/img/icon_16.png create mode 100644 src/img/icon_32-loading.png create mode 100644 src/img/icon_32-off.png create mode 100644 src/img/icon_32.png create mode 100644 src/img/icon_64-loading.png create mode 100644 src/img/icon_64-off.png create mode 100644 src/img/icon_64.png create mode 100644 src/img/material-design.svg create mode 100644 src/img/photon.svg create mode 100644 src/img/ublock-defs.svg create mode 100644 src/img/ublock.svg create mode 100644 src/js/1p-filters.js create mode 100644 src/js/3p-filters.js create mode 100644 src/js/about.js create mode 100644 src/js/advanced-settings.js create mode 100644 src/js/asset-viewer.js create mode 100644 src/js/assets.js create mode 100644 src/js/background.js create mode 100644 src/js/base64-custom.js create mode 100644 src/js/benchmarks.js create mode 100644 src/js/biditrie.js create mode 100644 src/js/broadcast.js create mode 100644 src/js/cachestorage.js create mode 100644 src/js/click2load.js create mode 100644 src/js/cloud-ui.js create mode 100644 src/js/code-viewer.js create mode 100644 src/js/codemirror/search-thread.js create mode 100644 src/js/codemirror/search.js create mode 100644 src/js/codemirror/ubo-dynamic-filtering.js create mode 100644 src/js/codemirror/ubo-static-filtering.js create mode 100644 src/js/commands.js create mode 100644 src/js/console.js create mode 100644 src/js/contentscript-extra.js create mode 100644 src/js/contentscript.js create mode 100644 src/js/contextmenu.js create mode 100644 src/js/cosmetic-filtering.js create mode 100644 src/js/dashboard-common.js create mode 100644 src/js/dashboard.js create mode 100644 src/js/devtools.js create mode 100644 src/js/diff-updater.js create mode 100644 src/js/document-blocked.js create mode 100644 src/js/dom-inspector.js create mode 100644 src/js/dom.js create mode 100644 src/js/dyna-rules.js create mode 100644 src/js/dynamic-net-filtering.js create mode 100644 src/js/epicker-ui.js create mode 100644 src/js/fa-icons.js create mode 100644 src/js/filtering-context.js create mode 100644 src/js/filtering-engines.js create mode 100644 src/js/hnswitches.js create mode 100644 src/js/hntrie.js create mode 100644 src/js/html-filtering.js create mode 100644 src/js/httpheader-filtering.js create mode 100644 src/js/i18n.js create mode 100644 src/js/logger-ui-inspector.js create mode 100644 src/js/logger-ui.js create mode 100644 src/js/logger.js create mode 100644 src/js/lz4.js create mode 100644 src/js/messaging.js create mode 100644 src/js/mrucache.js create mode 100644 src/js/pagestore.js create mode 100644 src/js/popup-fenix.js create mode 100644 src/js/redirect-engine.js create mode 100644 src/js/redirect-resources.js create mode 100644 src/js/reverselookup-worker.js create mode 100644 src/js/reverselookup.js create mode 100644 src/js/scriptlet-filtering-core.js create mode 100644 src/js/scriptlet-filtering.js create mode 100644 src/js/scriptlets/cosmetic-logger.js create mode 100644 src/js/scriptlets/cosmetic-off.js create mode 100644 src/js/scriptlets/cosmetic-on.js create mode 100644 src/js/scriptlets/cosmetic-report.js create mode 100644 src/js/scriptlets/dom-inspector.js create mode 100644 src/js/scriptlets/dom-survey-elements.js create mode 100644 src/js/scriptlets/dom-survey-scripts.js create mode 100644 src/js/scriptlets/epicker.js create mode 100644 src/js/scriptlets/load-3p-css.js create mode 100644 src/js/scriptlets/load-large-media-all.js create mode 100644 src/js/scriptlets/load-large-media-interactive.js create mode 100644 src/js/scriptlets/noscript-spoof.js create mode 100644 src/js/scriptlets/should-inject-contentscript.js create mode 100644 src/js/scriptlets/subscriber.js create mode 100644 src/js/scriptlets/updater.js create mode 100644 src/js/settings.js create mode 100644 src/js/start.js create mode 100644 src/js/static-dnr-filtering.js create mode 100644 src/js/static-ext-filtering-db.js create mode 100644 src/js/static-ext-filtering.js create mode 100644 src/js/static-filtering-io.js create mode 100644 src/js/static-filtering-parser.js create mode 100644 src/js/static-net-filtering.js create mode 100644 src/js/storage.js create mode 100644 src/js/support.js create mode 100644 src/js/tab.js create mode 100644 src/js/tasks.js create mode 100644 src/js/text-encode.js create mode 100644 src/js/text-utils.js create mode 100644 src/js/theme.js create mode 100644 src/js/traffic.js create mode 100644 src/js/ublock.js create mode 100644 src/js/uri-utils.js create mode 100644 src/js/url-net-filtering.js create mode 100644 src/js/utils.js create mode 100644 src/js/wasm/README.md create mode 100644 src/js/wasm/biditrie.wasm create mode 100644 src/js/wasm/biditrie.wat create mode 100644 src/js/wasm/hntrie.wasm create mode 100644 src/js/wasm/hntrie.wat create mode 100644 src/js/whitelist.js create mode 100644 src/lib/codemirror/LICENSE create mode 100644 src/lib/codemirror/README.md create mode 100644 src/lib/codemirror/addon/comment/comment.js create mode 100644 src/lib/codemirror/addon/display/panel.js create mode 100644 src/lib/codemirror/addon/edit/closebrackets.js create mode 100644 src/lib/codemirror/addon/edit/matchbrackets.js create mode 100644 src/lib/codemirror/addon/fold/foldcode.js create mode 100644 src/lib/codemirror/addon/fold/foldgutter.css create mode 100644 src/lib/codemirror/addon/fold/foldgutter.js create mode 100644 src/lib/codemirror/addon/hint/show-hint.css create mode 100644 src/lib/codemirror/addon/hint/show-hint.js create mode 100644 src/lib/codemirror/addon/merge/merge.css create mode 100644 src/lib/codemirror/addon/merge/merge.js create mode 100644 src/lib/codemirror/addon/scroll/annotatescrollbar.js create mode 100644 src/lib/codemirror/addon/search/matchesonscrollbar.css create mode 100644 src/lib/codemirror/addon/search/searchcursor.js create mode 100644 src/lib/codemirror/addon/selection/active-line.js create mode 100644 src/lib/codemirror/lib/codemirror.css create mode 100644 src/lib/codemirror/lib/codemirror.js create mode 100644 src/lib/codemirror/mode/css/css.js create mode 100644 src/lib/codemirror/mode/htmlmixed/htmlmixed.js create mode 100644 src/lib/codemirror/mode/javascript/javascript.js create mode 100644 src/lib/codemirror/mode/xml/xml.js create mode 100644 src/lib/codemirror/theme/night.css create mode 100644 src/lib/csstree/LICENSE create mode 100644 src/lib/csstree/css-tree.js create mode 100644 src/lib/diff/README.md create mode 100644 src/lib/diff/swatinem_diff.js create mode 100644 src/lib/hsluv/LICENSE create mode 100644 src/lib/hsluv/README create mode 100644 src/lib/hsluv/hsluv-0.1.0.min.js create mode 100644 src/lib/js-beautify/LICENSE create mode 100644 src/lib/js-beautify/README create mode 100644 src/lib/js-beautify/beautifier.min.js create mode 100644 src/lib/lz4/README.md create mode 100644 src/lib/lz4/lz4-block-codec-any.js create mode 100644 src/lib/lz4/lz4-block-codec-js.js create mode 100644 src/lib/lz4/lz4-block-codec-wasm.js create mode 100644 src/lib/lz4/lz4-block-codec.wasm create mode 100644 src/lib/lz4/lz4-block-codec.wat create mode 100644 src/lib/publicsuffixlist/publicsuffixlist.js create mode 100644 src/lib/publicsuffixlist/wasm/README.md create mode 100644 src/lib/publicsuffixlist/wasm/publicsuffixlist.wasm create mode 100644 src/lib/publicsuffixlist/wasm/publicsuffixlist.wat create mode 100644 src/lib/punycode.js create mode 100644 src/lib/regexanalyzer/CHANGES.md create mode 100644 src/lib/regexanalyzer/README.md create mode 100644 src/lib/regexanalyzer/regex.js create mode 100644 src/logger-ui.html create mode 100644 src/no-dashboard.html create mode 100644 src/popup-fenix.html create mode 100644 src/settings.html create mode 100644 src/support.html create mode 100644 src/web_accessible_resources/1x1.gif create mode 100644 src/web_accessible_resources/2x2.png create mode 100644 src/web_accessible_resources/32x32.png create mode 100644 src/web_accessible_resources/3x2.png create mode 100644 src/web_accessible_resources/README.txt create mode 100644 src/web_accessible_resources/amazon_ads.js create mode 100644 src/web_accessible_resources/amazon_apstag.js create mode 100644 src/web_accessible_resources/ampproject_v0.js create mode 100644 src/web_accessible_resources/chartbeat.js create mode 100644 src/web_accessible_resources/click2load.html create mode 100644 src/web_accessible_resources/dom-inspector.html create mode 100644 src/web_accessible_resources/doubleclick_instream_ad_status.js create mode 100644 src/web_accessible_resources/empty create mode 100644 src/web_accessible_resources/epicker-ui.html create mode 100644 src/web_accessible_resources/fingerprint2.js create mode 100644 src/web_accessible_resources/fingerprint3.js create mode 100644 src/web_accessible_resources/google-analytics_analytics.js create mode 100644 src/web_accessible_resources/google-analytics_cx_api.js create mode 100644 src/web_accessible_resources/google-analytics_ga.js create mode 100644 src/web_accessible_resources/google-analytics_inpage_linkid.js create mode 100644 src/web_accessible_resources/google-ima.js create mode 100644 src/web_accessible_resources/googlesyndication_adsbygoogle.js create mode 100644 src/web_accessible_resources/googletagmanager_gtm.js create mode 100644 src/web_accessible_resources/googletagservices_gpt.js create mode 100644 src/web_accessible_resources/hd-main.js create mode 100644 src/web_accessible_resources/nobab.js create mode 100644 src/web_accessible_resources/nobab2.js create mode 100644 src/web_accessible_resources/noeval-silent.js create mode 100644 src/web_accessible_resources/noeval.js create mode 100644 src/web_accessible_resources/nofab.js create mode 100644 src/web_accessible_resources/noop-0.1s.mp3 create mode 100644 src/web_accessible_resources/noop-0.5s.mp3 create mode 100644 src/web_accessible_resources/noop-1s.mp4 create mode 100644 src/web_accessible_resources/noop-vmap1.0.xml create mode 100644 src/web_accessible_resources/noop.css create mode 100644 src/web_accessible_resources/noop.html create mode 100644 src/web_accessible_resources/noop.js create mode 100644 src/web_accessible_resources/noop.json create mode 100644 src/web_accessible_resources/noop.txt create mode 100644 src/web_accessible_resources/outbrain-widget.js create mode 100644 src/web_accessible_resources/popads-dummy.js create mode 100644 src/web_accessible_resources/popads.js create mode 100644 src/web_accessible_resources/prebid-ads.js create mode 100644 src/web_accessible_resources/scorecardresearch_beacon.js create mode 100644 src/whitelist.html (limited to 'src') diff --git a/src/1p-filters.html b/src/1p-filters.html new file mode 100644 index 0000000..bafa992 --- /dev/null +++ b/src/1p-filters.html @@ -0,0 +1,68 @@ + + + + + +uBlock — Your filters + + + + + + + + + + + + + + + + +
+
+ +

question-circle

+

+ + +   + + +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/3p-filters.html b/src/3p-filters.html new file mode 100644 index 0000000..a779120 --- /dev/null +++ b/src/3p-filters.html @@ -0,0 +1,117 @@ + + + + + +uBlock — Filter lists + + + + + + + + + + +
+ +
+
+ + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + +
+ +
+ +
+ + + + + + + + + + + + + + + + + diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json new file mode 100644 index 0000000..be9af18 --- /dev/null +++ b/src/_locales/ar/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "يو بلوك أوريجين", + "description": "extension name." + }, + "extShortDesc": { + "message": "وأخيراً, مانع اعلانات كفوء. خفيف على المعالج و الذاكرة.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — لوحة التحكم", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "تنبيه! لديك تغييرات لم تقم بحفظها", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "إبقى", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "تجاهل", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "الإعدادات", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "قوائم الفلاتر", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "الفلاتر الخاصة بي", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "القواعد الخاصة بي", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "المواقع الموثوقة", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "الاختصارات", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "\"uBlock₀\" — سجل الإتصال بالشبكة", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "حول البرنامج", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "الدعم", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — مُعاين العناصر", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "الإعدادات المتقدمة", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "اضغط: لتعطيل/تشغيل ميكروبلوك لهذا الموقع.\n\nCtrl+click لتعطيل ميكروبلوك لهذه الصفحة فقط.", + "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₀ لهذه الصفحة فقط.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "اضغط لتفعيل uBlock₀ لهذا الموقع.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "تم منع الطلبات", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "على هذه الصفحة", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} أو {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "منذ التنصيب", + "description": "English: since install" + }, + "popupOr": { + "message": "أو", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "محجوب من هذه الصفحة", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "حُجِب منذ التنصيب", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "النطاقات المتصلة", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "إضغط لفتح لوحة التحكم", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "دخول وضع تحديد العناصر السريع", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "دخول وضع تحديد العناصر", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "إفتح سجل طلبات الشبكة", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "التقرير عن مُشكلة في الموقع", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "تفعيل أو تعطيل النوافذ منبثقة لهذا الموقع", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "اضغط لحجب جميع النوافذ المنبثقة لهذا الموقع", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "أضغط للوقف منع جميع النوافذ المنبثقة لهذا الموقع", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "تفعيل أو تعطيل حجب عناصر الوسائط الكبيرة لهذا الموقع", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "اضغط لحجب عناصر الوسائط الكبيرة لهذا الموقع", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "أضغط للوقف منع عناصر الوسائط الكبيرة لهذا الموقع", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "تفعيل أو تعطيل الفلترة التجميلية لهذا الموقع", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "اضغط لتعطيل الفلترة التجميلية لهذا الموقع", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "اضغط لتشغيل الفلترة التجميلية لهذا الموقع", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "تفعيل أو تعطيل حجب الخطوط الخارجية لهذا الموقع", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "أضغط لحجب الخطوط الخارجية لهذا الموقع", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "أضغط للسماح للخطوط الخارجية لهذا الموقع", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "انقر لتعطيل الجافا سكريبت على هذا الموقع", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "انقر لإلغاء تعطيل الجافا سكريبت على هذا الموقع", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "الإطارات المنبثقة", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "عناصر وسائط كبيرة", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "إعادات الفلاتر التجميلية العمومية", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "الخطوط الخارجية", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "جافا سكريبت", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "المزيد", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "أقل", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "القواعد العامة: هذا العمود يتعلق بالقواعد التي تنطبق على جميع الموقع.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "القواعد الموضعية: هذا العمود يتعلق بالقواعد التي تنطبق فقط على الموقع المزار حاليا.\nالقواعد الموضعية تحل محل القواعد العامة.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "إضغط لحفظ التغييرات بشكل دائم.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "إضغط لإعادة التغييرات للوضع السابق.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "الكل", + "description": "" + }, + "popupImageRulePrompt": { + "message": "الصور", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "جهة خارجية", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "كود CSS/صورة من مصدر خارجي", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "نصوص برمجة بين السطور", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "سكربتات من الطرف الاول", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "سكربتات من طرف خارجي", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "إطارات من طرف خارجي", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "النطاقات المتصلة", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} من {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "نسخة", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "سكربت", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "إطار", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "إنشاء", + "description": "English: Create" + }, + "pickerPick": { + "message": "اختار", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "خروج", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "معاينة", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "فلاتر الشبكة", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "فلاتر تجميلية", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "إضغط، إضغط مع Ctrl", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "إحجب العنصر...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "اخفاء مكان العناصر المحجوبه", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "عرض عدد طلبات المحضوره على الايقونه", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "تعطيل التلميحات", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "إستخدم لائحة السياق في المكان المناسب", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "وضع عمى الألوان", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "مظهر", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "المظاهر", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "لون التمييز المخصص", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "تفعيل دعم سحابة التخزين", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "أنا مستخدم ذو خبرة (قراءة إجبارية)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "تعطيل الجلب المسبق على الشبكة (لمنع أي اتصال لطلبات الشبكة المحجوبة)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "تعطيل مراجعة الروابط التشعبية", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "منع WebRTC من كشف عنوان الـ IP المحلي", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "السلوك الإفتراضي", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "هذه السلوكيات الإفتراضية يمكن إستبدالها في كل حالة", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "تعطيل الفلترة التجميلية", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "احجب عناصر الوسائط الأكبر من {{input}} كيلو بايت", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "منع الخطوط البعيدة", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "تعطيل الجافا سكريبت", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "حظر تقارير الـ CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "فك الأسماء المتعارف عليها", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "متقدم", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "ميزات مناسبة فقط للمستخدمين التقنيين", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "الإعدادات المتقدمة", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "آخر إسترجاع:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "آخر نسخ إحتياطي:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} من فلاتر الشبكه + {{cosmeticFilterCount}} فلاتر تجميليه:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} تم استعماله من {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "تحديث تلقائي للستات الفلاتر", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "حدث الان", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "نظف جميع المخابئ", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "تحليل وتطبيق فلاتر التجميليه", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "الفلاتر التجميلية تعمل لإزالة العناصر في صفحة الويب التي تعتبر إزعاج بصريًا و تلك التي لا يمكن حجبها عن طريق محركات التصفية القائمة على طلبات الشبكة.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "تجاهل الفلاتر التجميلية العامة", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "الفلاتر التجميلية العمومية هي الفلاتر التجميلية التي تنطبق على كل مواقع الإنترنت. تفعيل هذا الخيار سوف يترك مساحة أقل من الذاكرة و قوة المعالجة للإستعمال من قبل صفحات الويب كنتيجة لمعالجة الفلاتر التجميلية العمومية.\n\nمن الأفضل تفعيل هذا الخيار على الأجهزة الأقل قوة.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "تعليق نشاط الشبكة حتى يتم تحميل كافة قوائم عوامل التصفية", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "قائمة المواقع المحجوبة", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "حفظ التغيرات", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "مدمج", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "اعلانات", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "خصوصيه", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "مواقع مصابة أو تحتوي على فايروسات", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "عناصر مزعجة", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "متعددة الأغراض", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "المناطق واللغات", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "مخصصه", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "إسترجاع...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "رابط واحد في كل سطر. الروابط الغير الصحيحة سوف يتم تجاهلها بصمت.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "متقادم.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "اظهر المحتوى", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "آخر تحديث: {{ago}}. \nانقر لفرض التحديث.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "جار التحديث...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "حدث خطأ في الشبكة منع تحديث المورد.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "فلتر واحد في كل سطر. يمكن ان يكون الفلتر رابط موقع او فلتر متوافق مع EasyList-compatible. السطور المسبوقة بـ! سوف يتم تجاهلها.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "لا تضف مرشحات من مصادر غير موثوقة.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "استيراد و إضافة", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "تصدير", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "حفظ التغيرات", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "قواعد دائمة", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "قواعد مؤقتة", + "description": "header" + }, + "rulesRevert": { + "message": "إلغاء", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "تطبق", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "تعديل", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "حفظ", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "إلغاء", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "الاستيراد من ملف...", + "description": "" + }, + "rulesExport": { + "message": "تصدير إلى ملف", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "قائمة قواعد الفلترات الديناميكية الخاصة بك.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "صياغة القواعد: مصدر نوع وجهة العمل (تعليمات كاملة).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "الفرز:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "نوع القاعدة", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "المصدر", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "الوجهة", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "تحدد توجيهات الموقع الموثوق به صفحات الويب التي يجب تعطيل uBlock Origin عليها.\nأدخل رابط واحد كل سطر. ", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "استيراد و إضافة", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "تصدير", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "حفظ التغيرات", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "النوع", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "الموقع", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "رابط الموقع", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "فلتر", + "description": "English: Filter" + }, + "logAll": { + "message": "كل", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "بلا تبويب", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "علامة التبويب الحالية", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "إعادة تحميل محتوى علامة التبويب", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "تفعيل أو تعطيل مراقب DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "تفعيل أو تعطيل اللوحة المنبثقة", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "ويكي يو بلوك أوريجين: حافظ السجلات", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "امسح السجلات", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "ايقاف التسجيل مؤقتا (استبعاد كل البيانات الواردة) ", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "استىئناف حافظ السجلات", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "تبديل ترشيح بيانات التسجيل ", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "رشّح محتوى السجل", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "خيارات التصفية للمسجّل", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "ليس", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "محظور", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "مسموح", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "معدّل", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "أول طرف ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "ثالث-طرف ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "تفاصيل", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "فلتر", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "قائمة الفلتر", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "قاعدة", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "السياق", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "سياق الجدر", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "عديمة الطرف", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "النوع", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "قاعدة URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "حالة:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "نوع:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "فلتر ثابت", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} طلبات شبكة {{type}} {{br}}اللتي تحتوي عنوان الرابط {{url}} {{br}}من المصدر {{origin}},{{br}}{{importance}} هناك فلتر استثناء مطابق.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "حجب", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "سماح", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "نوع “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "أي نوع", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "من “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "من أي مكان", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "باستثناء إذا", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "حتى لو", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "فلتر ثابت {{filter}} موجود في:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "الفلتر الثابت لا يوجد في أي من قوائم الفلاتر المفعلة", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "مدخلات السجل التي لا تطابق أيا من المعايير ستحذف تلقائيا:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "أبق على المدخلات في آخر {{input}} دقيقة", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "أبقِ بحد أقصى على {{input}} تحميلات للصفحة في كل لسان", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "أبق بحد أقصى على {{input}} مدخلات في كل تبويبة", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "استخدم {{input}} من السطور لكل مدخلة في الوضع الرأسي", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "أخفِ الأعمدة:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} الوقت", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} المرشِّح\\القاعدة", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} السياق", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} الجهة", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "قائمة", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "جدول", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "واضح", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "افتح", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "إنشاء تقرير جديد", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "العثور على تقارير مماثلة", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "وثائق", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "اقرأ الوثائق على uBlock/wiki للتعرف على جميع ميزات يو بلوك أوريجين.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "الأسئلة والدعم", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "يتم توفير إجابات للأسئلة وأنواع أخرى من دعم المساعدة على subreddit /r/uBlockOrigin", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "تصفية المسائل/موقع الويب معطل", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "الإبلاغ عن مشكلات التصفية في مواقع ويب محددة لـ uBlockOrigin/uAssets أداة تعقب المشكلات. يتطلب حساب GitHub..", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "هام: تجنب استخدام أدوات الحظر الأخرى ذات الغرض المشابه مع يو بلوك أوريجين، حيث قد يتسبب ذلك في حدوث مشكلات في التصفية على مواقع ويب معينة.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "نصائح: تأكد من تحديث قوائم التصفية. المُسجِّل هو الأداة الأساسية لتشخيص المشكلات المتعلقة بالفلتر", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "تقرير الأخطاء", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "الإبلاغ عن المشكلات المتعلقة بيو بلوك أوريجين نفسه إلى uBlockOrigin/uBlock-issue أداة تعقب المشكلات. يتطلب حساب GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "رأس قسم \"معلومات استكشاف الأخطاء وإصلاحها\" في جزء الدعم", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "فيما يلي معلومات فنية قد تكون مفيدة عندما يحاول المتطوعون مساعدتك في حل مشكلة ما.فيما يلي معلومات فنية قد تكون مفيدة عندما يحاول المتطوعون مساعدتك في حل مشكلة ما.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "هام: يتم تنقيح المعلومات التي يُحتمل أن تكون خاصة أو حساسة بشكل افتراضي. المعلومات المنقحة قد تجعل حل مشكلة ما أكثر صعوبة.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "الإبلاغ عن مشكلة في عوامل التصفية", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "لتجنب إثقال كاهل المتطوعين بتقارير مكررة، يرجى التحقق من عدم الإبلاغ عن المشكلة بالفعل.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "يتم تحديث قوائم الفلتر بشكل يومي. تحقق أن مشكلتك لم يتم مواجهتها في أحدث قوائم الفلتر", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "تحقق من أن المشكلة ما تزال موجودة بعد إعادة تحميل صفحة الويب التي بها إشكالية.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "عنوان صفحة الويب:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "صفحة الويب...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- إختر خيارًا --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "ٌيُظهر الإعلانات أو بقايا الإعلانات", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "به تراكبات أو مضايقات أخرى", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "يكتشف يو بلوك أوريجين", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "لديه مشاكل متعلقة بالخصوصية", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "الأعطال عند تمكين يو بلوك أوريجين", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "افتح التبويبات أو النوافذ التي ليس مرغوبًا بها", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "تسمية صفحة الويب باسم \"NSFW\" (\"ليس آمن للعمل\"\n", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "تنقيح", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "غير منقح", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "سياسة الخصوصية", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "سجل التغييرات", + "description": "" + }, + "aboutCode": { + "message": "اكواد البرنامج (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "المساهمين", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "شيفرة المصدر", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "الترجمات", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "القوائم المرشحة", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "الإعتماديات الخارجية (متوافقة مع GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "يتم استضافة قوائم عوامل التصفية الخاصة بـ uBO بحرية على ما يلي CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "يتم استخدام CDN الذي تم اختياره عشوائيًا عند الحاجة إلى تحديث قائمة عوامل التصفية", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "النسخ الإحتياطي إلى ملف", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "إحتياط-ublock-الخاص-بي_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "إسترجع من الملف...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "إعادة الضبط للوضع الافتراضي...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "كل إعداداتك سوف يتم كتابتها بإستعمال البيانات التي تم نسخها إحتياطيا على {{time}}، و سيعيد uBlock₀ التشغيل.\n\nأعد كتابة كل الإعدادات الموجود بإستخدام البيانات التي تم نسخها إحتياطيا؟", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "تعذر قراءة البيانات أو إنها غير صالحة", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "كل إعداداتك سيتم إلغائها، و سيتم إعادة تشغيل \"uBlock₀\".\n\n\nإعادة ضبط \"uBlock₀\" على الإعدادات الأصلية؟", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "خطأ في الشبكة: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "µBlock : أضف الرابط التالي لقائمة الفلترة الخاصة بك؟\n\nعنوان : \"{{title}}\"\nرابط : {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "اشترك", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "منذ دقيقة", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "منذ {{value}} دقائق", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "منذ ساعة", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "منذ {{value}} ساعات", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "قبل يوم واحد", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "منذ {{value}} أيام", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "عرض لوحة التحكم", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "عرض سجل الإتصال بالشبكة", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "تعطيل", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "الصفحة محجوبة", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ منع الصفحة التالية من التحميل:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "بسبب الفلتر التالي", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "موجود في:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "العودة للخلف", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "أغلق هذه النافذة", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "لا تحذرني لهذا الموقع مرة أخرى", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "تعطيل الحجب الصارم على {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "مؤقتا", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "بشكل دائم", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "تقدّم", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "التصدير إلى سحابة التخزين", + "description": "tooltip" + }, + "cloudPull": { + "message": "إستيراد من سحابة التخزين", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "إستيراد التخزين من السحابية و دمجه مع الإعدادات الحالية", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "إسم هذا الجهاز:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "تحذير! تغيير هذه الإعدادات المتقدمة يكون على مسؤوليتك.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "تطبيق", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "حفظ التغييرات", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "إلغاء", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "بايت", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "احظر العنصر في البرواز...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "اشترك في قائمة التصفية ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "السماح مؤقتا لعناصر الوسائط كبيرة", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "عرض المصدر…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "ادخل اختصار", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "بدل حالة التمرير الموصَد", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "نسخ إلى الحافظة", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "اختر الكل", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "تبديل تصفية مستحضرات التجميل", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "وضع الحظر المتراخي", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "مساحة التخزين المستخدمة: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "كيلو بايت", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "ميغا بايت", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "جيغا بايت", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "اضغط للتحميل", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "أخطاء: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "لا يمكن الفلترة بشكل صحيح عند تشغيل المتصفح.\nقم بتحديث الصفحة للتأكد من الفلترة بشكل صحيح.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "يجب أن يكون هذا الإدخال آخر واحد", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/az/messages.json b/src/_locales/az/messages.json new file mode 100644 index 0000000..e712582 --- /dev/null +++ b/src/_locales/az/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Axır ki, prosessor və yaddaş yükünü azaldan səmərəli bir əngəlləyici var.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — İdarəetmə paneli", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "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", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Əhəmiyyət vermə", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Tənzimləmələr", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtr siyahıları", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Filtrlərim", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Qaydalarım", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Etibarlı saytlar", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Qısayollar", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Jurnal", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Haqqında", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Dəstək", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Resurslar", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Qabaqcıl tənzimləmələr", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Bu saytda uBlock₀-u fəallaşdırmaq üçün klikləyin.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "tələb(request) bloklandı", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "bu səhifədə", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} və ya {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "quraşdırmadan bəri", + "description": "English: since install" + }, + "popupOr": { + "message": "və ya", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bu səhifədə əngəllənən", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Quraşdırmadan bəri əngəllənən", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Bağlantı qurulmuş domenlər", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "İdarəetmə panelini aç", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Element silmə rejiminə keç", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Element seçmə rejiminə keç", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Jurnalı aç", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Bu veb-saytdakı problemi bildir", + "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", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Bu saytda bütün açılan pəncərələri əngəlləmək üçün kliklə", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Bu saytdakı bütün açılan pəncələri artıq əngəlləməmək üçün kliklə", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Bu saytda böyük media elemetlərini əngəlləməyi aç/bağla", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Bu saytda böyük media elementlərini əngəlləmək üçün düyməyə basın", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Bu saytda böyük media elementlərini daha əngəlləməmək üçün düyməyə basın", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Bu saytda kosmetik filtrləri qoş/söndür", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Bu saytda kosmetik filtrləri söndürmək üçün düyməyə basın", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Bu saytda kosmetik filtrləri qoşmaq üçün düyməyə basın", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Bu saytda uzaqdan idarə olunan şriftləri qoş/söndür", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Bu saytda uzaqdan idarə olunan şriftləri əngəlləmək üçün düyməyə basın", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Bu saytda uzaqdan idarə olunan şriftləri daha əngəlləməmək üçün düyməyə basın", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Bu saytda JavaScript-i sıradan çıxartmaq üçün kliklə", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Bu saytda JavaScript-i artıq əngəlləməmək üçün düyməyə basın", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Peyda olan pəncərələr", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Böyük ölçülü media elementləri", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetik filtrləmə", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Kənar şriftlər", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Daha çox", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Daha az", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Qlobal qaydalar: bu sütun bütün saytlarda tətbiq olunan qaydalar üçündür.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Dəyişiklikləri daimi etmək üçün klikləyin.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Dəyişiklikləri geri qaytarmaq üçün düyməyə basın.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "hamısı", + "description": "" + }, + "popupImageRulePrompt": { + "message": "təsvirlər", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3-cü tərəf", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3-cü tərəf CSS/təsvirlər", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "sətiriçi skriptlər", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1-ci tərəf skriptlər", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3-cü tərəf skriptlər", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3-cü tərəf frame-lər", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "qoşulmuş domen", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} / {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versiya", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "çərçivə", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Yarat", + "description": "English: Create" + }, + "pickerPick": { + "message": "Seç", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Çıxış", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Önbaxış", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Şəbəkə filtrləri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetik filtrlər", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Elementi əngəllə...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Əngəllənmiş elementlərin tutduğu yeri gizlə", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Əngəllənən tələb sayını nişan üstündə göstər", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Alət izahlarını söndür", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Uyğun olduqda kontekst menüsündən istifadə et", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Rəng seçmə qabiliyyəti olmayanlar üçün rəngləmə rejimi", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Görünüş", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Mövzu", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Xüsusi vurğu rəngi", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Bulud yaddaşı dəstəyini işə sal", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Mən təcrübəli istifadəçiyəm (mütləq oxuyun)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Erkən yükləməni dayandır (əngəllənmiş şəbəkə sorğuları üzrə qoşulmalara yol verməmək üçün)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Hiperkeçidlərin yoxlanılmasını dayandır", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Lokal IP-ünvanların WebRTC vasitəsilə sızmasını əngəllə", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standart davranış", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Bu standart parametrlər hər bir sayt üçün ayrıca qeyd oluna bilər", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Kosmetik filtrləri söndür", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input}} KB-dan artıq olan media elementlərini əngəllə", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Uzaqdan idarə olunan şriftləri əngəllə", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript-i Əngəllə", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP hesabatlarını əngəllə", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Canonical adları ortaya çıxarın", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Təkmil", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Yalnız texniki istifadəçilərə uyğun parametrlər", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "əlavə parametrlər", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Son bərpa əməliyyatının tarixi:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Son ehtiyat nüsxəsinin tarixi:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} şəbəkə filtri + {{cosmeticFilterCount}} kosmetik filtr:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} ədəddən {{used}} ədədi istifadə olundu", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Filtr siyahılarını avtomatik yenilə", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Yenilə", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Bütün keşləri sil", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Kosmetik filtrləri təhlil və tətbiq et", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetik filtrlər bir veb səhifəsində görüntü rahatsızlığına səbəb olan və şəbəkə sorğularının filtrlənməsi vasitəsilə əngəllənə bilməyən elementləri gizlətmək üçün istifadə olunur.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ümumi kosmetik filtrləri nəzərə alma", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Ümumi kosmetik filtrlərin bütün veb-saytlarda istifadəsi nəzərdə tutulur. Bu seçimi etdiyiniz təqdirdə veb-səhifələrdə ümumi kosmetik filtrlərin işlənməsi ilə əlaqədar yaddaşdan istifadə və prosessor yükü azalacaq.\n\nAz güclü cihazlarda bu seçimin aktivləşdirilməsi tövsiyə olunur.", + "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", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Dəyişiklikləri tətbiq et", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Lokal filtrlər", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklam", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Məxfilik", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Zərərli domenlər", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Zəhlətökən elementlər əleyhinə filtrlər", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Çoxməqsədli filtrlər", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Bölgələr, dillər", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Fərdi", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Əlavə et...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Hər sətrdə yalnız bir URL. Yanlış URL-lər xəbərdarlıq edilmədən nəzərə alınmayacaq.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Köhnəlmişdir.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "məzmunu nəzərdən keçir", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Sonuncu yeniləmə: {{ago}}.\nYeniləmək üçün düyməyə basın.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Yenilənir...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Şəbəkə xətası üzündən yeniləmə mümkün olmadı.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Hər sətirdə yalnız bir filtr. Bu, ya domen adı, ya da Adblock Plus formatında yazılmış filtr ola bilər. Əvvəli ! ilə başlayan sətirlər nəzərə alınmayacaqdır.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Etibarsız mənbələrdən filtrlər əlavə etməyin.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "İdxal və əlavə et", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "İxrac et", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Dəyişiklikləri tətbiq et", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Daimi qaydalar", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Müvəqqəti qaydalar", + "description": "header" + }, + "rulesRevert": { + "message": "Geri qaytar", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Təsdiq et", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Redaktə", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Yadda saxla", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Nəzərə alma", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Fayldan götür...", + "description": "" + }, + "rulesExport": { + "message": "Fayla yaz", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Dinamik filtr qaydalarınızın siyahısı.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Qaydalar sintaksisi: mənbə təyinat növ əməliyyat (bütün sənədlər).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sırala:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Qayda növü", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Mənbə", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Hədəf", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "İstisnalar siyahısındakı təlimatlar uBlock Origin-in hansı veb-səhifələrdə işləyişinin dayandırılmasını təmin edir. Hər sətirdə yalnız bir təlimat ola bilər. Yanlış təlimatlar xəbərdarlıq edilmədən nəzərə alınmayacaq və şərhə çeviriləcəkdir.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "İdxal və əlavə et", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "İxrac et", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Dəyişiklikləri tətbiq et", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Növü", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domen", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtr", + "description": "English: Filter" + }, + "logAll": { + "message": "Hamısı", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabsız", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Cari tab vərəqi", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Tab vərəqinin məzmununu yenidən yüklə", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM müfəttişini işə sal/söndür", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Peyda olan paneli aç/bağla", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin viki: Logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Loggeri təmizlə", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Loggeri dayandır (daxil olan bütün məlumatları rədd et)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Loggeri yenidən işə sal", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Logger filtrləməsini işə sal/dayandır", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "logger qeydlərinin filtrlənməsi", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger üçün filtrləmə parametrləri", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Deyil", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "əngəllənmiş", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "icazə verilmiş", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "dəyişdirildi", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1-ci tərəf resurslar", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3-cü tərəf resurslar", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Təfsilatlar", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtr", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filtr siyahısı", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Qayda", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Məzmun", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Ana məzmun", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Tərəf", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Növü", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL qaydası", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Məzmun:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Növ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statik filtr", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "Müvafiq istisna filtri varsa {{importance}},{{br}}URL ünvanı {{url}} {{br}}ilə eyni olan və mənbəyi {{origin}} {{br}}olan {{type}} növlü şəbəkə sorğularını {{action}}.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Əngəllə", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "İcazə ver", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "“{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "istənilən növ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "istənilən yerdən", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "halından savayı", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "əgər hətta", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "{{filter}} statik filtrinin mənbəyi:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statik filtr hal-hazırda aktiv olan filtr siyahılarının heç birində tapılmadı", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Üç şərtin hamısına cavab erməyən aşağıdakı logger qeydləri avtomatik olaraq rədd ediləcək:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Son {{input}} dəq. ərzində edilmiş qeydləri saxla", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Hər tab vərəqi üzrə ən çox {{input}} səh. yükləməsini saxla", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Hər tab vərəqi üzrə ən çox {{input}} qeyd saxla", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Şaquli genişləndirilmiş rejimdə hər qeyd üçün {{input}} sətir istifadə et", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sütunları gizlə:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Vaxt", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtr/Qayda", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Məzmun", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Tərəf", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Siyahı", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Cədvəl", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Sadə", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Nişanlı", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Aç", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Yeni hesabat yaradın", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Oxşar hesabat tap", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentasiya", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "UBlock Origin-in bütün xüsusiyyətlərini öyrənmək üçün uBlock/wiki ünvanında sənədləri oxuyun.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Suallar və dəstək", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Suallara və yardım dəstəyinin digər növlərinə cavablar /r/uBlock Origin - də təqdim olunur.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter problemləri / vebsəhifə işləmir", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Müəyyən vebsaytların filtr problemlərini uBlockOrigin/uAssets problem izləyicisinə bildirin. GitHub hesabı tələb edir.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Vacib: uBlock Origin-lə yanaşı, oxşar bloklayıcı genişləndirmələrin istifadəsindən çəkinin. Əks halda bəzi veb-saytlarda filtr problemləri ilə üzləşə bilərsiniz.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "İpuçları: Filtr siyahınızın yenilənmiş olduğundan əmin olun. Qeydiyyatçı, filtrlərlə bağlı problemləri müəyyənləşdirmək üçün başlıca vasitədir.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Xəta bildirişi", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlock Origin-lə bağlı problemləri uBlockOrigin/uBlock-issue problem izləyicisinə bildirin. Github hesabı tələb edir.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Problemlərin Həlli", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Vacib: Gizli və həssas ola biləcək məlumatlar defolt olaraq qısaldılır. Qısaldılmış məlumatlar, bir problemi aradan qaldırmağı çətinləşdirə bilər.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Filter problemini bildir", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Könüllülərə eyni hesabatların narahatçılıq verməməsi üçün, xahiş olunur problemin əvvəlcədən bildirilmədiyinə əmin olun.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filtr siyahıları hər gün yenilənir. Probleminizin ən son filtr siyahılarında həll edilmədiyinə əmin olun.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Problemli veb-səhifəni yenidən yüklədikdən sonra problemin hələ də qaldığından əmin olun.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Veb-səhifənin ünvanı:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Səhifə...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Bir daxiletmə seçin --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Reklam və ya reklam qalıqları göstərir", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Üst-üstə düşmə və ya digər nasazlıqları var", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin-i aşkarlayır", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Məxfiliklə bağlı problemləri var", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin aktiv ikən xarab olur", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Arzuolunmaz tab-vərəqələr və ya pəncərələr açır", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Veb-səhifəni uyğun olmayan (“NSFW”) olaraq işarələ (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Məxfilik siyasəti", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Dəyişikliklər siyahısı", + "description": "" + }, + "aboutCode": { + "message": "Mənbə kodu (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Layihəyə töhfə verənlər", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Mənbə kodu", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tərcümələr", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filtr siyahıları", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Xarici asılılıqlar (GPLv3-uyumlu):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO-nun öz filtr siyahıları ödənişsiz şəkildə bu CDN-lərdə yerləşdirilib:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Bir filtr siyahısının yenilənməsi lazım olduqda təsadüfi seçilən bir CDN istifadə olunur", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Fayla yaz", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Fayldan bərpa et...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Standart parametrləri yüklə...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Bütün parametrləriniz {{time}} tarixində yadda saxlanılmış məlumatlarla əvəz olunacaq və uBlock₀ yenidən başladılacaq.\n\nBütün cari parametrlər ehtiyat nüsxəsindəki məlumatlarla əvəz olunsun?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Məlumat oxunmur yaxud xətalıdır", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Bütün parametrləriniz silinəcək və uBlock₀ yenidən başladılacaq.\n\nuBlock₀ standart parametrlərə qaytarılsın?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Şəbəkə xətası: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Aşağıdakı URL ünvanı fərdi filtr siyahılarınıza əlavə edilsin?\n\nAdı: \"{{title}}\"\nURL ünvanı: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abunə ol", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "bir dəqiqə əvvəl", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} dəq. əvvəl", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "bir saat əvvəl", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} saat əvvəl", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "bir gün əvvəl", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} gün əvvəl", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "İdarəetmə panelini göstər", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Loggeri göstər", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "işləmir", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Səhifə əngəlləndi", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin bu səhifənin yüklənməsini əngəllədi:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Bu filtrə görə", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "parametrsiz", + "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": "Mənbə:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Geriyə qayıt", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Bu pəncərəni bağla", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Bu sayt barədə məni xəbərdar etmə", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}} üçün sərt əngəlləməni dayandır", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Müvəqqəti", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Daimi", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Davam et", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Bulud yaddaşa göndər", + "description": "tooltip" + }, + "cloudPull": { + "message": "Bulud yaddaşdan götür", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Bulud yaddaşdan götür və cari parametrlərlə birləşdir", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Bu cihazın adı:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Diqqət! Bu əlavə parametrlərdəki dəyişikliklərə görə siz məsuliyyət daşıyırsınız.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Təsdiqlə", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Dəyişiklikləri tətbiq et", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Geri qaytar", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bayt", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "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", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Böyük media elementlərinin yüklənməsinə müvəqqəti icazə ver", + "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...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Qısayol yaz", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Məhdud sürüşdürməni işə sal/dayandır", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Lövhəyə kopyala", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Hamısını seç", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kozmetik filtrləməni yandır/söndür", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Əngəlləmə rejimini yüngülləşdir", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "İstifadə olunan anbar: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Yükləmək üçün düyməyə bas", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Xətalar: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Brauzer açılışında filtrləmə düzgün alınmadı. Düzgün filtrləməni təmin etmək üçün səhifəni yenidən yükləyin.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/be/messages.json b/src/_locales/be/messages.json new file mode 100644 index 0000000..52ee835 --- /dev/null +++ b/src/_locales/be/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Нарэшце, эфектыўны блакавальнік. Не нагружае працэсар і памяць.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Панэль кіравання", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Увага! Ёсць незахаваныя змены", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Застацца", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Iгнараваць", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Налады", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Спісы фільтраў", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Мае фільтры", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Мае правілы", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Давераныя сайты", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Спалучэнні клавіш", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Журнал сеткавых запытаў", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Пра пашырэнне", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Падтрымка", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Прагляд рэсурсаў", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Пашыраныя налады", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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\nНацісніце з Ctrl, каб адключыць uBlock₀ толькі на гэтай старонцы.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Націсніце, каб уключыць uBlock₀ для гэтага сайта.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "запытаў заблакавана", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на гэтай старонцы", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "з моманту ўсталявання", + "description": "English: since install" + }, + "popupOr": { + "message": "або", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Заблакавана на гэтай старонцы", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Заблакавана з моманту ўсталявання", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Даменаў падлучана", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Адкрыць панэль кіравання", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Перайсці ў рэжым імгненнага хавання элементаў", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Перайсці ў рэжым выбару элементаў", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Адкрыць журнал запытаў", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Паведаміць аб праблеме з сайтам", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Пераключыць блакаванне ўсіх выплыўных акон на гэтым сайце", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Націсніце, каб блакаваць усе выплыўныя вокны на гэтым сайце", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Націсніце, каб выключыць блакаванне ўсіх выплыўных акон на гэтым сайце", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Пераключыць блакаванне вялікіх медыя-элементаў на гэтым сайце", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Націсніце, каб блакаваць вялікія медыя-элементы на гэтым сайце", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Націсніце, каб выключыць блакаванне вялікіх медыя-элементаў на гэтым сайце", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Пераключыць касметычнае фільтраванне на гэтым сайце", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Націсніце, каб выключыць касметычнае фільтраванне на гэтым сайце", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Націсніце, каб уключыць касметычнае фільтраванне на гэтым сайце", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Пераключыць блакаванне аддаленых шрыфтоў на гэтым сайце", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Націсніце, каб блакаваць аддаленыя шрыфты на гэтым сайце", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Націсніце, каб выключыць блакаванне аддаленых шрыфтоў на гэтым сайце", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Націсніце, каб выключыць JavaScript на гэтым сайце", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Націсніце, каб JavaScript не быў выключаны на гэтым сайце", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Выплыўныя вокны", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Вялікія медыя-элементы", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Касметычнае фільтраванне", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Аддаленыя шрыфты", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Больш", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Менш", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Глабальныя правілы: гэты слупок для правіл, якія прымяняюцца на ўсіх сайтах.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Лакальныя правілы: гэты слупок для правіл, якія прымяняюцца толькі на гэтым сайце.\nЛакальныя правілы перавызначаюць глабальныя.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Націсніце, каб захаваць змены.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Націсніце, каб скасаваць змены.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "усе", + "description": "" + }, + "popupImageRulePrompt": { + "message": "відарысы", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "староннія", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "староннія CSS/відарысы", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "убудаваныя скрыпты", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "уласныя скрыпты", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "староннія скрыпты", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "староннія рамкі", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "даменаў падлучана", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} з {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Версія", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "скрыпт", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "рамка", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Стварыць", + "description": "English: Create" + }, + "pickerPick": { + "message": "Выбраць", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Выйсці", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Папярэдні прагляд", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Сеткавыя фільтры", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Касметычныя фільтры", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Клік, Ctrl-клік", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Блакаваць элемент…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Хаваць контуры заблакаваных элементаў", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Паказваць колькасць заблакаваных запытаў на значцы", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Адключыць выплыўныя падказкі", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Выкарыстоўваць кантэкстнае меню, дзе магчыма", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Колеравая схема для дальтонікаў", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Выгляд", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Тэма", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Уласны колеравы акцэнт", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Уключыць падтрымку воблачнага сховішча", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Я — дасведчаны карыстальнік", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Адключыць папярэднюю загрузку (каб прадухіліць злучэнне для заблакаваных сеткавых запытаў)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Выключыць праверку гіперспасылак", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Прадухіліць уцечку лакальнага IP-адраса праз WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Прадвызначаныя паводзіны", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Гэтыя налады могуць быць перавызначаныя для кожнага сайта асобна", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Выключыць касметычныя фільтры", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блакаваць медыя-элементы большыя за {{input}} КБ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блакаваць аддаленыя шрыфты", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Адключыць JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Блакаваць справаздачы CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Раскрываць CNAME назвы", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Пашыраныя налады", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Функцыі, патрэбныя толькі тэхнічным карыстальнікам", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "пашыраныя налады", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Апошняе аднаўленне:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Апошняя рэзервовая копія:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} сеткавых фільтраў + {{cosmeticFilterCount}} касметычных фільтраў з:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} выкарыстана з {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Аўтаматычна абнаўляць спісы фільтраў", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Абнавіць зараз", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Ачысціць усе кэшы", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Разбіраць і прымяняць касметычныя фільтры", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Касметычныя фільтры служаць для хавання элементаў вэб-старонак, якія ствараюць візуальныя нязручнасці, і якія не могуць быць заблакаваныя сродкамі фільтравання сеткавых запытаў.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ігнараваць агульныя касметычныя фільтры", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Агульныя касметычныя фільтры — гэта тыя касметычныя фільтры, якія прызначаны для прымянення на ўсіх вэб-сайтах. Уключэнне гэтай налады знізіць спажыванне памяці і працэсара, дададзенае да вэб-старонак у выніку працы агульных касметычных фільтраў.\n\nРэкамендуецца ўключыць гэту наладу на менш магутных прыладах.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Прыпыніць сеткавую актыўнасць, пакуль не пагрузяцца ўсе спісы фільтраў", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Ужыць змяненні", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Убудаваныя", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Рэклама", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Прыватнасць", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Дамены шкодных праграм", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Надакучлівасці", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Шматмэтавыя", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Рэгіёны, мовы", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Карыстальніцкія", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Імпартаваць…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Адзін URL на радок. Няспраўныя URL-адрасы будуць праігнараваныя.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Неактуальны.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "паглядзець змест", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Апошняе абнаўленне: {{ago}}.\nНацісніце для прымусовага абнаўлення.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Абнаўляецца…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Памылка сеткі не дазволіла абнавіць рэсурс.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Адзін фільтр на радок. Фільтрам можа быць адрас сайта або сумяшчальны з EasyList фільтр. Радкі, што пачынаюцца з !, будуць праігнараваны.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Не дадавайце фільтры з крыніц, якім не давяраеце.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Імпартаваць і дадаць", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Экспартаваць", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Ужыць змяненні", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Пастаянныя правілы", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Часовыя правілы", + "description": "header" + }, + "rulesRevert": { + "message": "Вярнуць", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Зацвердзіць", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Змяніць", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Захаваць", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Адкінуць", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Імпартаваць з файла…", + "description": "" + }, + "rulesExport": { + "message": "Экспартаваць у файл", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Спіс вашых правіл дынамічнага фільтравання.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Сінтаксіс правіл: крыніца прызначэнне тып дзеянне (поўная дакументацыя).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Сартаванне:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тып правіла", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Крыніца", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Прызначэнне", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Дырэктывы давераных сайтаў указваюць, на якіх вэб-старонках uBlock Origin павінен быць выключаны. Адзін запіс на радок.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Імпартаваць і дадаць", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Экспартаваць", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Ужыць змяненні", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тып", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Дамен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Фільтр", + "description": "English: Filter" + }, + "logAll": { + "message": "Усе", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Па-за карткамі", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Дзейная картка", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Перазагрузіць змесціва карткі", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Пераключыць інспектар DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Пераключыць выплыўную панэль", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin вікі: Логер", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Ачысціць логер", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Паставіць логер на паўзу (адкідваць усе ўваходныя звесткі)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Зняць логер з паўзы", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Пераключыць фільтраванне логера", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "фільтраваць запісы логера", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Налады фільтравання логера", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Не", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "заблакаваны", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "дазволены", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "мадыфікаваны", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "асноўны", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "старонні", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Падрабязнасці", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Фільтр", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Спіс фільтраў", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правіла", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Кантэкст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Кантэкст кораня", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Старана", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тып", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL-адрас", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL правіла", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Кантэкст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тып:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статычны фільтр", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} сеткавыя запыты {{type}}, {{br}}URL-адрас якіх супадае з {{url}} {{br}}і паходзяць з {{origin}},{{br}}{{importance}} ёсць адпаведны фільтр-вынятак.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блакаваць", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Дазволіць", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "тыпу “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "любы тып", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "з “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "з любога месца", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "акрамя выпадкаў, калі", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "нават калі", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Статычны фільтр {{filter}} знойдзены ў:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Статычны фільтр не знойдзены ні ў адным з уключаных зараз спісе фільтраў", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Запісы логера, якія не адпавядаюць усім тром дадзеным ніжэй умовам, будуць аўтаматычна адкінуты:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Захоўваць запісы за апошнія {{input}} хвілін", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Захоўваць не больш за {{input}} загрузак старонкі на картцы", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Захоўваць не больш за {{input}} запісаў на картку", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Выкарыстоўваць {{input}} радкоў на запіс пры вертыкальным пашырэнні", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Схаваць слупкі:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Час", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Фільтр/правіла", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Кантэкст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Старана", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Спіс", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Табліца", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Просты", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Адкрыць", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Стварыць новую справаздачу", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Знайсці падобныя справаздачы", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Дакументацыя", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Прачытайце дакументацыю на uBlock/wiki, каб даведацца пра ўсе магчымасці uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Пытанні і падтрымка", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Адказы на пытанні і іншыя віды падтрымкі даступныя на сабрэддыце /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Праблемы з фільтрамі/няспраўны сайт", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Паведамляйце аб праблемах з фільтрамі на пэўных сайтах на трэкеры хібаў uBlockOrigin/uAssets. Патрабуе ўліковы запіс GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Важна: Пазбягайце выкарыстання іншых блакавальнікаў аналагічнага прызначэння разам з uBlock Origin, паколькі гэта можа прывесці да праблем з фільтрамі на пэўных сайтах.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Парада: Упэўніцеся, што вашы спісы фільтраў абноўленыя. Логер — галоўны інструмент для дыягностыкі праблем, звязаных з фільтрамі.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Справаздача пра хібу", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Паведамляйце пра праблемы самога uBlock Origin на трэкеры хібаў uBlockOrigin/uBlock-issue. Патрабуе ўліковы запіс GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Інфармацыя для выпраўлення непаладак", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Ніжэй - тэхнічная інфармацыя, што можа быць карысная добраахвотнікам, якія паспрабуюць дапамагчы вам вырашыць праблему.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Важна: Патэнцыйна прыватная або адчувальная інфармацыя тыпова рэдагуецца. Адрэдагаваная інфармацыя можа зрабіць цяжэйшым вырашэнне праблемы.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Паведаміць аб праблеме з фільтрам", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Каб не абцяжарваць добраахвотнікаў дубляванымі справаздачамі, калі ласка, праверце, што пра гэтую праблему не паведамлялі раней.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Спісы фільтраў абнаўляюцца штодзённа. Упэўніцеся, што ваша праблема не была вырашана ў найноўшых спісах фільтраў.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Спраўдзіце, ці праблема ўсё яшчэ існуе пасля перазагрузкі праблемнай вэб-старонкі.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Адрас вэб-старонкі:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Вэб-старонка…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Выберыце катэгорыю --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Паказвае рэкламу або яе астачу", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Мае накладанні або іншыя недарэчнасці", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Выяўляе uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Праблемы, звязаныя з прыватнасцю", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Няспраўная, калі ўключаны uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Адкрывае непажаданыя карткі або вокны", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Пазначыць вэб-старонку як “NSFW” (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Палітыка прыватнасці", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Журнал змяненняў", + "description": "" + }, + "aboutCode": { + "message": "Зыходны код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Удзельнікі", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Зыходны код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Пераклады", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Спісы фільтраў", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Вонкавыя залежнасці (GPLv3-сумяшчальныя):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Уласныя спісы фільтраў uBO свабодна размяшчаюцца ў наступных сетках CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Калі спіс фільтраў патрабуе абнаўлення, выкарыстоўваецца выпадкова выбраная сетка CDN", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Стварыць рэзервовую копію…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Аднавіць з файла…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Скінуць на пачатковыя налады…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Усе вашы налады будуць заменены звесткамі з рэзервовай копіі, створанай {{time}}, затым uBlock₀ будзе перазапушчаны.\n\nПеразапісаць усе налады, выкарыстаўшы рэзервовую копію?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Звесткі немагчыма прачытаць або яны нядзейсныя", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Усе вашы налады будуць выдаленыя, uBlock₀ будзе перазапушчаны.\n\nСкінуць uBlock₀ да прадвызначаных налад?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Памылка сеткі: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Дадаць наступны URL-адрас да вашага спісу фільтраў?\n\nНазва: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Падпісацца", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "хвіліну таму", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} хвілін(ы) таму", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "гадзіну таму назад", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} гадзін(ы) таму", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "дзень таму", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} дні таму", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Паказаць панэль кіравання", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Паказаць логер", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "выключаны", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Старонка заблакавана", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin папярэдзіў чытанне наступнай старонкі:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "З-за наступнага фільтра", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Знойдзены ў:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Вярнуцца", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Закрыць гэта акно", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Не папярэджваць больш пра гэты сайт", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Выключыць строгае блакаванне для {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Часова", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Назаўжды", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Працягнуць", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Экспартаваць у воблачнае сховішча", + "description": "tooltip" + }, + "cloudPull": { + "message": "Імпартаваць з воблачнага сховішча", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Імпартаваць з воблачнага сховішча і аб'яднаць з дзейнымі наладамі", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Назва гэтай прылады:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Увага! Змяняйце гэтыя пашыраныя налады на ўласную рызыку.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Пацвердзіць", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Ужыць змяненні", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Вярнуць", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байтаў", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Заблакаваць элемент у рамцы…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Падпісацца на спіс фільтраў…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Тымчасова дазволіць вялікія медыя-элементы", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Паглядзець зыходны код…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Упішыце спалучэнне", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Пераключыць агульную пракрутку", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Капіяваць у буфер абмену", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Абраць усе", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Пераключыць касметычнае фільтраванне", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Паслаблены рэжым блакавання", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Памер сховішча: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "КБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Націсніце, каб загрузіць", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Памылак: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Немагчыма фільтраваць належным чынам пры запуску браўзера.\nАбнавіце старонку, каб забяспечыць належнае фільтраванне.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/bg/messages.json b/src/_locales/bg/messages.json new file mode 100644 index 0000000..fd2b676 --- /dev/null +++ b/src/_locales/bg/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Най-накрая, ефективен блокер. Щадящ процесора и паметта.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Табло", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Внимание! Има незапазени промени", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Оставане", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Игнориране", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Настройки", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Филтри", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Мои филтри", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Мои правила", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Доверени сайтове", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Клавишни комбинации", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Дневник", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Относно", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Поддръжка", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Активи", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Разширени настройки", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ само за тази страница.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Щракнете, за да включите uBlock₀ за този сайт.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "блокирани заявки", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на тази страница", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} или {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "общо досега", + "description": "English: since install" + }, + "popupOr": { + "message": "или", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Блокирани на тази страница", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Блокирани общо досега", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Свързани домейни", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Табло с настройки", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Временно блокиране на отделен елемент", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Блокиране на отделен елемент", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Преглед на дневника със заявки", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Докладване на проблем с този уебсайт", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Превключване блокирането на всички изскачащи прозорци за този сайт", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Щракнете, за да блокирате всички изскачащи прозорци за този сайт", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Щракнете, за да разрешите всички изскачащи прозорци за този сайт", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Превключване блокирането на големи мултимедийни елементи за този сайт", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Щракнете, за да блокирате големите мултимедийни елементи за този сайт", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Щракнете, за да разрешите големите мултимедийни елементи за този сайт", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Превключване на козметичното филтриране за този сайт", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Щракнете, за да изключите козметичните филтри за този сайт", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Щракнете, за да включите козметичните филтри за този сайт", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Превключване блокирането на външни шрифтове за този сайт", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Щракнете, за да блокирате външните шрифтове за този сайт", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Щракнете, за да разрешите външните шрифтове за този сайт", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Щракнете, за да забраните JavaScript за този сайт", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Щракнете, за да разрешите JavaScript за този сайт", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Изкачащи прозорци", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Големи мултимедийни елементи", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Козметично филтриране", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Външни шрифтове", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Още", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "По-малко", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Глобални правила: колона с правила, приложими към всички сайтове.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Локални правила: колона с правила, приложими само към текущият сайт. Локалните правила заместват глобалните.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Щракнете, за да направите промените постоянни.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Щракнете, за да отмените направените промени.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Всички", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Изображения", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3-ти страни", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/изображения от 3-ти страни", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Вградени скриптове", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Скриптове от 1-ви страни", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Скриптове от 3-ти страни", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Рамки от 3-ти страни", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "свързани домейни", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} от {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Версия", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "скрипт", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "рамка", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Създаване", + "description": "English: Create" + }, + "pickerPick": { + "message": "Нов избор", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Отказ", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Преглед", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Мрежови филтри", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Козметични филтри", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Щракване, Ctrl + щракване", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Блокиране на елемент…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Скриване подсказващите текстове на блокираните елементи", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Показване на брояч в иконката за блокираните заявки", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Изключване на поясненията", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Използване на контекстното меню, когато е възможно", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Достъпност за хора с нарушено цветоусещане", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Външен вид", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Тема", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Потребителски цвят на акцента", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Включване на поддръжка за съхранение в облак", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Аз съм опитен потребител", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Изключване на предварителното извличане (за избягване на всяка връзка за блокираните мрежови заявки)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Изключване на проверката за препратки", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Предотвратяване изтичането на локалния IP адрес през WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Поведение по подразбиране", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Тези поведения по подразбиране могат да бъдат отменени за отделни сайтове", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Изключване на козметичното филтриране", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блокиране на мултимедийни елементи, по-големи от {{input}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блокиране на външни шрифтове", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Забраняване на JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Блокиране на CSP отчетите", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Разкриване на каноничните имена", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Разширени", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Функции, подходящи само за технически грамотни потребители", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "разширени настройки", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Последно възстановяване:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Последно резервно копие:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} мрежови филтри + {{cosmeticFilterCount}} козметични филтри от:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "ползвани {{used}} от общо {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Автоматично обновяване на филтрите", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Обновяване", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Изчистване на кеш паметта", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Анализиране и прилагане на козметичните филтри", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Козметичните филтри служат за скриване на елементи в уебстраницата, които се считат за визуално неприятни и които не могат да бъдат блокирани от механизмите за филтриране, базирани на мрежови заявки.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Игнориране на общите козметични филтри", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Общокозметични са филтрите, предназначени за прилагане във всички сайтове. Разрешаването на тази опция ще премахне натоварването на паметта и процесора, добавено към уеб страниците в резултат на обработката на общите козметични филтри.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Преустановяване на мрежовата дейност, докато се заредят всички списъци с филтри", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Списъци на блокираните хостове", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Прилагане на промените", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Вградени", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Реклами", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Поверителност", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Защита от зловреден софтуер, сигурност", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Досадни неща", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Многоцелеви", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Региони, езици", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Потребителски", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Внасяне...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Един адрес на ред. Невалидните адреси ще бъдат игнорирани.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Остарял", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Преглед на съдържанието", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Последно обновяване: {{ago}}.\nЩракнете за принудително обновяване.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Обновяване...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Грешка в мрежата възпрепятства обновяването на ресурса.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Един филтър на ред. Това може да бъде обикновен адрес или филтър, съвместим с EasyList. Редовете с представка ! ще бъдат игнорирани.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Не добавяйте филтри от ненадеждни източници.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Внасяне и добавяне...", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Изнасяне...", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-мои-филтри_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Прилагане на промените", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Постоянни правила", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Временни правила", + "description": "header" + }, + "rulesRevert": { + "message": "Връщане", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Приемане", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Редактиране", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Запазване", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Отказ на промените", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Внасяне от файл...", + "description": "" + }, + "rulesExport": { + "message": "Изнасяне във файл...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-мои-правила_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Списък на динамичните правила за филтриране.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Синтаксис на правилото: източник цел тип действие (пълна документация).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Сортиране:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тип правило", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Източник", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Дестинация", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Указанията за доверени сайтове определят кои уеб страници трябва да бъдат изключени от uBlock Origin. По един запис на ред.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Внасяне и добавяне...", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Изнасяне...", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-доверени_сайтове_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Прилагане на промените", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тип", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домейн", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL адрес", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Филтър", + "description": "English: Filter" + }, + "logAll": { + "message": "Всички", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Скрити", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Последно активен раздел", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Презареждане съдържанието на раздела", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Превключване на DOM инспектора", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Превключване на изскачащия панел", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Дневникът със заявки", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Изчистване на заявките", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Пауза на заявките (отхвърляне на входящите данни)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Включване на заявките", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Превключване на филтрирането", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "филтриране на записи", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Опции за филтриране", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Изкл.", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "блокирани", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "позволени", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "променен", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1-ви страни", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3-ти страни", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Детайли", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Филтър", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Списък с филтри", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правило", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Основен контекст", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Страна", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тип", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Адрес", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Правило за адрес", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тип:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статично филтриране", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} на мрежови заявки от {{type}} за адрес, съвпадащ с {{br}}{{url}}{{br}}и произлизащ от {{origin}},{{importance}} има филтър със съвпадащи изключения.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блокиране", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Разрешаване", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "тип \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "всеки тип", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "където и да е", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "с изключение, когато", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "дори ако", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Статичният филтър {{filter}} е намерен в:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Статичният филтър не е намерен в никой от активните списъци с филтри", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Записите в дневника, които не отговарят на трите условия по-долу ще бъдат автоматично отхвърлени:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Запазване на записите от последните {{input}} минути", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Запазване най-много на {{input}} зареждания на страница за раздел", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Запазване най-много на {{input}} записа за раздел", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Използване на {{input}} реда за записи в разширен вертикален режим", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Скриване на колони:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Време", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Филтър/правило", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Контекст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Страна", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Списък", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Таблица", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Обикновен", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Отваряне", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Нов доклад", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Намиране на подобни доклади", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Документация", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Прочетете документацията в uBlock/wiki, за да научите повече за всички функции на uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Въпроси и поддръжка", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Отговори на въпроси и други видове помощ се предоставят в Reddit /r/uBlockOrigin", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Проблеми с филтъра/уебсайтът е счупен", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Докладвайте за проблеми с филтрирането на конкретни уебсайтове в uBlockOrigin/uAssets за проследяване на проблеми. Изисква се акаунт в GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Важно: Избягвайте да използвате други блокери с подобно предназначение заедно с uBlock Origin, тъй като това може да доведе до проблеми с филтрирането на определени уебсайтове.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Съвети: Уверете се, че списъците ви с филтри са актуални. Дневникът е основният инструмент за диагностициране на проблеми, свързани с филтрите.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Доклад за грешка", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Докладвайте за проблеми със самия uBlock Origin в uBlockOrigin/uBlock-issue за проследяване на проблеми. Изисква се акаунт в GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Информация за отстраняване на неизправности", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "По-долу е представена техническа информация, която може да е полезна, когато доброволците се опитват да ви помогнат да разрешите даден проблем.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Важно: Потенциално лична или чувствителна информация се редактира по подразбиране. Редактираната информация може да затрудни решаването на даден проблем.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Докладване на проблем с филтъра", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "За да се избегне натоварването на доброволците с дублиращи се доклади, моля, проверете дали проблемът все още не е докладван.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Списъците с филтри се актуализират ежедневно. Уверете се, че вашият проблем вече не е решен в най-новите списъци с филтри.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Проверете дали проблемът продължава да съществува след презареждане на проблемната уеб страница.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Адрес на уеб страницата:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Уеб страницата...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Изберете запис --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Показва реклами или остатъци от реклами", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Има наслагвания или други неудобства", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Открива uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Има проблеми, свързани с поверителността", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Функционира неправилно, когато uBlock Origin е активиран", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Отваря нежелани раздели или прозорци", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Маркиране на уеб страницата като “NSFW” (“не е безопасна за работа”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Редактиран вид", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Нередактиран вид", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Политика за поверителност", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Списък с промени", + "description": "" + }, + "aboutCode": { + "message": "Изходен код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Сътрудници", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Изходен код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Преводи", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Списъци с филтри", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Външни зависимости (съвместими с GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Собствените списъци с филтри на uBO се хостват свободно на следните CDN-и:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ще бъде използван случайно избран CDN, когато трябва да се обнови списък с филтри", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Изнасяне във файл...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-всички-настройки_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Възстановяване от файл...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Възстановяване на първоначалните настройки...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Всички настройки ще бъдат презаписани с данни, архивирани на {{time}} и uBlock₀ ще се рестартира.\n\nПрезаписване на съществуващите настройки, използвайки архивираните данни?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Данните не могат да бъдат прочетени или са невалидни", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Всички настройки ще бъдат премахнати и uBlock₀ ще се рестартира.\n\nВръщане на uBlock₀ към стандартните настройки?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Грешка в мрежата: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Добавяне на следния адрес към списъците с потребителски филтри?\n\nИме: \"{{title}}\"\nURL адрес: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Абониране", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "преди минута", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "преди {{value}} минути", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "преди час", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "преди {{value}} часа", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "преди ден", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "преди {{value}} дни", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Показване на табло", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Показване на дневник за мрежовите заявки", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "изключен", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Страницата е блокирана", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin предотврати зареждането на страницата:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Блокиращ филтър", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Намерен в:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Назад", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Затваряне на прозореца", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Без повторно предупреждение за този сайт", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Изключване на строгото блокиране за {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Временно", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Постоянно", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Продължаване", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Изнасяне в облачно хранилище", + "description": "tooltip" + }, + "cloudPull": { + "message": "Внасяне от облачно хранилище", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Внасяне на настройки от облачно хранилище и обединяване с текущите", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Име на устройството:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Внимание! Променяте настройките на свой собствен риск.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Изпращане", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Прилагане на промените", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Връщане", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байта", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Блокиране на елемента в рамката...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Абониране за списъка с филтри...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Временно разрешаване на големи мултимедийни елементи", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Преглед на изходния код…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Натиснете клавиши", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Превключване на заключеното превъртане", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Копиране в клипборда", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Избиране на всичко", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Превключване на козметичното филтриране", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Отпуснат режим на блокиране", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Използвано пространство: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "КБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Щракнете, за да се зареди", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Грешки: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Не може да се филтрира правилно при стартиране на браузъра.\nПрезаредете страницата, за да се уверите, че филтрирането е правилно.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Това поле трябва да бъде последното", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/bn/messages.json b/src/_locales/bn/messages.json new file mode 100644 index 0000000..adbb21a --- /dev/null +++ b/src/_locales/bn/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "অবশেষে, একটি সাশ্রয়ী বিজ্ঞাপন রোধক। সিপিইউ এবং মেমরিতে নমনীয়।", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — ড্যাশবোর্ড", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "সতর্কীকরণ! আপনার পরিবর্তনগুলো সংরক্ষণ করা হয়নি।", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "থাকুন", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "অবজ্ঞা করুন", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "সেটিংস", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "ছাঁকন তালিকা", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "আমার ফিল্টার", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "আমার নিয়ম", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "বিশ্বস্ত তালিকা", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "শর্টকাটগুলি", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ঘটনাবলী", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "সম্পর্কে", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "সাহায্য", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — তথ্য নিরিক্ষক", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "উন্নত সেটিংস", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ নিষ্ক্রিয় করুন", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "এই সাইটের জন্য ইউব্লক₀ সক্রিয় করতে ক্লিক করুন।", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "অবরোধের অনুরোধ", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "এই পাতায়", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}}টি বা {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "ইনস্টলের পর থেকে", + "description": "English: since install" + }, + "popupOr": { + "message": "বা", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "এই পাতাটা অবরুদ্ধ হয়েছে", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "ইনস্টল করার পর থেকে অবরুদ্ধ হয়েছে", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "যুক্ত ডোমেন ", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ড্যাশবোর্ড খুলুন", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "উপাদান অপসারণ মোডে প্রবেশ করুন", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "উপাদান বাছাইকারী মোডে প্রবেশ করুন", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "ঘটনাবলী খুলুন", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "এই ওয়েবসাইট এর একটি সমস্যার ব্যাপারা অভিযোগ যানান", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "এই সাইটের সব পপআপ ব্লকিং চালু/বন্ধ করুন", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "এই সাইটে সব পপআপ অবরুদ্ধ করতে ক্লিক করুন", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "এই সাইটে সব পপআপ আর অবরুদ্ধ না করতে ক্লিক করুন", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "এই সাইটের জন্য বড় মিডিয়া উপাদান অবরোধ চালু/বন্ধ করুন", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "এই সাইটে বড় মিডিয়া উপাদান অবরুদ্ধ করতে ক্লিক করুন", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "এই সাইটের বর মিডিয়া এলিমেন্টগুলি ব্লক করা বন্ধ করতে ক্লিক করুন", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "এই সাইটের জন্য কসমেটিক ছাঁকন চালু/বন্ধ করুন", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "এই সাইটে কসমেটিক ফিল্টার নিষ্ক্রিয় করতে ক্লিক করুন", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "এই সাইটে কসমেটিক ফিল্টার সক্রিয় করতে ক্লিক করুন", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "এই সাইটের রিমোট ফন্টের অবরোধ চালু/বন্ধ করুন", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "এই সাইটে রিমোট ফন্ট অবরুদ্ধ করতে ক্লিক করুন", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "এই সাইটে রিমোট ফন্ট আর অবরুদ্ধ না করতে ক্লিক করুন", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "এই সাইটের জাভাস্ক্রিপ্ট বন্ধ করতে ক্লিক করুণ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "এই সাইটের জাভাস্ক্রিপ্ট চালু করতে ক্লিক করুণ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "পপ-আপ উইন্ডোগুলি", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "বড় মিডিয়া এলিমেন্টগুলি", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "সৌন্দর্য্যবর্ধক ছাকন", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "রিমোট ফন্টগুলি", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "জাভাস্ক্রিপ্ট", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "আরো", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "কম", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "সার্বজনীন নিয়ম: এই স্তম্ভ সেইসব নিয়মের জন্য যা সকল সাইটের উপর প্রযোজ্য।", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "অভ্যন্তরীন নিয়ম: এই কলামটি সেইসব নিয়মের জন্য যা শুধু বর্তমান সাইটে প্রয়োগ করা হবে।\nঅভ্যন্তরীন নিয়ম সার্বজনীন নিয়মকে অগ্রাহ্য করবে।", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "আপনার পরিবর্তনগুলি স্থায়ী করতে ক্লিক করুন।", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "আপনার পরিবর্তনগুলি ফেরত নিতে ক্লিক করুন।", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "সব", + "description": "" + }, + "popupImageRulePrompt": { + "message": "চিত্র", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "৩য়-পক্ষ", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "৩য়-পক্ষের সিএসএস/চিত্র", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "সারির সাথে সঙ্গতিপূর্ণ স্ক্রিপ্ট", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "১ম-পক্ষের স্ক্রিপ্ট", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "৩য়-পক্ষের স্ক্রিপ্ট", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "৩য়-পক্ষের ফ্রেম", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "যুক্ত ডোমেন ", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}}টির মধ্যে {{count}}টি", + "description": "appears in popup" + }, + "popupVersion": { + "message": "সংস্করণ", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "স্ক্রিপ্ট", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "কাঠামো", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "তৈরি করুন", + "description": "English: Create" + }, + "pickerPick": { + "message": "চয়ন করুন", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "প্রস্থান", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "প্রাকদর্শন", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "নেটওয়ার্ক ফিল্টার", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "প্রসাধনী ফিল্টার", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "ক্লিক, Ctrl-ক্লিক", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "উপাদান রুদ্ধ করুন", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "অবরুদ্ধ উপাদানের স্থানধারক লুকান", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "আইকনে অবরোধের অনুরোধ সংখ্যা দেখান", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "টুলটিপ নিষ্ক্রিয় করুন", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "উপযুক্ত স্থানে প্রাসঙ্গিক মেনু ব্যবহার করুন", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "বর্ণান্ধ সহযোগী", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "দৃষ্টি", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "থিম", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "কাস্টম অ্যাকসেন্ট রঙ", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "ক্লাউড সংরক্ষণ সক্রিয় করুন", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "আমি একজন উন্নত ব্যবহারকারী (পড়া আবশ্যক)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "প্রি-ফেচিং বন্ধ করুন (অবরুদ্ধ নেটওয়ার্ক থেকে যে কোনো সংযোগ প্রতিরোধ করতে)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "হাইপারলিঙ্ক নিরীক্ষণ নিষ্ক্রিয় করুন", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "স্থানীয় আইপি ঠিকানা ফাঁস থেকে ওয়েব আর.টি.সি.কে প্রতিরোধ করুন", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "পূর্বনির্ধারিত আচরণ", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "এই পূর্বনির্ধারিত আচরণ প্রতি সাইট ভিত্তিতে ওভাররাইড করা যেতে পারে", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "প্রসাধন ফিল্টারিং নিষ্ক্রিয় করুন", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input:number}} কেবির থেকে বড় মিডিয়া উপাদান অবরুদ্ধ করুন", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "রিমোট ফন্ট অবরুদ্ধ করুন", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "জাভা স্ক্রিপ্ট বন্ধ করা", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP প্রতিবেদন অবরুদ্ধ করুন", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Canonical Name এর উন্মোচন", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "অ্যাডভান্সড", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "শুধুমাত্র প্রযুক্তিগত ব্যবহারকারীদের জন্য উপযুক্ত ফিচারসমুহ", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "উন্নত সেটিংস", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "সর্বশেষ পুনঃস্থাপন:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "সর্বশেষ ব্যাকআপ:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "এ থেকে {{netFilterCount}}টি নেটওয়ার্ক ফিল্টার + {{cosmeticFilterCount}}টি প্রসাধনী ফিল্টার:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}}টির মধ্যে {{used}}টি ব্যবহৃত", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "ফিল্টার তালিকা স্বয়ংক্রিয়-হালনাগাদ করুন।", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "এখনই হালনাগাদ করুন", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "সব ক্যাশে শোধন করুন", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "প্রসাধনী ফিল্টার পার্স ও কার্যকর করুন।", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

এই অপশনটি অ্যাডব্লক-প্লাসের সামঞ্জস্যপূর্ণ “উপাদান আড়াল করার” ফিল্টারকে সক্রিয় করবে। এই ফিল্টারগুলি মূলত প্রসাধনী, তাদের একটি ওয়েব পাতায় উপাদান আড়াল করতে প্রয়োজন হয় যাকে চাক্ষুষ উত্পাত বলিয়া গণ্য করা হয়, এবং যাদের নেট অনুরোধ ভিত্তিক ফিল্টারিং ইঞ্জিন দ্বারা অবরুদ্ধ করা যায় না।

এই বৈশিষ্ট্য সক্রিয় করলে uBlock₀-এর মেমরির পদচিহ্ন বৃদ্ধি পাবে।

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "জেরেরিক প্রসাধনী ছাঁকনি উপেক্ষা করুন।", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

জেনেরিক প্রসাধনী ছাঁকনি হচ্ছে সেইসব প্রসাধনী ছাঁকনি যা সব ওয়েবসাইটে প্রয়োগের জন্য অভিপ্রেত।

যদিও তা uBlock₀ দ্বারা দক্ষতার সঙ্গে পরিচালনা করে, কিন্তু জেনেরিক প্রসাধন ফিল্টার এখনও কিছু ওয়েব পাতার পরিমাপযোগ্য মেমরি ও CPU-র অত্যাধিক চাপ সৃষ্টিতে অবদান রাখতে পারে, বিশেষ করে বড় এবং দীর্ঘ একটিতে।

এই অপশন সক্রিয় করলে জেনেরিক প্রসাধনী ছাঁকনি পরিচালিত হবে যা ওয়েব পাতার পরিমাপযোগ্য মেমরি ও CPU-র অত্যাধিক চাপ সৃষ্টি দূর করবে এবং uBlock₀ নিজেই মেমরি পদাঙ্ক অর্ধ করবে।

এটা কম শক্তিশালী ডিভাইসে এই অপশনটি সক্রিয় করার জন্য সুপারিশ করা হচ্ছে।", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "সবগুলি ফিল্টার তালিকা লোড না হওয়া পর্যন্ত নেটওয়ার্ক কার্যকলাপ স্থগিত করুন", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "অবরুদ্ধ হোস্টের তালিকা", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "পরিবর্তনগুলি প্রয়োগ", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "বিল্ট-ইন", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "বিজ্ঞাপন", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "গোপনীয়তা", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "ম্যালওয়্যার ডোমেইন", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "বিরক্তিকর", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "বহুমুখী", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "অঞ্চল, ভাষা", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "স্বনির্ধারিত", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "আমদানি করুন...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "লাইন প্রতি একটি URL। ‘!’ সহ উপসর্গ লাইন উপেক্ষা করা হবে। অকার্যকর URL গুলি নীরবে উপেক্ষা করা হবে।", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "পুরোনো", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "কন্টেন্ট দেখুন", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "সর্বশেষ হালনাগাদ: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "হালনাগাদ করা হচ্ছে...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "একটি নেটওয়ার্ক ত্রুটি রিসোর্স বা তথ্য হালনাগাদ হওয়া রোধ করেছে।", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "লাইন প্রতি একটি ফিল্টার। একটি ফিল্টার শুধু হোস্টনেম বা অ্যাডব্লক প্লাস-এর সাথে সামঞ্জস্যপূর্ণ ফিল্টার হতে পারে। ! দিয়ে শুরু হওয়া লাইন উপেক্ষা করা হবে।", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "সন্দেহজনক উৎস থেকে ফিল্টারে কোন কিছু যোগ করবেন না।", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "আমদানি করে পরিশেষে যোগ করুন", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "রপ্তানি করুন", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "amar-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "পরিবর্তনগুলি প্রয়োগ", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "স্থায়ী নিয়ম", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "অস্থায়ী নিয়ম", + "description": "header" + }, + "rulesRevert": { + "message": "প্রত্যাবর্তন", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "কমিট", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "সম্পাদনা", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "সংরক্ষণ", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "বাতিল করুন", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ফাইল থেকে আমদানি...", + "description": "" + }, + "rulesExport": { + "message": "ফাইলে রপ্তানি", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "amar-ublock-dynamic-niyom_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "আপনার গতিশীল ফিল্টারের নিয়মের তালিকা।", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "শব্দবিন্যাসের নিয়ম: source destination type action (সম্পূর্ণ নথিপত্র)।", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "সাজাও:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "নিয়মের ধরন", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "উৎস", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "গন্তব্য", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "আপনার হোস্টের তালিকা যাদের জন্য uBlock₀ নিষ্ক্রিয় করা হবে। লাইন প্রতি একটি ভুক্তি। অবৈধ হোস্ট নাম নিশব্দে উপেক্ষা করা হবে।", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "আমদানি ও পরিশেষে যোগ করুন", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "রপ্তানি করুন", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "amar-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "পরিবর্তনগুলি প্রয়োগ", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "ধরন", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ডোমেইন", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "ফিল্টার", + "description": "English: Filter" + }, + "logAll": { + "message": "সব", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "পর্দার আড়ালে", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "বর্তমান ট্যাব", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "ট্যাবের বিষয় বস্তু রিলোড করুণ", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "ড.অ.ম. পরিদর্শক বোতাম", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "পপআপ এলাকার বোতাম", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "ইউব্লক অরিজিন উইকি: লগার", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "লগার পরিষ্কার করুন", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "লগার থামান (আগত সকল তথ্য বাতিল করুন)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "লগার চালু করুন", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "লগার ছাকন বোতাম", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "ফিল্টার লগের ভুক্তি", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "লগার ছাকন বাছাইকরণ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "না", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "অবরুদ্ধ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "অনুমোদিত", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "পাল্টানো", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "১ম-পক্ষ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "৩য়-পক্ষ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "বিস্তারিত", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ছাকন", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "ছাঁকন তালিকা", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "নিয়ম", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "প্রসঙ্গ", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "রুট প্রসঙ্গ", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "দলমত", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "ধরন", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "ইউ.আর.এল.", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "ডায়নামিক URL ফিল্টারিং", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "প্রসঙ্গ:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "ধরন:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "স্থির ফিল্টারিং", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{type}}-এর নেটওয়ার্ক অনুরোধ {{action}} {{br}}যার URL ঠিকানা {{url}}-এর সাথে মিলেছে {{br}}এবং যার মূলভিত্তি {{origin}},{{br}} {{importance}} এখানে একটি মেলানো ব্যতিক্রম ফিল্টার আছে।", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "অবরুদ্ধ করুন", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "মঞ্জুর", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "ধরন “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "যে কোন ধরন", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}” থেকে", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "যে কোন জায়গা থেকে", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "এছাড়া যখন", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "এমনকি যদি", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "স্থির ফিল্টার {{filter}} পাওয়া গেছে:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "স্থির ফিল্টার বর্তমানে সক্রিয় ফিল্টার তালিকার কোনটিতে পাওয়া যায় নি", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "নীচের যে লগার এন্ট্রিগুলি তিনটি শর্ত সম্পূর্ণ পূরণ করে না তাদেরকে স্বয়ংক্রিয়ভাবে বাতিল হবে:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "শেষ {{input}} মিনিটের এন্ত্রিগুলো সংরক্ষণ করা হবে", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "প্রত্যেক ট্যাবের সর্বোচ্চ {{input}} পেজ লোড সংরক্ষণ করা হবে", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "প্রত্যেক ট্যাবে সর্বোচ্চ {{input}} এন্ট্রি সংরক্ষণ করা হবে", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "প্রত্যেক এন্ট্রির জন্য খাড়াভাবে ছড়ানো মোডে {{input}}গুলো লাইন ব্যবহার করা হবে", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "কলাম লুকানো:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "সময় {{input}}", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "ছাকন/নিয়ম {{input}}", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "অনুবন্ধ {{input}}", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "দলের অন্তর্ভুক্ত", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "তালিকা", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "ছক", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "সমান্তরাল", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "মার্কডাউন", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "খুলুন", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "নতুন অভিযোগ", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "একই রকম অভিযোগ দেখুন", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "ডকুমেন্টেশন", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock Origin এর সমস্ত ফিচার সম্পর্কে জানতে uBlock/wiki এ ডকুমেন্টেশন পড়ুন।", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "যোগাযোগ এবং সহায়তা", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "প্রশ্নের উত্তর এবং অন্যান্য ধরনের সাহায্য ও সহায়তা /r/uBlockOrigin সাবরেডিট এ দেওয়া আছে।", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "ফিল্টার সমস্যা/ওয়েবসাইট ভেঙে গেছে", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "নির্দিষ্ট ওয়েবসাইটের ফিল্টার সমস্যাগুলি uBlockOrigin/uAssets ইস্যু ট্র্যাকারে রিপোর্ট করুন একটি GitHub অ্যাকাউন্ট প্রয়োজন৷", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "গুরুত্বপূর্ণ: uBlock Origin-এর সাথে একই রকম-উদ্দেশ্যযুক্ত ব্লকার ব্যবহার করা এড়িয়ে চলুন, কারণ এটি নির্দিষ্ট ওয়েবসাইটে ফিল্টার এর সমস্যা সৃষ্টি করতে পারে।", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "টিপস: আপনার ফিল্টার তালিকা আপ টু ডেট আছে তা নিশ্চিত করুন। লগার হল ফিল্টার-সম্পর্কিত সমস্যা নির্ণয়ের প্রাথমিক টুল।", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "বাগ রিপোর্ট", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlockOrigin/uBlock-issue ইস্যু ট্র্যাকার এ uBlock অরিজিন সংক্রান্ত সমস্যাগুলি রিপোর্ট করুন। একটি GitHub অ্যাকাউন্ট প্রয়োজন৷৷", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "সমস্যা সমাধানের তথ্য", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "স্বেচ্ছাসেবকরা যখন কোনো সমস্যা সমাধানের জন্য আপনাকে সাহায্য করার চেষ্টা করছেন তখন প্রযুক্তিগত তথ্য নিচে দেওয়া হল যা কার্যকর হতে পারে।", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "গুরুত্বপূর্ণ: সম্ভাব্য ব্যক্তিগত বা সংবেদনশীল তথ্য ডিফল্টরূপে সংশোধন করা হয়। সংশোধিত তথ্য সমস্যা সমাধান করা আরও কঠিন করে তুলতে পারে।", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "একটি ফিল্টার সমস্যা রিপোর্ট করুন", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "ডুপ্লিকেট রিপোর্ট সহ স্বেচ্ছাসেবকদের বোঝা এড়াতে, অনুগ্রহ করে যাচাই করুন যে সমস্যাটি ইতিমধ্যে রিপোর্ট করা হয়নি।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "ফিল্টারের লিস্ট প্রতিদিন আপডেট করা হয়। নতুন আপডেটে আপনার সমস্যার সমাধান করা হয়েছে কিনা তা লক্ষ্য করুন। ", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "অভিযোগ দিন যদি আপনার রিলোডের পরও ওয়েবপেজের সমস্যার সমাধান না হয়।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "ওয়েব পেজের ঠিকানা:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "ওয়েব পেজটি…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- একটি এন্ট্রি চয়ন করুন --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "বিজ্ঞাপন বা বিজ্ঞাপনের অবশিষ্টাংশ দেখায়", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "ওভারলে বা অন্যান্য উপদ্রব আছে", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin শনাক্ত করে", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "গোপনীয়তা-সম্পর্কিত সমস্যা আছে", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "যখন uBlock Origin চালু করা থাকে তখন সমস্যা দেখা দেয়", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "অবাঞ্ছিত ট্যাব বা উইন্ডো খোলে", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "ওয়েব পৃষ্ঠাটিকে “NSFW” হিসাবে লেবেল করুন (“কাজের জন্য নিরাপদ নয়”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "গোপনীয়তার নীতি", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "পরিবর্তন লগ", + "description": "" + }, + "aboutCode": { + "message": "উত্স কোড (GPLv৩)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "অবদানকারী", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "সোর্স কোড", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "অনুবাদ সমূহ", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "ফিল্টার লিস্ট", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "বাহ্যিকভাবে নির্ভশীলসমূহ (জিপিএল ভা.৩-সঙ্গতিপূর্ণ)", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO-এর নিজস্ব ফিল্টার তালিকাগুলি নিম্নলিখিত CDN এ অবাধে হোস্ট করা হয়েছে:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "একটি ফিল্টার তালিকা আপডেট করার প্রয়োজন হলে একটি এলোমেলোভাবে বাছাই করা CDN ব্যবহার করা হয়", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ফাইলে ব্যাকআপ", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "amar-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "ফাইল থেকে পুনরুদ্ধার...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "ডিফল্ট সেটিংসে পুন:স্থাপন করুন...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "{{time}}-এর ডেটা ব্যাকআপ ব্যবহার করে আপনার সেটিংস পুনঃলিখিত হবে, এবং uBlock₀ পুনরায় চালু হবে।\n\nডেটা ব্যাকআপ ব্যবহার করে সমস্ত বিদ্যমান সেটিংস পুনঃলিখবেন?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "উপাত্তটি পড়া যায়নি বা অকার্যকর", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "আপনার সব সেটিংস বাতিল করা হবে, এবং uBlock₀ পুনরায় চালু হবে।\n\nইউব্লক₀ সেটিংস পুনঃস্থাপন করবেন?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "{{url}} -এ সংযোগ করতে অক্ষম", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: আপনার নিজস্ব ফিল্টার তালিকায় নিম্নলিখিত URL যোগ করবেন?\n\nশিরোনাম: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "সদস্যতা নাও", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "এক মিনিট আগে", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} মিনিট আগে", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "এক ঘণ্টা আগে", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ঘণ্টা আগে", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "এক দিন আগে", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} দিন আগে", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "ড্যাশবোর্ড দেখুন", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "লগার দেখান", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "বন্ধ", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "পেজটি ব্লক করা হয়েছে", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uব্লক অরিজিন নিচের পৃষ্ঠা লোড করাকে প্রতিহত করেছে:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "নিম্নলিখিত ফিল্টারের কারণে", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "যা এতে পাওয়া গেছে:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "ফিরে যান", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "এই উইন্ডোটি বন্ধ করুন", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "এই সাইটের ব্যাপারে আর সতর্ক করবেন না", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}}-এর জন্য কঠোর অবরোধ নিষ্ক্রিয় করুন", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "সাময়িকভাবে", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "স্থায়ীভাবে", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "এগিয়ে যান", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "ক্লাউড সঞ্চয়ে রপ্তানি করুন", + "description": "tooltip" + }, + "cloudPull": { + "message": "ক্লাউড সঞ্চয় থেকে আমদানি করুন", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "ক্লাউড সংগ্রহস্থল থেকে আমদানি করে বর্তমানে সেটিংসের সঙ্গে একত্রীকরণ করুন", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "এই ডিভাইসের নাম:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "সতর্কবাণী! আপনার নিজ ঝুঁকিতে এই উন্নত সেটিংগুলি পরিবর্তন করুন।", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "জমা দিন", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "পরিবর্তনগুলি প্রয়োগ", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "প্রত্যাবর্তন", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "বাইট", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "ফ্রেমের উপাদান রুদ্ধ করো...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "ফিল্টার তালিকায় সাবস্ক্রাইব করুন...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "সাময়িকভাবে বৃহৎ মিডিয়া উপাদান মঞ্জুরি দিন", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "সোর্স কোড দেখুন.... ", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "শর্টকাট লিখুন", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "স্ক্রলিং চালু/বন্ধ করুন", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "ক্লিপবোর্ডে প্রতিলিপি করুন", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "সবগুলো নির্বাচন করুন", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "সৌন্দর্য্যবর্ধক ফিল্টার চালু বা বন্ধ করুন", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "রোধক মোড শিথিল করুন", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "ব্যবহৃত স্টোরেজ: {{value}}{{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "কিলোবাইট", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "মেগাবাইট", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "গিগাবাইট", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "লোড করতে টিপ দাও", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "এরর: {{গণনা}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "ঠিকভাবে ফিল্টার চালু করা যায়নি। পুনরায় আবার পেজ রিলোড করুন ঠিকভাবে ফিল্টার চালু করার জন্য", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/br_FR/messages.json b/src/_locales/br_FR/messages.json new file mode 100644 index 0000000..58c7dd6 --- /dev/null +++ b/src/_locales/br_FR/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Erfin, ur stanker saotradurioù efedus hag a zouj d'ho reizhiad korvoiñ ha d'ho memor.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Taolenn-vourzh", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Diwallit! Kemmoù zo ha n'ho peus enrollet anezho", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Chom amañ", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Tremen e-bioù", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Arventennoù", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Roll ar siloù", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Ma siloù", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Ma reolennoù", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Lec'hiennoù sur", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Berradennoù", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Deizlevr ar rekedoù", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Diwar-benn", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Skoazell", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Enseller elfennoù", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Arventennoù araokaet", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: lazhañ/enaouiñ uBlock₀ war al lec'hienn-mañ.\n\nReol+klik: lazhañ uBlock₀ war al lec'hienn-mañ nemetken.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klikit evit lazhañ uBlock₀ war al lec'hienn-mañ.\n\nReol+klik evit lazhañ uBlock₀ war al lec'hienn-mañ.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klikit evit enaouiñ uBlock₀ war al lec'hienn-mañ.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "Rekedoù stanket", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "er bajenn-mañ", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} pe {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "abaoe ar staliadur", + "description": "English: since install" + }, + "popupOr": { + "message": "pe", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Stanket er bajenn-mañ", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Stanket abaoe ar staliadur", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domanioù kennasket", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Digeriñ an daolenn-vourzh", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Lemel elfennoù", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Diuzañ elfennoù", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Digeriñ deizlevr ar rekedoù", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Danevelliñ ur gudenn war al lec'hienn-mañ", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Lazhañ/enaouiñ evit stankañ an holl brenestroù pop-up war al lec'hienn-mañ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klikit evit stankañ an holl brenestroù pop-up war al lec'hienn-mañ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klikit evit aotren an holl brenestroù pop-up war al lec'hienn-mañ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Stankañ/aotren kargadur an elfennoù media pounner war al lec'hienn-mañ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klikit evit stankañ an elfennoù media pounner war al lec'hienn-mañ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klikit evit aotren an elfennoù media pounner en-dro war al lec'hienn-mañ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Lazhañ/enaouiñ ar silañ kenedel war al lec'hienn-mañ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klikit evit lazhañ ar silañ kenedel war al lec'hienn-mañ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klikit evit enaouiñ ar silañ kenedel war al lec'hienn-mañ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Lazhañ/enaouiñ evit stankañ an nodrezhioù diavaez war al lec'hienn-mañ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klikit evit stankañ an nodrezhioù diavaez war al lec'hienn-mañ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klikit evit aotren an nodrezhioù diavaez war al lec'hienn-mañ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klikit evit diweredekaat JavaScript war al lec'hienn-mañ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klikit evit gweredekaat JavaScript war al lec'hienn-mañ en-dro", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Prenestroù pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elfennoù media pounner", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Silañ kenedel", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Nodrezhioù diavaez", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Muioc'h", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Nebeutoc'h", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Reolennoù hollek: er bann-mañ e vez lakaet ar reolennoù a dalvez da gement lec'hienn.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klikit evit lakaat ho kemmoù da dalvezout.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klikit evit nullañ ar c'hemmoù ho peus graet.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Pep tra", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Skeudennoù", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Kevelerien diavaez", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/skeudennoù kevelerien diavaez", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "skriptoù enlakaet", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Skriptoù domani ar bajenn", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skriptoù kevelerien diavaez", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Frammoù kevelerien diavaez", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domanioù kennasket", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} diwar {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Handelv", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "framm", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Krouiñ", + "description": "English: Create" + }, + "pickerPick": { + "message": "Dibab", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Kuitaat", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Rakwel", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Siloù rouedad", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Siloù kenedel", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Reol.-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Stankañ an elfenn-mañ…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Kuzhat an esaouennoù lezet gant an elfennoù bet stanket", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Diskouez an niver a rekedoù bet stanket war an arouez", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Diweredekaat an tunioù", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Ober gant al lañser kendestenn pa vez ezhomm", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Mod daltonek", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Neuz", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tem", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Liv splannañ personelaet", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Gweredekaat ar stokañ e-barzh ar goumoulenn (cloud)", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Me zo un implijer araokaet", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Diweredekaat ar \"rak-lenn\", pe diougan an oberoù war ar rouedad (evit ma ne gennaskfe ket ar rekedoù rouedad stanket)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Diweredekaat evezhiañ ar gourliammoù", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Mirout ouzh WebRTC da ziskuilhañ chomlec'hioù IP lec'hel", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Emzalc'h dre ziouer", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Gallout a reer erlec'hiañ an emzalc'hioù-se dre ziouer e lec'hiennoù resis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Lazhañ ar silañ kenedel", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Stankañ an elfennoù media a zo pounneroc'h evit {{input}} KB ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Stankañ an nodrezhioù diavaez", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Diweredekaat JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Stankañ an danevelloù CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Diskouez an anvioù gwir (CNAME)", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Araokaet", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Fonksionelezhioù azasaet d'an implijerien araokaet hepken", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "arventennoù araokaet", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Adsavet da ziwezhañ:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Gwaredet da ziwezhañ:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} sil rouedad + {{cosmeticFilterCount}} sil kenedel diouzh:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} anezho implijet diwar {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Hizivaat ar rolloù siloù ent-emgefreek", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Hizivaat diouzhtu", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Riñsañ an holl grubuilhoù", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Dielfennañ ha lakaat ar siloù kenedel da dalvezout", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Ar siloù kenedel a servij da guzhat elfennoù ur bajenn web a c'hallfe bezañ noazadurioù d'ar gwelet ha ne c'hallont ket bezañ stanket gant silañ ar rouedad diazezet war ar rekedoù.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ober fae ouzh ar siloù kenedel hollek", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Name Mar bez gweredekaet an dibarzh-mañ e vo dilemel an memor ha an CPU ouzhpennet d'ar bajennoù web evel ur c'helc'h ar siloù kosmetik generel.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Ehan oberoù ar rouedad betek ma kargo an holl rolloù siloù", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Lakaat da dalvezout", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Enframmet", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Bruderezh", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Prevezded", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Gwarez a-enep ar malware ha surentez", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Saotradurioù", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Siloù lies-implij", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Rannvroioù, broioù", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personelaet", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Enporzhiañ", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Un URL dre linenn. Graet e vo fae ouzh an URLoù direizh hep kemenn deoc'h.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Diamzeriet.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "gwelet an endalc'had", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Hizivaet da ziwezhañ: {{ago}}.\nKlikit evit hizivaat.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Oc'h hizivaat…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ur fazi rouedad en deus miret an danvez da vezañ hizivaet.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ur sil dre linenn. Ur sil a c'hall bezañ un anv ostiz hepken pe ur sil hag a glot gant EasyList.\nAl linennoù a grog gant ! a vo dilezet.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Arabat ouzhpennañ siloù a zeu diouzh mammennoù douetus.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Enporzhiañ hag ouzhpennañ", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Ezporzhiañ", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ma-siloù-statek-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Lakaat da dalvezout", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Reolennoù da badout", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Reolennoù berrbad", + "description": "header" + }, + "rulesRevert": { + "message": "Nullañ", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Lakaat da dalvezout", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Kemmañ", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Enrollañ", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Nullañ", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Enporzhiañ diouzh ur restr…", + "description": "" + }, + "rulesExport": { + "message": "Ezporzhiañ etrezek ur restr", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ma-reolennoù-silañ-dinamek-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Roll eus ho reolennoù silañ dinamek.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Reolenn ereadurezh: mammenn pal seurt ober (Teuliadur klok e saozneg).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Rummañ:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Seurt reolenn", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Mammenn", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Pal", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "En ur dermeniñ peseurt lec'hiennoù a zo sur e lavarit da uBlock Origin e peseurt lec'hiennoù e rank bezañ diweredekaet. Un enmont dre linenn.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Enporzhiañ hag ouzhpennañ", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Ezporzhiañ", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ma-lec'hiennoù-fizius-ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Lakaat da dalvezout", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Seurt", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domani", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Sil", + "description": "English: Filter" + }, + "logAll": { + "message": "Pep tra", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Rekedoù dre guzh", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Ivinell a-vremañ", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Adkargañ endalc'had an ivinell", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Enaouiñ/lazhañ an enseller DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Enaouiñ/lazhañ ar banell pop-up", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "Pajenn wiki uBlock Origin: An Deizlevr", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Skarzhañ an deizlevr", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Ehan an deizlevr (ober fae ouzh an titouroù resevet)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Adstagañ gant an deizlevr", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Stagañ da silañ an deizlevr", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "Silañ endalc'had an deizlevr", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Arventennoù silañ an deizlevr", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Pas", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "stanket", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "aotreet", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "kemmet", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Domani ar bajenn", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Kevelerien diavaez", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Munudoù", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Sil", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Roll ar siloù", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Reolenn", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Kontekst gwrizienn", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Seurt keveler", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Seurt", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Reolenn URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Seurt:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Sil statek", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} ar rekedoù rouedad eus ar seurt {{type}} {{br}}da neuze an URL a glot gant {{url}} {{br}}hag a zeu eus {{origin}},{{br}}{{importance}} bout zo ur sil nemedennoù hag a glot gantañ.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Stankañ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Aotren", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "seurt \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "a bep seurt", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "n'eus forzh pelec'h", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "nemet pa", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "zoken ma", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Kavet e vez ar sil statek {{filter}} e-barzh:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "N'haller ket kavout ar sil statek-mañ e-touez ar rolloù siloù oberiant", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Enmonedoù an deizlevr ha ne glot gant an tri diviz zo amañ dindan a vo skarzhet ent-emgefreek:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Mirout an enmonedoù eus ar/an {{input}} v/munutenn gent", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Mirout {{input}} g/kargadenn pajenn dre ivinell d'ar muiañ", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Mirout {{input}} enmont dre ivinell d'ar muiañ", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Ober gant {{input}} linenn dre enmont er mod dispaket a-blom", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Kuzhat ar bannoù:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Eur", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Sil/reolenn", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kendestenn", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Seurt keveler", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Listenn", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Taolenn", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plaen", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Digeriñ", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Sevel ur rentañ-kont nevez", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Klask danevelloù koulz ha homañ", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Teuliadur", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lennit an teuliadur en uBlock/wiki evit gouzout hiroc'h diwar-benn uBlock Origin ha pep tra a c'hall ober.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Goulennoù ha skor", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Er subreddit /r/uBlockOrigin e c'hallit kavout respontoù d'ho koulennoù hag a bep seurt skoazelloù all.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Kudennoù silañ/lec'hienn sac'het", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Danevellit kudennoù silañ e lec'hiennoù resis zo e-barzh roll evezhiañ kudennoù uBlockOrigin/uAssets. Ur c'hont GitHub zo rekis.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "A-bouez: Chomit hep ober gant meur a stanker a zo heñvel ouzh uBlock Origin war un dro rak kement-se a c'hallfe degas kudennoù e lod lec'hiennoù zo.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tro-bleg: Gwiriit ma'z eo bet hizivaet ho rolloù siloù. An deizlevr eo an ostilh pennañ evit diagnostikañ kudennoù e-keñver ar silañ.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Danevelliñ un draen", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Danevellit kudennoù gant uBlock Origin e-unan e-barzh roll evezhiañ kudennoù uBlockOrigin/uBlock-issue. Ur c'hont GitHub zo rekis.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Titouroù diagnostikañ kudennoù", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Amañ dindan ez eus titouroù teknikel a c'hallfe sikour an dud a-youl vat a zo o klask diskoulmañ ur gudenn.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Talvoudus: An titouroù a c'hallfe bezañ prevez pe kizidik a zo skarzhet ent-emgefreek. Pa vez skarzhet an titouroù mod-se e c'hall bezañ diaesoc'h da ziskoulmañ ur gudenn.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Danevelliñ ur gudenn gant ur sil", + "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 c'hoazh mar plij.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Bemdez e vez hizivaet ar rolloù siloù. Gwiriit ma n'eo ket bet diskoulmet ho kudenn c'hoazh er rolloù siloù nevesañ.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Gwiriit ma chom ar gudenn goude bezañ adloc'het ar bajenn gudennek.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Chomlec'h ar bajenn web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Ar bajenn web-mañ…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Dibab ur seurt --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Diskouez a ra bruderezh pa restachoù bruderezh", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Gwiskadoù pe saotradurioù all en deus", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Diskoachañ a ra uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Kudennoù a-fed prevezded he deus", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Ne ya ket mat en-dro p'eo enaouet uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Digeriñ a ra ivinelloù pe prenestroù noazus", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Merkañ ar bejenn evel \"NSFW\" (“Not Safe For Work”) hag a dalv ez eus danvez noazus pe kizidik enni", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Politikerezh prevezded", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Deizlevr ar cheñchamantoù", + "description": "" + }, + "aboutCode": { + "message": "Kod mammenn (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Kenlabourerien", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kod mammenn", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Troidigezhioù", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Rolloù ar siloù", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dalc'hioù diavaez (a glot gant GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Ar rolloù siloù a zo da uBO e-unan a zo herberc'hiet digoust war ar CDNoù-mañ:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Graet e vez gant ur CDN dre zegouezh pa vez ezhomm hizivaat ur roll siloù.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Ezporzhiañ war-zu ur restr…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ma-roadennoù-ublock_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Adsevel diwar ur restr…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Adlakaat an arventennoù dre ziouer…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Hoc'h arventennoù a vo erlec'hiet gant ar roadennoù bet gwaredet d'an/ar {{time}}, goude-se ec'h adloc'ho uBlock₀.\n\nKenderc'hel gant an oberiadenn-se?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "N'haller ket lenn ar roadennoù pe direizh ez int", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Skarzhet e vo hoc'h arventennoù hag adloc'het uBlock₀.\n\nHa fellout a ra deoc'h adderaouekaat arventennoù uBlock₀?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Fazi rouedad: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Fellout a ra deoc'h ouzhpennañ an URL-mañ d'ho rolloù siloù?\n\nTitl: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Koumanantiñ", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ur vunutenn zo", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} v/munutenn zo", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "un eurvezh zo", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} eur zo", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "un devezh zo", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} deiz zo", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Diskouez an daolenn-vourzh", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Gwelet deizlevr ar rekedoù", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "enaouet", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pajenn stanket", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin en deus miret ar bajenn-mañ da gargañ:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Stanket eo bet abalamour d'ar sil-mañ:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "kuit a arventennoù", + "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": "Hag a vez kavet e-barzh:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Distreiñ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Serriñ ar prenestr-mañ", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Arabat kemenn din diwar-benn al lec'hienn-mañ en-dro", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Lazhañ ar stankañ strizh evit {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "berrbad", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Da badout", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Kenderc'hel", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Ezporzhiañ etrezek stokañ ar goumoulenn (cloud)", + "description": "tooltip" + }, + "cloudPull": { + "message": "Enporzhiañ diouzh stokañ ar goumoulenn (cloud)", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Enporzhiañ adalek ar goumoulenn ha kendeuziñ gant an arventennoù a-vremañ", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Anv an ardivink-mañ:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Diwallit! Kemmit an arventennoù araokaet-mañ nemet ma ouifec'h petra emaoc'h oc'h ober.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Kas", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Lakaat da dalvezout", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Nullañ", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "eizhbitoù", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Stankañ an elfenn er framm…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Koumanantiñ d'ar roll siloù…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Aotren elfennoù media pounner evit ar mare", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Diskouez ar c'hod mammenn…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Enankit ur verradenn", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Prennañ/dibrennañ an dibunañ", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Eilañ er golver", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Diuzañ an holl", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Enaouiñ ar silañ kenedel", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Distanañ ar mod stankañ", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Spas stokañ implijet: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klikañ evit kargañ", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Fazioù: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Ur fazi silañ zo bet en ur lañsañ ar merdeer. Adkargit ar bajenn evit ma vo silet mat.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/bs/messages.json b/src/_locales/bs/messages.json new file mode 100644 index 0000000..79a2fbe --- /dev/null +++ b/src/_locales/bs/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Konačno, efikasan bloker. Štedljiv na procesoru i memoriji.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Kontrolna ploča", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Upozorenje! Imate nesačuvane promjene", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Ostani", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignoriši", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Postavke", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Liste filtera", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Moji filteri", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Moja pravila", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Bijela lista", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Prečice", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logiranje", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O aplikaciji", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Podrška", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Pregled sadržaja", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Napredne postavke", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: onemogućite/omogućite uBlock₀ za ovaj sajt.\n\nCtrl+klik: onemogućite µBlock₀ samo za ovu stranicu.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknite da onemogućite uBlock₀ za ovaj sajt.\n\nCtrl+klik da onemogućite uBlock₀ samo za ovu stranicu.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknite da omogućite uBlock₀ za ovaj sajt.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "zahtjeva blokirano", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na ovoj stranici", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od instalacije", + "description": "English: since install" + }, + "popupOr": { + "message": "ili", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokirano na ovoj stranici", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokirano od instalacije", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domena povezano", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Otvori kontrolnu ploču", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Pokrenite režim za odabiranje i uklanjanje elemenata", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Pokrenite režim za odabiranje elemenata", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Otvorite zapisnik", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Prijavite problem na ovoj web stranici", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Uključite/isključite sve iskačujuće prozore na ovoj stranici", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknite da blokirate sve iskačujuće prozore na ovoj stranici", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknite da više ne blokirate sve iskačujuće prozore na ovoj stranici", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Uključite/isključite blokiranje velikih medijskih elemenata za ovaj sajt", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknite da blokirate velike medijske elemente na ovom sajtu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknite da više ne blokirate velike medijske elemente na ovom sajtu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Uključite/isključite estetsko filtriranje za ovaj sajt", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknite da isključite estetsko filtriranje za ovaj sajt", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknite da uključite estetsko filtriranje za ovaj sajt", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Uključite/isključite blokiranje udaljenih fontova za ovaj sajt", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknite da blokirate udaljene fontove na ovom sajtu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknite da više ne blokirate udaljene fontove na ovom sajtu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kliknite da isključite JavaScript na ovom sajtu", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kliknite da uključite JavaScript na ovom sajtu", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-Up prozor", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Veliki medijski elementi", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Estetsko filtriranje", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Udaljeni fontovi", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Više", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Manje", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globalna pravila: ovaj stupac je za pravila koja su primjenjena za sve sajtove.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknite da vaše promjene učinite trajnim.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknite da biste vratili promjene.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "sve", + "description": "" + }, + "popupImageRulePrompt": { + "message": "slike", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Treće strane", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/slike trećih strana", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "umetnute skripte", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Korisničke skripte", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skripte trećih strana", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Okviri trećih strana", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "povezane domene", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} od {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Verzija", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skripta", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "okvir", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Kreiraj", + "description": "English: Create" + }, + "pickerPick": { + "message": "Odaberi", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Zatvori", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Pregled", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Mrežni filteri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Estetski filteri", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokiraj elemenat…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Sakrij držače blokiranih elemenata", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Prikaži broj blokiranih zahtjeva na ikoni", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Isključi savjete", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Koristite kontekstni meni gdje je prikladno", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Mod za daltoniste", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Izgled", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Prilagođena prikazna boja", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Uključi podršku za pohranu u oblaku", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ja sam napredni korisnik (obavezna literatura)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Onemogućite predučitavanje (da bi ste spriječili bilo koju vezu za blokirane mrežne zahtjeve)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Onemogućite provjeravanje hiperlinkova", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Spriječite WebRTC da propušta lokalnu IP adresu", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Podrazumijevano ponašanje", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ova podrazumijevana ponašanja mogu biti poništena posebno po stranici", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Onemogućite estesko filtriranje", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokirajte medijske elemente veće od {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokirajte udaljene fontove", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Islkjučite JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokirajte CSP izvještaje", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Otkrijte kanonske nazive", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Napredno", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkcije prikladne samo za napredne korisnike", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "napredne postavke", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Posljednji prijašnji povratak:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Posljednja rezervna kopija:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} mrežni/ih filter/a + {{cosmeticFilterCount}} estetski/ih filter/a iz:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} iskorišteno od {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatski ažuriraj popise filtera", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Ažuriraj sada", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Obriši svu predmemoriju", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Raščlanite i primijenite estetske filtre.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Estetski filteri služe za sakrivanje elementa na web stranici koji se smatraju izglednim smjetnjama, i koji ne mogu biti blokirani filterima zasnovanih od mrežnih zahtjeva.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorišite opće estetske filtere.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Opći estetski filteri su onakvi estetski filteri koji su namijenjeni za primjenu na svim sajtovima. Uključivanjem ove postavke će se eliminirati dodatna upotreba memorije i procesora na sajtovima kao rezultat upravljanja općih estetskih filtera.\n\nPreporučeno je omogućiti ovu postavku na slabijim uređajima.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Obustavite mrežnu aktivnost dok se ne učitaju svi popisi filtera", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista blokiranih hostova", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Primijenite promjene", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Ugrađeno", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklame", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privatnost", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Zlonamjerne domene", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Smetnje", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Višenamjenski", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regije, jezici", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Prilagođeno", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Uvezi…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Jedan URL po redu. Neispravni URL-ovi će biti tiho ignorisani.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zastarjelo.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "prikaži sadržaj", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Posljednje ažuriranje: {{ago}}.\nKliknite za biste prisilili ažuriranje.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ažuriranje u toku…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Mrežna greška je spriječila ažuriranje resursa.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Jedan filter po redu. Filter može biti običan naziv domaćina/hosta ili filter kompatibilan sa EasyList-om. Redovi sa prefiksom ! će biti ignorisani.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nemojte dodavati filtere iz nepouzdanih izvora.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Uvezi i dodaj", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Izvezi", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "moji-ublock-statični-filteri_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Primijenite promjene", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Trajna/Stalna pravila", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Privremena pravila", + "description": "header" + }, + "rulesRevert": { + "message": "Vrati", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Potvrdi", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Uredi", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Spremi", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Odbaci", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Uvezi iz datoteke…", + "description": "" + }, + "rulesExport": { + "message": "Izvezi u datoteku", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "moja-ublock-dinamična-pravila_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista vaših dinamičkih pravila za filtriranje.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Pravila sintakse: izvor odredište tip akcija (sva dokumentacija).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortiraj:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Vrsta/tip pravila", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Izvor", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinacija/odredište", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Direktive pouzdanih sajtova kažu na kojim sajtovima bi uBlock Origin trebao biti isključen. Jedna stavka po redu.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Uvezi i dodaj", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Izvezi", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "moji-ublock-pouzdani-sajtovi_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Primijenite izmjene", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Vrsta", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domena", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Sve", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Bez tabova", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Trenutni tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Ponovo učitaj sadržaj taba", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Uključite/isključite DOM inspektor", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Uključite/isključite okno za skočne prozore", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: zapisnik", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Očistite zapise", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pauzirajte zapise (odbacite sve dolazne podatke)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Pokrenite zapise", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Uključite/isključite filtriranje zapisa", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrirajte sadržaj zapisa", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Postavke filtriranja zapisa", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nije", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "puno događaja", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokirano", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "dozvoljeno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "Izmjenjeno:", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Prve strane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Treće strane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalji", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista filtera", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Pravilo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Korijenski kontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Pripadna informacija", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Vrsta", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL pravilo", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Vrsta:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statični filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} mrežni zahtjevi {{type}} {{br}} od čiji se URL adresa slaže sa {{url}} {{br}} i koji izvire od {{origin}},{{br}}{{importance}} postoji odgovarajući odstupni filter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokiraj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Dozvoli", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "vrsta “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "bilo koja vrsta", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "od “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "od bilo kuda", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "osim kada", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "čak iako", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statični filter {{filter}} pronađen u:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statični filter nije pronađen u nijednoj od trenutno uključenih filterskih listi", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Unosi u bilješku koji ne ispunjavaju sva tri navedena uvjeta/uslova ispod će biti automatski odbačeni:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Spremite unose iz zadnje/ih {{input}} minute/a", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Spremite najviše {{input}} učitavanja stranica po kartici", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Spremite najviše {{input}} unosa po kartici", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Koristi {{input}} linija po unosu u vertikalno proširenom režimu", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sakrij stubove:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Vrijeme", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/pravilo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Strana/Pripadnost", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Popis/Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tablica", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Obično", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Otvori", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Napravite novu prijavu", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Pronađite slične prijave", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacija", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Pročitajte dokumentaciju na uBlock/wiki da bi ste naučili sve o uBlock Origin-ovim funkcijama.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Pitanja i podrška", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odgovori na pitanja i druge vrste podrške nalaze se na podreditu r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemi sa filterom/website ne radi", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Prijavite probleme s filtriranjem određenih web stranica na uBlockOrigin/uAssets stranici za praćenje problema. Potreban će vam biti GitHub račun.\n\n", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Važno: Nemojte koristiti druge blokere slične namjene zajedno sa uBlock Origin-om, jer bi to moglo uzrokovati probleme s filtriranjem na određenim web stranicama.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Savjeti: Provjerite jesu li vaše liste filtera ažurirane. Zapisnik je primarni alat za dijagnosticiranje problema povezanim sa filterima.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Prijava greške", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Prijavite probleme sa samim uBlock Origin-om na uBlockOrigin/uBlock-problem stranici za praćenje problema. Potreban če vam biti GitHub račun.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informacija o rješavanju problema", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Ispod se nalaze tehničke informacije koje bi vam mogle biti korisne kada vam dobrovoljci pokušavaju pomoći s rješenjem problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Važno: Moguće privatna ili osjetljiva informacija je prema zadanim postavkama automatski zaklonjena. Zaklonjene informacije mogu otežati rješavanju problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Prijavite problem sa filterom", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Liste filtera se ažuriraju svakodnevno. Budite sigurni da vaš problem nije već riješen na najnovijim listama filtera.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Provjerite postoji li problem i nakon ponovnog učitavanja problematične web stranice.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa web stranice:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Web stranica…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Odaberite unos --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Pokaže oglase ili ostatke oglasa", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ima prekrive ili druge dosade", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Otkrije uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ima probleme povezane za privatnost", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Kvari se kad je uBlock Origin uključen", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Otvara neželjene kartice ili prozore", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Označite web stranicu kao “NSZP” (“Ne-Sigurna-Za-Posao”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Zakloni", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Odzakloni", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Pravila privatnosti", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Popis izmjena", + "description": "" + }, + "aboutCode": { + "message": "Izvorni kod (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Saradnici", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Izvorni kod", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Prijevodi", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Liste filtera", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Vanjske zavisnosti (GPLv3-kompatiblini):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Sopstveni zapisi filtera uBO-a su besplatno hostani na sljedećim CDN-ovima:\n", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Slučajno odabrani CDN će biti korišten kada zapis filtera treba biti ažuriran", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sačuvaj rezervnu kopiju u datoteku", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "moja-ublock-rez_kopija_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Vrati iz datoteke…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Vrati na izvorne postavke…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Sve vaše postavke će je biti prebrisane koristeći rezervnu kopiju sa postavkama sačuvanim {{time}}, i uBlock₀ će se ponovno pokrenuti. \n\nPrepisati sve postojeće postavke sa rezervnom kopijom postavki?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Podatke nije moguće učitati ili su neispravni", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Sve vaše postavke će je biti obrisane i µBlock₀ će se ponovo pokrenuti. \n\nVrati µBlock₀ na izvorne postavke?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Greška sa mrežom: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Dodajte slijedeću URL adresu u vašu listu prilagođenih filtera?\n\nNaziv: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Pretplatite se", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "prije minutu", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "prije {{value}} minute/a", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "prije sat vremena", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "prije {{value}} sata/i", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "prije jedan dan", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "prije {{value}} dana", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Prikaži kontrolnu ploču", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Pokaži zapisnik", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "isključen", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Stranica je blokirana", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin je onemogućio učitavanje sljedeće stranice:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Zbog sljedećeg filtera", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametara", + "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": "Pronađeno u:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Nazad", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zatvori ovaj prozor", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ne upozoravaj me ponovo za ovu stranicu", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Isključi strogo blokiranje za {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Privremeno", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Trajno", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Nastavi", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Izvezi u cloud pohranu", + "description": "tooltip" + }, + "cloudPull": { + "message": "Uvezi iz cloud pohrane", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Uvezite iz cloud pohrane i spojite sa trenutnim postavkama", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Naziv ovog uređaja:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Upozorenje! Napredne postavke mijenjate na vlastitu odgovornost.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Pošalji", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Primijeni promjene", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Vrati", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajta", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokiraj elemenat u okviru…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Pretplatite se na popis filtera…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Privremeno omogući velike medijske elemente", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Pogledaj izvorni kod…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Upišite prečicu", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "(De)aktivacija zaključanog pomicanja", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiraj u međuspremnik", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Označi sve", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Uključi/isključi estetsko filtriranje", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaksiran mod blokiranja", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Iskorišten prostor: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kliknite za učitavanje", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Greške: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Nije moguće ispravno filtrirati pri pokretanju preglednika. Ponovo učitajte stranicu kako biste osigurali pravilno filtriranje.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Ova stavka mora biti posljednja", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json new file mode 100644 index 0000000..be806f7 --- /dev/null +++ b/src/_locales/ca/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finalment, un blocador eficient que utilitza pocs recursos de memòria i processador.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Tauler de control", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Atenció! Hi ha canvis sense desar", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Roman", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignora", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Configuració", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtres de tercers", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Els vostres filtres", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Les meves regles", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Llista blanca", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Dreceres", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Registre de peticions de xarxa", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Quant a", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Ajuda", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visor de recursos", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Configuració avançada", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clic: habilita/inhabilita l'uBlock₀ per a aquest lloc.\n\nCtrl+clic: inhabilita l'uBlock₀ només en aquesta pàgina.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Feu clic per inhabilitar l'uBlock₀ en aquest lloc.\n\nFeu Ctrl+clic per inhabilitar l'uBlock₀ només en aquesta pàgina.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Feu clic per habilitar l'uBlock₀ en aquest lloc.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "sol·licituds bloquejades", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "en aquesta pàgina", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} o {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "des de la instal·lació", + "description": "English: since install" + }, + "popupOr": { + "message": "o", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocat en aquesta pàgina", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocat des de la instal·lació", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Dominis connectats", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Clic per obrir el tauler de control", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Activa el mode d'eliminació d'elements", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Canvia al mode de selecció d'elements", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Obre el registre d'esdeveniments", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Informeu d'un problema en aquest lloc web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Commuta el bloqueig de totes les finestres emergents d'aquest lloc", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Feu clic per blocar totes les finestres emergents d'aquest lloc", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Feu clic per desblocar les finestres emergents d'aquest lloc", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Commuta el bloqueig d'elements multimèdia grans per a aquest lloc", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Feu clic per blocar elements multimèdia grans en aquest lloc", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Feu clic per desblocar elements multimèdia grans en aquest lloc", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Commuta els filtres cosmètics d'aquest lloc", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Feu clic per inhabilitar els filtres cosmètics en aquest lloc", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Feu clic per habilitar els filtres cosmètics en aquest lloc", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Commuta el bloqueig de fonts remotes per a aquest lloc", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Feu clic per blocar les fonts remotes en aquest lloc", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Feu clic per desblocar les fonts remotes en aquest lloc", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Feu clic per inhabilitar completament el JavaScript en aquest lloc", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Feu clic per no inhabilitar el JavaScript en aquest lloc", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Finestres emergents", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elements multimèdia grans", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtres cosmètics", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fonts remotes", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Més", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menys", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Regles globals: les regles d'aquesta columna s'apliquen a tots els llocs.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Feu clic per fer els canvis permanents.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Feu clic per desfer els canvis.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "tot", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imatges", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "de tercers", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "css/imatges de tercers", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripts incrustats", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts de tercers", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "marcs de tercers", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "dominis connectats", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versió", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "marc", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Crear", + "description": "English: Create" + }, + "pickerPick": { + "message": "Escollir", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Sortir", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Vista prèvia", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtres de xarxa", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtres cosmètics", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clic, Ctrl+clic", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloca l'element", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Amaga els marcadors de posició dels elements blocats", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Mostra el número de peticions blocades a l'icona", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Inhabilita els suggeriments", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Utilitzar el menú contextual quan sigui possible", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Configuració per a persones daltòniques", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aparença", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Color d'accent personalitzat", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Habilita el suport d'emmagatzematge al núvol", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Sóc un usuari avançat (lectura necessària)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Inhabilita la cerca prèvia (per evitar qualsevol connexió de xarxa per a sol·licituds blocades)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Inhabilita l'auditoria de l'enllaç", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Evita que el protocol WebRTC divulgui la IP local", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportament per defecte", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Es pot anul·lar el comportament per defecte per a qualsevol web", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Inhabilita els filtres cosmètics", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloca els fitxers multimèdia més grans que {{input:number}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloca les fonts remotes", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Inhabilita el JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloca els informes CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Revela els noms canònics", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avançat", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Característiques adequades només per a usuaris tècnics", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "configuració avançada", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Darrera restauració:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Darrera còpia de seguretat:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtres de xarxa + {{cosmeticFilterCount}} filtres cosmètics de:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} utilitzats de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Actualitzar automàticament la llista de filtres.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Actualitza ara", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Neteja la memòria caché", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analitzar i aplicar filtres cosmètics.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Aquesta opció permet l'anàlisi i l'aplicació dels filtres compatibles amb l'Adblock Plus “element hiding”. Aquests filtres són principalment cosmètics, que serveixen per amagar elements d'una pàgina web molestos que per defecte no es poden amagar.

Habilitant aquesta opció augmentarà el consum de memòria de l'µBlock.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignora els filtres cosmètics genèrics", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Els filtres cosmètics genèrics són filtres que no s'apliquen a tots els llocs web.

Tot i que l'uBlock₀ els gestiona de manera eficient, aquests filtres encara poden contribuir a un augment d'ús de la memòria o sobrecàrrega de la CPU en algunes pàgines web, especialment si tenen molt contingut, elements d'animació o temps real.

En habilitar aquesta opció s'elimina el risc de sobrecàrrega a la CPU i excés d'ús de la memòria com a resultat de la manipulació de filtres cosmètics genèrics i també es redueix el consum de memòria de l'uBlock₀.

Es recomana habilitar aquesta opció en dispositius poc potents.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspèn l'activitat de la xarxa fins a carregar totes les llistes de filtres", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Llistes de servidors bloquejats", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar canvis", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Local", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Anuncis", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacitat", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Dominis perillosos", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Elements molestos", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Polivalent", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, llengües", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalitzat", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importa...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Una URL per línia. S'ignoraran les línies amb el símbol ‘!’. Les URL no vàlides s'ignoraran silenciosament.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Obsolet", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "mostra el contingut", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Darrera actualització: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "S'està actualitzant...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Un error de xarxa va impedir que s'actualitzés el recurs.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Un filtre per línia. Un filtre pot ser un domini, o un filtre compatible amb l'Adblock Plus. S'ignoraran les línies amb el símbol ‘!’.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "No afegiu filtres de fonts no confiables.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importa i annexa", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exporta", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-custom-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar canvis", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Normes permanents", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Normes temporals", + "description": "header" + }, + "rulesRevert": { + "message": "Desfer", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Establir", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Editar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Desar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Descartar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importa des del fitxer...", + "description": "" + }, + "rulesExport": { + "message": "Exporta a...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Llista de regles de filtrat dinàmic.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaxi de les regles: origen destinació tipus acció (documentació).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordena:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipus de regla", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Origen", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinació", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Llistat dels noms de servidor amb que s'inhabilitarà l'µBlock. Una entrada per línia. S'ignoraran els noms de servidor no vàlids.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importa i annexa", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exporta", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "Llista-blanca-de-l'ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar canvis", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipus", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domini", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtre", + "description": "English: Filter" + }, + "logAll": { + "message": "Tot", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Peticions amagades", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Pestanya actual", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Torna a carregar el contingut de la pestanya", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Commuta l'inspector DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Commuta el menú emergent", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "Wiki - uBlock Origin: L'informe", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Neteja l'informe", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausa el registre de l'informe (descarta qualsevol data entrant)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Continua creant el registre", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Commuta el filtratge del registre", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtra entrades del registre", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opcions de filtratge del registre", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Cap", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "important", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permès", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "primari", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "de tercers", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalls", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtre", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Llista de filtres", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regla", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Context arrel", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Petició", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipus", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Filtre dinàmic d'URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipus:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtre estàtic", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} peticions de la xarxa {{type}} {{br}}amb l'URL coincidint {{url}} {{br}}originada des de {{origin}},{{br}}{{importance}} si és una concordança d'un filtre d'excepció.\nhttps://github.com/gorhill/uBlock/issues/235#issuecomment-109745745.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloca", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permet", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipus «{{type}}»", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "de qualsevol tipus", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "des de «{{origin}}»", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "des de qualsevol web", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "excepte", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "fins i tot", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "S'ha trobat el filtre estàtic {{filter}} a:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "No s'ha trobat el filtre estàtic {{filter}} a cap de les llistes de filtres actualment habilitades", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Les entrades del registrador que no compleixin les tres condicions següents es rebutjaran automàticament:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Conserva les entrades dels darrers {{input}} minuts", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Conserva com a màxim {{input}} càrregues de pàgina per pestanya", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Conserva com a màxim {{input}} entrades per pestanya", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Utilitza {{input}} línies per entrada en mode expandit verticalment", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Amaga les columnes:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Temps", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtre/regla", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "Petició de {{input}}", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Llista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Taula", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Text pla", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Obre", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Crea un informe nou", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Cerca d'informes semblants", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentació", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Llegiu la documentació a uBlock/wiki per obtenir informació sobre totes les funcions de l'uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Preguntes i suport", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Les respostes a preguntes i altres tipus d’ajuda es proporcionen al subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemes de filtre/lloc web trencat", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Informeu de problemes de filtres amb llocs web específics al uBlockOrigin/uAssets rastrejador de problemes. Requereix un compte de GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Important: eviteu utilitzar altres bloquejadors amb propòsits similars juntament amb l'uBlock Origin, ja que això pot causar problemes de filtratge en llocs web específics.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Consells: Assegureu-vos que les vostres llistes de filtres estiguin actualitzades. El registrador és l’eina principal per diagnosticar problemes relacionats amb els filtres.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Informe d'errors", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Informeu de problemes amb el propi uBlock Origin al uBlockOrigin/uBlock-issue rastrejador de problemes . Requereix un compte de GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informació de resolució de problemes", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "A continuació es mostra informació tècnica que pot ser útil quan els voluntaris intenten ajudar-vos a resoldre un problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Per defecte es redacta informació potencialment privada o confidencial. La informació redactada pot dificultar la resolució d'un problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Informeu d'un problema de filtre", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Per evitar carregar els voluntaris amb informes duplicats, verifiqueu que el problema encara no s'hagi notificat.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Les llistes de filtres s'actualitzen diàriament. Assegureu-vos que el vostre problema encara no s'hagi resolt amb les llistes de filtres més recents.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Comproveu que el problema encara existeix després de recarregar la pàgina web problemàtica.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adreça de la pàgina web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "La pàgina web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Trieu una entrada --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Mostra anuncis o restes d'anuncis", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Té superposicions o altres errors", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detecta l'uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Té problemes relacionats amb la privadesa", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "No funciona amb l'uBlock Origin habilitat", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Obre pestanyes o finestres no desitjades", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Marca aquesta pàgina com a “NSFW” (“No segur per al treball”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redacta", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "No redactis", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Política de privadesa", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Registre de canvis", + "description": "" + }, + "aboutCode": { + "message": "Codi font (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Col·laboradors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Codi font", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduccions", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Llistat de filtres", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependències externes (compatibles amb GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Les llistes de filtres pròpies d'uBO s'allotgen lliurement als següents CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "S'utilitzarà un CDN triat a l'atzar quan calgui actualitzar una llista de filtres", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Còpia de seguretat a un fitxer", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaura des d'un fitxer...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Restaura als valors per defecte...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "La configuració es sobreescriurà amb la còpia de seguretat del {{time}}, i l'uBlock₀ es reiniciarà.\n\nVoleu restaurar la configuració amb la còpia de seguretat?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Les dades no es poden llegir o no son vàlides", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "La configuració serà suprimida i es reiniciarà l'uBlock₀.\n\nVoleu reiniciar l'uBlock₀ als valors per defecte?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Error de xarxa: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Voleu afegir aquest URL a la llista de filtres personalitzats?\n\nTítol: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscriu-me", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "fa un minut", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "fa {{value}} minuts", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "fa una hora", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "fa {{value}} hores", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "fa un dia", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "fa {{value}} dies", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Mostrar Tauler de control", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Mostra el registre d'esdeveniments", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "desactivat", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pàgina blocada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "L'uBlock Origin ha impedit que es carregui la pàgina:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Detectat per aquest filtre", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sense paràmetres", + "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": "Trobat a:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Enrere", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Tanca aquesta finestra", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "No em tornis a avisar sobre aquest lloc", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Inhabilita el blocatge estricte per {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporalment", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentment", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Procedeix", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exporta a un servei al núvol", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importa des d'un servei al núvol", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importa des del núvol i afegeix a la configuració actual", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nom d'aquest dispositiu:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Atenció! Canvieu aquestes configuracions avançades sota la vostra responsabilitat.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Envia", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplica els canvis", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Desfés", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloca l'element al marc...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Uniu-vos a la llista de filtres... ", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permet temporalment els fitxers multimèdia grans", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Mostra el codi font…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Escriviu una drecera", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Commuta el desplaçament blocat", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copia al porta-retalls", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Selecciona-ho tot", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Commuta els filtres cosmètics", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Mode de bloqueig relaxat", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Emmagatzematge utilitzat: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clic per carregar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "No s'ha pogut filtrar correctament en iniciar el navegador.\nTorneu a carregar la pàgina per garantir un filtratge correcte", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Aquesta entrada ha de ser l'última", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json new file mode 100644 index 0000000..e25baf5 --- /dev/null +++ b/src/_locales/cs/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Konečně efektivní blokovač. Nezatěžuje CPU a paměť.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Ovládací panel", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Varování! Máte neuložené změny", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Zůstat", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorovat", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Nastavení", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtry třetích stran", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Vaše filtry", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Vaše pravidla", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Povolené domény", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Zkratky", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Protokol požadavků", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O rozšíření", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Podpora", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Prohlížeč zdrojů", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Pokročilá nastavení", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Kliknutí: trvale zakázat uBlock₀ pro celý tento web.\n\nCtrl+kliknutí: zakázat uBlock₀ pouze pro tuto stránku.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknutí: trvale zakázat uBlock₀ pro celý tento web.\n\nCtrl+kliknutí: zakázat uBlock₀ pouze pro tuto stránku.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknutím povolíte uBlock₀ pro tento web.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "zablokované požadavky", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na této stránce", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} neboli {{percent}} %", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od instalace", + "description": "English: since install" + }, + "popupOr": { + "message": "neboli", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Zablokováno na této stránce", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Zablokováno od instalace", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Počet připojených domén", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Otevřít ovládací panel", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Zapnout režim likvidace prvků", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Zapnout režim výběru prvků", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Otevřít protokol požadavků", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Nahlásit problém na této webové stránce", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Přepnout blokování všech vyskakovacích oken na tomto webu", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknutím zablokujete všechny popupy pro tento web", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknutím vypnete blokování všech popupů pro tento web", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Přepnout blokování velkých multimediálních prvků na tomto webu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknutím zablokujete velké multimediální prvky na tomto webu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknutím vypnete blokování velkých multimediálních prvků na tomto webu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Přepnout kosmetické filtrování na tomto webu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknutím zakážete kosmetické filtrování na tomto webu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknutím povolíte kosmetické filtrování na tomto webu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Přepnout blokování vzdálených fontů pro tento web", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknutím zablokujete externí/vzdálené fonty na tomto webu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknutím vypnete blokování externích/vzdálených fontů na tomto webu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kliknutím zakážete JavaScript na této stránce", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kliknutím znovu povolíte JavaScript na této stránce", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Vyskakovací okna", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Velké multimediální prvky", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetické filtrování", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Vzdálená písma", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Více", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Méně", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globální pravidla: tento sloupec slouží pro pravidla, která platí pro všechny weby.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokální pravidla: tento sloupec slouží pro pravidla, která platí pouze pro aktuální web.\nLokální pravidla přepisují globální pravidla.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknutím natrvalo uložíte provedené změny.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknutím zrušíte provedené změny.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "vše", + "description": "" + }, + "popupImageRulePrompt": { + "message": "obrázky", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "z třetí strany", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/obrázky třetích stran", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "řádkové skripty", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skripty první strany", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skripty třetích stran", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "rámce třetích stran", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domén připojeno", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} z {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Verze", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "rámec", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Vytvořit", + "description": "English: Create" + }, + "pickerPick": { + "message": "Vybrat", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Ukončit", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Náhled", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Síťové filtry", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetické filtry", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Kliknutí, Ctrl+Kliknutí", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Zablokovat prvek", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Skrýt zástupné objekty zablokovaných prvků", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Zobrazit počet blokovaných požadavků u ikony", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Skrýt nápovědu při najetí", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Využít kontextovou nabídku kde je to možné", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Styl pro barvoslepé", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Vzhled", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Motiv", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Vlastní barva motivu", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Povolit podporu cloudového úložiště", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Jsem pokročilý uživatel (nutno přečíst)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Zakázat přednačítání (zakáže jakékoliv spojení pro zablokované síťové požadavky)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Vypnout auditování hypertextových odkazů", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Předejít úniku lokálních IP adres přes WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Výchozí chování", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Tato výchozí chování mohou být přepsána u jednotlivých webů", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Zakázat kosmetické filtrování", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokovat multimediální prvky větší než {{input}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokovat externí fonty", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Zakázat JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokovat CSP reporty", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Odkrýt kanonická jména", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Pokročilé", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkce vhodné pouze pro pokročilé uživatele", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "pokročilá nastavení", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Poslední obnova:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Poslední záloha:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} síťových filtrů + {{cosmeticFilterCount}} kosmetických filtrů z:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} použito z celkových {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automaticky aktualizovat seznamy filtrů.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Aktualizovat nyní", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Vyčistit celou mezipaměť", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Zpracovat a použít kosmetické filtry.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "\nKosmetické filtry slouží ke skrytí prvků na webové stránce, které jsou považovány za vizuálně obtěžující a které nemohou být blokovány filtry na základě síťových volání.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorovat obecné kosmetické filtry", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Obecné kosmetické filtry jsou takové kosmetické filtry, které jsou určeny k použití na všech webových stránkách. Povolení této možnosti odstraní nadbytečnou režii paměti a procesoru, přidanou na webové stránky v důsledku manipulace s obecnými kosmetickými filtry.\n\nTuto možnost doporučujeme povolit na méně výkonných zařízeních.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Pozastavit síťové aktivity, dokud se nenačtou všechny seznamy filtrů.", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Seznamy blokovaných hostitelů", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Použít změny", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Zabudované", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamy", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Soukromí", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Ochrana před malwarem, bezpečnost", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Dotěrnosti", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Víceúčelové", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regionální, jazykové", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Vlastní", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importovat…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Jedna URL adresa na řádek. Neplatné URL adresy budou tiše ignorovány.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zastaralé.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Zobrazit obsah", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Poslední aktualizace: {{ago}}.\nKliknutím vynutíte aktualizaci.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Aktualizuji…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Chyba sítě znemožnila aktualizaci tohoto zdroje.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Jeden filtr na řádek. Filtr může být prostý název hostitele nebo filtr kompatibilní s EasyList. Řádky začínající vykřičníkem ! budou ignorovány.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nepřidávejte filtry z nedůvěryhodných zdrojů.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importovat a připojit…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportovat…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-me-vlastni-filtry_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Použít změny", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanentní pravidla", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Dočasná pravidla", + "description": "header" + }, + "rulesRevert": { + "message": "Vrátit", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Potvrdit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Upravit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Uložit", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Zrušit", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Načíst ze souboru…", + "description": "" + }, + "rulesExport": { + "message": "Exportovat do souboru…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-ma-dynamicka-pravidla_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Seznam vašich pravidel pro dynamické filtrování.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Syntaxe pravidel: zdroj destinace typ akce (kompletní dokumentace).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Třídit:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Typ pravidla", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Zdroj", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Cíl", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Pravidla v seznamu povolených domén určují, pro které webové stránky bude uBlock Origin vypnutý. Jedna položka na řádek.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importovat a připojit", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportovat", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-muj-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Použít změny", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Typ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Doména", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtr", + "description": "English: Filter" + }, + "logAll": { + "message": "Všechny stránky", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Za oponou", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktivní list", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Znovu načíst obsah listu", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Přepnout DOM inspektor", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Přepnout vyskakovací panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Vyčistit logger", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Zastavit logování (ignorovat všechny příchozí údaje)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Pokračovat v logování", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Přepnout filtrování loggeru", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrovat obsah loggeru", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Možnosti filtrování loggeru", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Není", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokováno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "povoleno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "upraveno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "vlastní doména", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "třetí strany", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Podrobnosti", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtr", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Seznam filtrů", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Pravidlo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontext", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Kořenový kontext", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Strana", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Typ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dynamické filtrování URL adres", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontext:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Typ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statický filtr", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} síťové požadavky {{type}} {{br}}jejichž URL adresa se shoduje s {{url}} {{br}}a pochází {{origin}},{{br}}{{importance}} shodný výjimkový filtr.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokovat", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Povolit", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "typu “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "jakéhokoliv typu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "z “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "odkudkoliv", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "pokud neexistuje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "i když existuje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statický filtr {{filter}} nalezen v seznamech:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statický filtr {{filter}} nebyl nalezen v žádném aktuálně povoleném seznamu filtrů", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Záznamy logu, které nesplní všechny uvedené podmínky, budou automaticky zahozeny:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Zachovat záznamy z posledních {{input}} minut", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Zachovat nejvýše {{input}} načtení stránky pro list", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Zachovat nejvýše {{input}} záznamů pro list", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Použít {{input}} řádků pro jeden záznam v režimu svislého rozbalení", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Skrýt sloupce:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Čas", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtr/pravidlo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontext", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} strana", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Seznam", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabulka", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Prostý text", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Otevřít", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Vytvořit nové hlášení", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Vyhledat podobná hlášení", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentace", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Přečtěte si dokumentaci na uBlock/wiki, kde se dozvíte o všech funkcích uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Dotazy a podpora", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odpovědi na otázky a další druhy podpory jsou poskytovány na subredditu /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problémy s filtrem/web. stránka je nefunkční", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Hlášení problémů s filtrem u učitých web. stránek do uBlockOrigin/uAssets issue tracker. Vyžaduje účet GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Důležité: Nepoužívejte podobně zaměřené blokátory s uBlock Origin, může to způsobit problémy s filtry na určitých webových stránkách.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tipy: Ověřte, že jsou seznamy filtrů aktuální. Protokol je hlavní nástroj pro diagnósu problémů s filtry.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Hlášení chyb", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Hlášení problémů se samotným uBlock Origin na uBlockOrigin/uBlock-issue issue tracker. Požaduje účet GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informace o řešení problémů", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Níže jsou technické informace, které mohou být užitečné, když vám dobrovolníci pomáhají vyřešit nějaký problém.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Důležité: Potenciálně soukromé nebo citlivé informace jsou ve výchozím nastavení redigovány. Redigované informace mohou ztížit řešení problému.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Nahlásit problém s filtrem", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Abyste dobrovolníky nezatěžovali duplicitními hlášeními, ověřte si, zda již problém nebyl nahlášen.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Seznamy filtrů jsou aktualizovány denně. Ujistěte se, že váš problém již nebyl vyřešen v nejnovějších seznamech filtrů.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Ověřte, že problém přetrvává i po opětovném načtení problematické webové stránky.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa webové stránky:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Webová stránka…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Vyberte položku --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Zobrazuje reklamy nebo zbytky reklam", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Je překrytá nebo má jiné nedostatky", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detekuje uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Má problémy související se soukromím", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Je rozbitá, když je povolen uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Otevírá nechtěné karty nebo okna", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Označit webovou stránku jako “NSFW” (Není bezpečné pro práci”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Upravit", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Odstranit", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Ochrana soukromí", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Přehled změn", + "description": "" + }, + "aboutCode": { + "message": "Zdrojový kód (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Přispěvatelé", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Zdrojový kód", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Překlady", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Seznam filtrů", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Externí závislosti (kompatibilní s GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Vlastní seznamy filtrů uBO jsou volně hostovány na následujících CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Při aktualizaci seznamu filtrů se použije náhodně vybraná síť CDN.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Zálohovat do souboru…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-moje-zaloha_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Obnovit ze souboru…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Obnovit výchozí nastavení…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Všechna nastavení budou přepsána těmi zálohovanými {{time}} a uBlock₀ se restartuje.\n\nPřepsat všechna existující nastavení zálohovanými daty?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Data nemohla být načtena nebo jsou neplatná", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Všechna nastavení budou smazána a uBlock₀ se restaruje.\n\nObnovit uBlock₀ do továrního nastavení?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Chyba sítě: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Přidat následující URL adresu do seznamů vlastních filtrů?\n\nNázev: „{{title}}“\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Odebírat", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "před minutou", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "před {{value}} minutami", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "před hodinou", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "před {{value}} hodinami", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "včera", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "před {{value}} dny", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Zobrazit řídící panel", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Zobrazit Zaznamenávač", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "vypnutý", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Zablokována stránka", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin zabránil následující stránce v načtení:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Kvůli následujícímu filtru", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametrů", + "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": "Nalezeno v:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Jít zpět", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zavřít toto okno", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Znova mě nevarujte ohladně této stránky", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Zakázat striktní blokování pro {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Dočasně", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Trvale", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Pokračovat", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportovat do cloudového úložiště", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importovat z cloudového úložiště", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importovat z cloudového úložiště a sloučit se současným nastavením", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Název tohoto zařízení:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Pozor! Tato pokročilá nastavení měníte na vlastní nebezpečí.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Odeslat", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Použít změny", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Vrátit", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajtů", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Zablokovat prvek v rámečku…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Přihlásit se k odběru seznamu filtrů ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Dočasně povolit velké multimediální prvky", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Zobrazit zdrojový kód…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Stiskněte zkratku", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Přepnout uzamčení posuvu", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopírovat do schránky", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Vybrat vše", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Zapnout kosmetické filtrování", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Uvolnit režim blokování", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Využití úložiště: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klikněte pro načtení", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Chyby: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Nebylo možné správně filtrovat při spuštění prohlížeče.\nNačtěte stránku znovu, abyste zajistili správné filtrování.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/cv/messages.json b/src/_locales/cv/messages.json new file mode 100644 index 0000000..55f9fb5 --- /dev/null +++ b/src/_locales/cv/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "Тинех Интернет тишкерӳҫӗ валли хӑвӑрт та витӗмлӗ чаркӑч пур.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "Йӗркелӳ ҫӳлӗкӗ", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Асӑрха! Санӑн упраман улшӑнусем пур", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ӗнерлев", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Ют фильтрсем", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Манӑн фильтрсем", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Манӑн йӗрке", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trusted sites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Сарӑм пирки", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Advanced settings", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requests blocked", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} е {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "е", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Йӗркелӳ ҫӳлӗкне уҫма пус", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Тата", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "пурте", + "description": "" + }, + "popupImageRulePrompt": { + "message": "ӳкерчӗксем", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "ют ресурссем", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "ют css/ӳкерчӗксем", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline-скриптсем", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Харпӑр скриптсем", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "ют скриптсем", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Ют фреймсем", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Create", + "description": "English: Create" + }, + "pickerPick": { + "message": "Суйласа ил", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Тух", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Эпӗ ӑста усӑҫ (Вуламасӑр иртме ҫук)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ку ӗнерлеве кашни сайт валли уйрӑм палӑртма май пур", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input:number}} КБ йывӑртарах медиа-элементсене чар", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Ют шрифтсене чар", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Юлашки тавӑру:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Халех ҫӗнет", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Чарнӑ хостсен йышӗ", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Улшӑнӑва ҫирӗплет", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Реклама", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Вӑрттӑнлӑх", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Нумай тӗллевлисем", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Регионсем, чӗлхесем", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Кивелнӗ", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Юлашки ҫӗнетӳ: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Куҫар", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-custom-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Улшӑнӑва ҫирӗплет", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Яланлӑх йӗрке", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Вӑхӑтлӑх йӗрке", + "description": "header" + }, + "rulesRevert": { + "message": "Тавӑр", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Ҫирӗплет", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Улӑштар", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Упра", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Улшӑнӑва ҫирӗплет", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тĕсĕ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Фильтр", + "description": "English: Filter" + }, + "logAll": { + "message": "Пурте", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Тӗл", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": " URL динамика фильтрацийӗ", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тĕсĕ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Чар", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Ирӗк пар", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "тĕсĕ “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": " “{{origin}}” ран", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "Кирек ӑҫтан та", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Улшӑнусен йышӗ", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Пайташсем", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "пӗр минут каялла", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} минут каялла", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "пӗр сехет каялла", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} сехет каялла", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "пӗр кун каялла", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} кун каялла", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Йӗркелӳ ҫӳлӗкне кӑтарт", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Тепӗр фильтра пула", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Тупӑннӑ:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Таврӑн", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Вӑхӑтлӑха", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Яланлăха", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Йышӑн", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Тавӑр", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байт", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Пысӑк медиа-элементсене вӑхӑтлӑха уҫ", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Ку ҫыру юлашки пулмалла", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json new file mode 100644 index 0000000..7714874 --- /dev/null +++ b/src/_locales/da/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Endelig en effektiv blocker. Lavt CPU- og hukommelsesforbrug.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Kontrolpanel", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Advarsel! Du har ændringer, der ikke er gemt", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Bliv her", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorér", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Indstillinger", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlister", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mine filtre", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mine regler", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Betroede websteder", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Genveje", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Om", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visning af aktiver", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Avancerede indstillinger", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: Deaktivér/aktivér uBlock₀ på dette websted.\n\nCtrl+klik: Deaktivér kun uBlock₀ på denne side.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klik for at deaktivere uBlock₀ på dette websted.\n\nCtrl+klik for kun at deaktivere uBlock₀ på denne side.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik for at aktivere uBlock₀ på dette websted.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokerede forespørgsler", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "på denne side", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} eller {{percent}} %", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "siden installation", + "description": "English: since install" + }, + "popupOr": { + "message": "eller", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokeret på denne side", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokeret siden installation", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Tilknyttede domæner", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Åbn kontrolpanelet", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Gå til elementdræber­tilstand", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Gå til elementvælger­tilstand", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Åbn loggeren", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Anmeld et problem med dette websted", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Aktivér/deaktivér blokering af alle popups på dette websted", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik for at blokere alle popups på dette websted", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik for ikke længere at blokere alle popups på dette websted", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Aktivér/deaktivér blokering af store medieelementer på dette websted", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik for at blokere store medieelementer på dette websted", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik for ikke længere at blokere store medieelementer på dette websted", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Slå kosmetisk filtrering til/fra for dette websted", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik for at slå kosmetisk filtrering fra på dette websted", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik for at slå kosmetisk filtrering til på dette websted", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Slå blokeringen af fjernskrifttyper til/fra for dette websted", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik for at blokere fjernskrifttyper på dette websted", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik for ikke længere at blokere fjernskrifttyper på dette websted", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klik for at deaktivere JavaScript på dette websted", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klik for ikke længere at deaktivere JavaScript på dette websted", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Popup-vinduer", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Store medieelementer", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetisk filtrering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fjernskrifttyper", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mere", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Skjul", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globale regler: Denne kolonne er til regler gældende alle websteder.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokale regler: Denne kolonne er til regler kun gældene dette websted.\nLokale regler tilsidesætter globale regler.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klik for at gøre dine ændringer permanente.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klik for at fortryde dine ændringer.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "alle", + "description": "" + }, + "popupImageRulePrompt": { + "message": "billeder", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Tredjeparts", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Tredjeparts CSS/billeder", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "indlejrede scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Førsteparts-scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Tredjeparts-scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Tredjeparts-rammer", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "forbundne domæner", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} af {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Opret", + "description": "English: Create" + }, + "pickerPick": { + "message": "Vælg", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Afslut", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Forhåndsvisning", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Netværksfiltre", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetiske filtre", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokér element...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Skjul blokerede elementers pladsholdere", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Vis antallet af blokerede forespørgsler på ikonet", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Deaktivér værktøjstips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Benyt kontekstmenuen, hvor det er relevant", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Optimeret til farveblinde", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Udseende", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Tilpasset fremhævningsfarve", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktivér understøttelse for Skylagring", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Jeg er en erfaren bruger", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Deaktivér præindlæsning (for at hindre enhver forbindelse for blokerede netværksanmodninger)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Deaktivér hyperlinkrevision", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Forhindr WebRTC i at lække lokale IP-adresser", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standardadfærd", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Standardadfærd som disse kan tilsidesættes pr. websted", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Deaktivér kosmetisk filtrering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokér medieelementer større end {{input:number}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokér fjernskrifttyper", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Deaktivér JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokér CSP-rapporter", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Vis kanoniske navne", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avanceret", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funktioner kun egnet til tekniske brugere.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "avancerede indstillinger", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Seneste gendannelse:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Seneste sikkerhedskopi:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} netværksfiltre + {{cosmeticFilterCount}} kosmetiske filtre fra:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} af {{total}} brugt", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-opdatér filterlister", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Opdatér nu", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Ryd alle caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Fortolk og benyt kosmetiske filtre", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetiske filtre tjener til at skjule elementer på en webside, der anses for at være visuel generende, og som ikke kan blokeres af den netværksanmodningsbaserede filtreringsmotor.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorér generiske kosmetiske filtre", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Generiske kosmetiske filtre er de kosmetiske filtre, der er beregnet til at gælde på alle websteder. Aktivering af denne indstilling vil eliminere hukommelse- og CPU-forbrug, der tilføjes til websider som et resultat af håndtering af generiske kosmetiske filtre.\n\nDet anbefales at aktivere denne indstilling på mindre kraftfulde enheder.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspendér netværksaktivitet, indtil alle filterlister er indlæst", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Liste over blokerede værter", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Effektuér ændringer", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Integreret", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Annoncer", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privatliv", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware-beskyttelse, sikkerhed", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Gener", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Universalfiltre", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regioner, sprog", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Tilpasset", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importér...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Én URL pr. linje. Ugyldige URL'er ignoreres uden notificering.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Forældet.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "vis indhold", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Seneste opdatering: {{ago}}.\nKlik for at gennemtvinge en opdatering.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Opdaterer...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "En netværksfejl forhindrede opdatering af ressourcen.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ét filter pr. linje. Et filter kan være et almindeligt værtsnavn eller et EasyList-kompatibelt filter. Linjer startende med ! ignoreres.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Tilføj ikke filtre fra ikke-betroede kilder.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importer og tilføj…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksporter…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mine-ublock-statiske-filtre_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Effektuér ændringer", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanente regler", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Midlertidige regler", + "description": "header" + }, + "rulesRevert": { + "message": "Gendan", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Gør permanent", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Redigér", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Gem", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Kassér", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importér fra fil...", + "description": "" + }, + "rulesExport": { + "message": "Eksporter til fil…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mine-ublock-dynamiske-regler_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Liste over dine dynamiske filtreringsregler.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regelsyntaks: kilde destination type handling (fuld dokumentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortering:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Regeltype", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Kilde", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "De betroede webstedsdirektiver dikterer, på hvilke websider uBlock Origin skal deaktiveres. En post pr. linje.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importer og tilføj…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksporter…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mine-ublock-betroede-websteder_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Effektuér ændringer", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domæne", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alle", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Bag kulisserne", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktuel fane", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Genindlæs faneindholdet", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Slå DOM-inspektøren til/fra", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Slå popup-panelet til/fra", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin-wiki: Loggeren", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Ryd logger", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Sæt logger på pause (ignorér alle indgående data)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Fortsæt logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Slå logger-filtrering til/fra", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrér logindhold", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger-filtreringsindstillinger", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ikke", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "begivenhedsrig", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokerede", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "tilladte", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "ændret", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "førsteparts", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "tredjeparts", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detaljer", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterliste", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root-kontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partsrelation", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL-regel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statisk filtrering", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} netværksanmodninger af {{type}} {{br}}, hvis URL matcher {{url}} {{br}}, og som stammer fra {{origin}},{{br}}{{importance}} når der er et matchende undtagelsesfilter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokér", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Tillad", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "enhver type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "fra \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "fra hvor som helst", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "undtagen når", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "selvom", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statisk filter {{filter}} fundet i:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statisk filter kunne ikke findes i nogen af de aktuelt aktiverede filterlister", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggerposter, som ikke opfylder alle tre betingelser nedenfor, kasseres automatisk:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Bevar poster fra de seneste {{input}} minutter", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Bevar maks. {{input}} sideindlæsninger pr. fane", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Bevar maks. {{input}} poster pr. fane", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Benyt {{input}} linjer pr. post i lodret udvidet tilstand", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Skjul kolonner:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} tid", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/regel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partsrelation", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Liste", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Enkel", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Åbn", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Opret ny anmeldelse", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find lign. anmeldelser", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentation", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Læs dokumentationen på uBlock/wiki for at få mere at vide om alle uBlock Origin-funktionerne.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Spørgsmål og Support", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Svar på spørgsmål samt andre former for hjælp/support er tilgængelig via subreddit/r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterproblemer/websted er ødelagt", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Rapportér filterproblemer med bestemte websteder via uBlockOrigin/uAssets-problemsporing. Kræver en GitHub-konto.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Vigtigt: Undgå brug af andre blockere med lign. formål sammen med uBlock Origin, da dette kan medføre filterproblemer på visse websteder.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tip: Sørg for, at dine filterlister er opdaterede. Loggeren er det primære værktøj til diagnosticering af filterrelaterede problemer.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Fejlrapport", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Rapportér problemer med selve uBlock Origin via uBlockOrigin/uBlock-issue problemsporingen. Kræver en GitHub-konto.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Fejlfindingsinformation", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Nedenfor findes tekniske oplysninger, som kan være nyttige, når frivillige forsøger at hjælpe dig med at løse et problem.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Vigtigt: Potentielt fortrolige eller sensitive oplysninger bortredigeres som standard, hvilket kan gøre problemløsningen vanskeligere.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Anmeld et filterproblem", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "For at undgå at belaste frivillige med dubletanmeldelser, så tjek venligst, at problemet ikke allerede er anmeldt.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlister opdateres dagligt. Sørg for, at problematikken ikke allerede er blevet behandlet i de seneste filterlister.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Bekræft problematikkens fortsatte eksistens efter genindlæsning af den problematiske webside.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Websideadressen", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Websiden...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Vælg problemtype --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Viser annoncer eller annoncerester", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Indeholder overlejringer eller andre gener", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detekterer uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Indeholder fortrolighedsrelaterede problemer", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Ødelægges, når uBlock Origin er aktiveret", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Åbner uønskede faner eller vinduer", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Markér websiden som “NSFW” (“Ikke sikker til arbejdsbrug”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Bortredigér", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Bortredigér ikke", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Fortrolighedspolitik", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Ændringslog", + "description": "" + }, + "aboutCode": { + "message": "Kildekode (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Bidragsydere", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kildekode", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Oversættelser", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlister", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Eksterne afhængigheder (GPLv3-kompatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBOs egne filterlister hostes frit på flg. CDN'er:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "En tilfældigt valgt CDN anvendes, når en filterliste kræver opdatering.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sikkerhedskopiér til fil...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "min-ublock-sikkerhedskopi_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Gendan fra fil...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Nulstil til standardindstillinger...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Alle dine indstillinger overskreves med data sikkerhedskopieret d. {{time}}, hvorefter uBlock₀ genstarter.\n\nOverskriv aktuelle indstillinger med data fra sikkerhedskopien?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Dataene kunne ikke læses eller er ugyldige", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Alle dine indstillinger fjernes, hvorefter uBlock₀ genstarter.\n\nNulstil uBlock₀ til standardindstillingerne?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Netværksfejl: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Føj følgende URL til dine tilpassede filterlister?\n\nTitel: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonnér", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "et minut siden", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutter siden", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "en time siden", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} timer siden", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "en dag siden", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dage siden", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Vis Kontrolpanel", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Vis Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "Slået fra", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Side blokeret", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origins har blokeret flg. side fra at hente:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Grundet flg. filter", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "uden parametre", + "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": "Fundet i:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Gå tilbage", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Luk dette vindue", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Advar ikke igen om dette websted", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Deaktivér stringent blokering for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Midlertidig", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanent", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Fortsæt", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksportér til Skylager", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importér fra Skylager", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importér fra Skylager og sammenflet med de aktuelle indstillinger", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Denne enheds navn:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Advarsel! Ændring af disse avancerede indstillinger sker på eget ansvar.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Indsend", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Effektuér ændringer", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Gendan", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokér element i ramme...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonnér på filterliste...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Tillad midlertidigt store medieelementer", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Vis kildekode…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Angiv en genvej", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Slå rullelåsning til/fra", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiér til Udklipsholder", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Vælg alt", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kosmetisk filtrering til/fra", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Lemp blokeringstilstand", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Lagerplads brugt: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klik for at indlæse", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Fejl: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Kunne ikke filtrere korrekt ved webbrowserstart. Genindlæs siden for at sikre korrekt filtrering.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Denne post skal være den sidste", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json new file mode 100644 index 0000000..80e8706 --- /dev/null +++ b/src/_locales/de/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Endlich ein effizienter Blocker, der wenig Prozessorleistung und Arbeitsspeicher verbraucht.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warnung! Nicht gespeicherte Änderungen", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Bleiben", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorieren", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Einstellungen", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlisten", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Meine Filter", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Meine Regeln", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Ausnahmeregeln", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Tastenkombinationen", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Protokoll der Netzwerkanfragen", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Über", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Unterstützung", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Ressourcenbetrachter", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Erweiterte Einstellungen", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klick: uBlock₀ für diese Website ein-/ausschalten.\n\nStrg+Klick: uBlock₀ nur für die aktuelle Seite ausschalten.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Hier klicken, um uBlock₀ für diese Website auszuschalten. \n\nStrg+Klick, um uBlock₀ nur auf dieser Seite auszuschalten.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Hier klicken, um uBlock₀ für diese Website einzuschalten.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "Blockierte Anfragen", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "auf dieser Seite", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}} %)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "seit Installation", + "description": "English: since install" + }, + "popupOr": { + "message": "oder", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Auf dieser Seite blockiert", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Seit der Installation blockiert", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Verbundene Domains", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Dashboard öffnen", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Element temporär entfernen", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Element dauerhaft entfernen", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Protokoll der Netzwerkanfragen öffnen", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Ein Problem mit dieser Website melden", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Pop-ups auf dieser Website blockieren/zulassen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Hier klicken, um alle Pop-ups auf dieser Website zu blockieren", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Hier klicken, um Pop-ups auf dieser Website wieder zuzulassen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Große Medienelemente auf dieser Website anzeigen/blockieren", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Hier klicken, um große Medienelemente auf dieser Website zu blockieren", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Hier klicken, um große Medienelemente auf dieser Website wieder zuzulassen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Kosmetisches Filtern für diese Website ein-/ausschalten", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Hier klicken, um kosmetisches Filtern auf dieser Website zu deaktivieren", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Hier klicken, um kosmetisches Filtern auf dieser Website zu aktivieren", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Externe Schriftarten für diese Website zulassen/blockieren", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Hier klicken, um externe Schriftarten auf dieser Website zu blockieren", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Hier klicken, um externe Schriftarten auf dieser Website wieder zuzulassen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Hier klicken, um JavaScript auf dieser Website zu deaktivieren", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Hier klicken, um JavaScript auf dieser Website wieder zuzulassen", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up-Fenster", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Große Medienelemente", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetisches Filtern", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Externe Schriftarten", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mehr", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Weniger", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globale Regeln: Diese Spalte ist für Regeln, die für alle Websites gelten.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokale Regeln: Diese Spalte ist für Regeln, die nur für die aktuelle Website gelten.\nLokale Regeln überschreiben globale Regeln.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Hier klicken, um die Änderungen dauerhaft zu übernehmen.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Hier klicken, um die Änderungen rückgängig zu machen.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Alle Ressourcen", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Bilder", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Ressourcen aus Drittquellen", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/Bilder aus Drittquellen", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Inline-Skripte", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Skripte dieser Domain", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skripte aus Drittquellen", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Frames aus Drittquellen", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "Verbundene Domains", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} von {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "Skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "Frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Erstellen", + "description": "English: Create" + }, + "pickerPick": { + "message": "Auswählen", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Beenden", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Vorschau", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Netzwerkfilter", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetische Filter", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klick, Strg-Klick", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Element blockieren …", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Platzhalter für blockierte Elemente ausblenden", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Anzahl der blockierten Anfragen auf dem Symbol anzeigen", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Tooltips deaktivieren", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Kontextmenü verwenden, falls verfügbar", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Modus für Farbenblinde", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Erscheinungsbild", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Farbschema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Personalisierte Akzentfarbe", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Unterstützung für Cloud-Speicher aktivieren", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ich bin technisch versiert", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Vorabruf von Webseiten deaktivieren (um jede Verbindung für blockierte Netzwerkanfragen zu verhindern)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Hyperlink-Überwachung deaktivieren", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Freigabe der lokalen IP-Adresse via WebRTC verhindern", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standardverhalten", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Dieses Standardverhalten kann für jede Website angepasst werden", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Kosmetisches Filtern deaktivieren", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Medienelemente größer als {{input}} KB blockieren", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Externe Schriftarten blockieren", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript deaktivieren", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP-Berichte blockieren", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Kanonische Namen auflösen", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Erweitert", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funktionen, die nur für technisch Versierte bestimmt sind", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Erweiterte Einstellungen", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Letzte Wiederherstellung:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Letzte Sicherung:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} Netzwerkfilter + {{cosmeticFilterCount}} kosmetische Filter von:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}}/{{total}} verwendet", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Filterlisten automatisch aktualisieren", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Jetzt aktualisieren", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Alle Caches leeren", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Kosmetische Filter auswerten und anwenden", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetische Filter dienen dazu, Elemente in einer Webseite auszublenden, die als visuell störend empfunden werden und die von den auf Netzwerkanfragen basierenden Filter-Engines nicht blockiert werden können.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Allgemeine kosmetische Filter ignorieren", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Allgemeine kosmetische Filter sind kosmetische Filter, die auf alle Websites angewendet werden sollen. Das Aktivieren dieser Option verhindert die Mehrbelastung des Arbeitsspeichers und der CPU, die durch das Verarbeiten allgemeiner kosmetischer Filter auf Websites entsteht.\n\nEs wird empfohlen, diese Option auf weniger leistungsfähigen Geräten zu aktivieren.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Netzwerkaktivität unterbrechen, bis alle Filterlisten geladen sind", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listen blockierter Hostnamen", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Änderungen übernehmen", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "uBlock-eigene Filterlisten", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Werbung", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Datenschutz", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Schutz vor Schadsoftware, Sicherheit", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Belästigungen", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Verschiedene Zwecke", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regionen, Sprachen", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Eigene Filterlisten", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importieren …", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Eine URL pro Zeile. Ungültige URLs werden stillschweigend ignoriert.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "veraltet", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Inhalt anzeigen", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Letzte Aktualisierung: {{ago}}.\nAktualisierung durch Anklicken erzwingen.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Wird aktualisiert …", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ein Netzwerkfehler verhinderte die Aktualisierung der Ressource.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ein Filter pro Zeile. Ein Filter kann ein einfacher Hostname oder ein EasyList-kompatibler Filter sein. Zeilen mit vorangestelltem ! werden ignoriert.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Verwenden Sie keine Filter aus unseriösen Quellen.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importieren und anfügen …", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportieren …", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-statische-filter_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Änderungen übernehmen", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Dauerhafte Regeln", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporäre Regeln", + "description": "header" + }, + "rulesRevert": { + "message": "Rückgängig machen", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Dauerhaft speichern", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Bearbeiten", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Speichern", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Verwerfen", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Aus Datei importieren …", + "description": "" + }, + "rulesExport": { + "message": "In Datei exportieren …", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-dynamische-regeln_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Liste eigener dynamischer Filterregeln.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regelsyntax: Quelle Ziel Typ Aktion (Ausführliche Dokumentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortieren:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Regeltyp", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Quelle", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Ziel", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Ausnahmeregeln bestimmen, auf welchen Webseiten uBlock Origin deaktiviert werden soll. Ein Eintrag pro Zeile.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importieren und anfügen …", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportieren …", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-ausnahmeregeln_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Änderungen übernehmen", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Typ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alle", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Hintergrund-Netzwerkanfragen", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktueller Tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Inhalt des Tabs neu laden", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM-Inspektor ein-/ausschalten", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Pop-up-Fenster ein-/ausblenden", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin-Wiki: Protokoll der Netzwerkanfragen", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Protokoll leeren", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Protokollierung anhalten (alle eingehenden Daten verwerfen)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Protokollierung fortsetzen", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Protokollfilter ein-/ausschalten", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "Protokolleinträge filtern", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Protokollfilteroptionen", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nicht", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "Ereignisreich", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blockiert", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "zugelassen", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "geändert", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Aktuelle Domain", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Ressourcen aus Drittquellen", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterliste", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontext", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Wurzelkontext", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Zugehörigkeit", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Typ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL-Regel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontext:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Typ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statischer Filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "Netzwerkanfragen {{type}} {{action}},{{br}}deren URL-Adresse mit {{url}} übereinstimmt{{br}}und von {{origin}} stammen,{{br}}{{importance}} ein übereinstimmender Ausnahmefilter existiert.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "blockieren", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "zulassen", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "vom Typ »{{type}}«", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "aller Typen", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "{{origin}}", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "überall", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "außer wenn", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "selbst wenn", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statischer Filter {{filter}} gefunden in:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statischer Filter konnte in keiner der derzeit aktivierten Filterlisten gefunden werden", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Protokolleinträge werden automatisch verworfen, wenn sie nicht alle der drei folgenden Bedingungen erfüllen:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Einträge der letzten {{input}} Minuten beibehalten", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Höchstens {{input}} Seitenladevorgänge pro Tab beibehalten", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Höchstens {{input}} Einträge pro Tab beibehalten", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "{{input}} Zeilen pro Eintrag im vertikal erweiterten Modus verwenden", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Spalten ausblenden:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Uhrzeit", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/Regel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontext", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Zugehörigkeit", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Liste", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabelle", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Einfach", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Öffnen", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Neuen Bericht erstellen", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Ähnliche Berichte suchen", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentation", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lesen Sie die Dokumentation auf uBlock/wiki, um mehr über alle Funktionen von uBlock Origin zu erfahren.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Fragen und Unterstützung", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Antworten auf Fragen und andere Arten der Hilfe werden im Subreddit /r/uBlockOrigin gegeben.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterprobleme / Website funktioniert nicht", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Bitte melden Sie Filterprobleme mit bestimmten Websites an den uBlockOrigin/uAssets Issue Tracker. Erfordert ein GitHub-Konto.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Wichtig: Vermeiden Sie es, andere ähnliche Blocker zusammen mit uBlock Origin zu verwenden, da dies bei einigen Websites zu Filterproblemen führen kann.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tipp: Vergewissern Sie sich, dass die Filterlisten auf dem aktuellen Stand sind. Protokoll der Netzwerkanfragen ist das primäre Werkzeug, um filterbezogene Fehler zu diagnostizieren.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Fehlerbericht", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Bitte melden Sie Probleme mit uBlock Origin an den uBlockOrigin/uBlock-issue Issue Tracker. Erfordert ein GitHub-Konto.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informationen zur Fehlerbehebung", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Im Folgenden sind einige technische Informationen aufgeführt, die nützlich sein können, wenn Freiwillige versuchen, bei der Lösung eines Problems zu helfen.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Wichtig: Potenziell private oder sensible Informationen werden standardmäßig unkenntlich gemacht. Unkenntlich gemachte Informationen können das Lösen eines Problems erschweren.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Ein Filterproblem melden", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Um die Freiwilligen nicht mit doppelten Meldungen zu belasten, vergewissern Sie sich bitte, dass das Problem nicht schon einmal gemeldet wurde.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlisten werden täglich aktualisiert. Bitte vergewissern Sie sich, dass Ihr Problem nicht durch aktuelle Filterlisten behoben wurde.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Bitte überprüfen Sie, ob das Problem nach dem Neuladen der Webseite weiterhin besteht.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresse der Webseite:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Die Webseite …", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Einen Eintrag auswählen --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Zeigt Werbung oder Anzeigenreste", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Enthält Überdeckungen oder andere Belästigungen", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Erkennt uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Hat Datenschutzprobleme", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Funktioniert nicht richtig, wenn uBlock Origin aktiviert ist", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Öffnet unerwünschte Tabs oder Fenster", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Webseite als »NSFW« kennzeichnen (»Unpassend für den Arbeitsplatz«)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Unkenntlich machen", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Kenntlich machen", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Datenschutzhinweise", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Änderungsprotokoll", + "description": "" + }, + "aboutCode": { + "message": "Quellcode (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Mitwirkende", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Quellcode", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Übersetzungen", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlisten", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Externe Abhängigkeiten (GPLv3-kompatibel):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Die uBO-eigenen Filterlisten werden auf den folgenden CDNs frei zur Verfügung gestellt:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ein zufällig ausgewähltes CDN wird verwendet, wenn eine Filterliste aktualisiert werden muss.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "In Datei sichern …", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-sicherung_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Aus Datei wiederherstellen …", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Auf Werkseinstellungen zurücksetzen …", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Alle Einstellungen werden überschrieben und auf den Stand vom {{time}} gebracht. Anschließend wird uBlock₀ neu gestartet.\n\nSollen die aktuellen Einstellungen durch die Sicherung ersetzt werden?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Die Daten konnten nicht gelesen werden oder sind ungültig", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Alle Einstellungen werden gelöscht und uBlock₀ wird neu gestartet.\n\nSoll uBlock₀ auf Werkseinstellungen zurückgesetzt werden?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Netzwerkfehler: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Folgende URL zu den eigenen Filterlisten hinzufügen?\n\nTitel: »{{title}}«\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonnieren", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "vor einer Minute", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "vor {{value}} Minuten", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "vor einer Stunde", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "vor {{value}} Stunden", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "vor einem Tag", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "vor {{value}} Tagen", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Dashboard anzeigen", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Protokoll der Netzwerkanfragen anzeigen", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "aus", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Seite blockiert", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin hat das Laden der folgenden Seite verhindert:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Aufgrund des folgenden Filters:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "ohne Parameter", + "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": "Gefunden in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Zurück", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Dieses Fenster schließen", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Nicht erneut vor dieser Seite warnen", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Striktes Blockieren für {{hostname}} deaktivieren", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporär", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Dauerhaft", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Fortfahren", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "In den Cloud-Speicher exportieren", + "description": "tooltip" + }, + "cloudPull": { + "message": "Aus dem Cloud-Speicher importieren", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Aus dem Cloud-Speicher importieren und mit den aktuellen Einstellungen zusammenführen", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Name dieses Gerätes:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Warnung! Das Ändern der erweiterten Einstellungen erfolgt auf eigenes Risiko.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Absenden", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Änderungen übernehmen", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Rückgängig machen", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "Bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Element im Frame blockieren …", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Filterliste abonnieren …", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Große Medienelemente temporär zulassen", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Quellcode anzeigen …", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Tastenkombination drücken", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Synchrones Scrollen ein-/ausschalten", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "In die Zwischenablage kopieren", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Alles auswählen", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kosmetisches Filtern ein-/ausschalten", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Blockiermodus lockern", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Genutzter Speicherplatz: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Zum Laden anklicken", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Fehler: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Beim Start des Browsers konnte nicht richtig gefiltert werden. Bitte die Seite neu laden, um ein korrektes Filtern zu gewährleisten.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Dieser Eintrag muss der letzte sein", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json new file mode 100644 index 0000000..cb8595c --- /dev/null +++ b/src/_locales/el/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Επιτέλους, ένας αποτελεσματικός blocker. Ελαφρύς για τον επεξεργαστή και τη μνήμη.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ - Πίνακας ελέγχου", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Προειδοποίηση! Έχετε μη αποθηκευμένες αλλαγές", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Παραμονή", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Παράβλεψη", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ρυθμίσεις", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Λίστες φίλτρων", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Τα φίλτρα μου", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Οι κανόνες μου", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Έμπιστες τοποθεσίες", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Συντομεύσεις", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ - Καταγραφή αιτημάτων δικτύου", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Σχετικά", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Υποστήριξη", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Προβολή πόρων", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Ρυθμίσεις για προχωρημένους", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ μόνο σε αυτήν τη σελίδα.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Κάντε κλικ για ενεργοποίηση του uBlock₀ για αυτή την ιστοσελίδα.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "αποκλεισμένα αιτήματα", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "σε αυτήν τη σελίδα", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ή {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "από την εγκατάσταση", + "description": "English: since install" + }, + "popupOr": { + "message": "ή", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Αποκλεισμένα σε αυτή τη σελίδα", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Φραγμένο από εγκατάσταση", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Συνδεδεμένοι τομείς", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Κάντε κλικ για να ανοίξετε τον πίνακα εργαλείων", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Είσοδος σε λειτουργία εκτέλεσης στοιχείων", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Είσοδος στη λειτουργία επιλογής στοιχείων", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Πηγαίνετε στο αρχείο καταγραφής αιτημάτων", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Αναφέρετε ένα πρόβλημα σε αυτόν τον ιστότοπο", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Παρεμπόδιση αναδυόμενων παραθύρων για αυτόν τον ιστότοπο", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Κάντε κλικ για φραγή όλων των αναδυόμενων σε αυτή την ιστοσελίδα", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Κάντε κλικ για φραγή όλων των αναδυόμενων σε αυτή την ιστοσελίδα", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Εναλλαγή της φραγής των μεγάλων στοιχείων πολυμέσων για αυτήν την τοποθεσία", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Κάντε κλικ για αποκλεισμό μεγάλων στοιχείων πολυμέσων σε αυτή την ιστοσελίδα", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Κάντε κλικ για αναίρεση φραγής των μεγάλων στοιχείων πολυμέσων σε αυτή την τοποθεσία", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Ενεργοποιήστε διακοσμητικό φιλτράρισμα για αυτήν τη σελίδα", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Κάντε κλικ για να απενεργοποιήσετε το καλλωπιστικό φιλτράρισμα σε αυτή την τοποθεσία", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Κάντε κλικ για να ενεργοποιήσετε το καλλωπιστικό φιλτράρισμα σε αυτή την τοποθεσία", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Ενεργοποιήστε το μπλοκάρισμα απομακρυσμένων γραμματοσειρών για αυτήν την ιστοσελίδα", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Κάντε κλικ για φραγή απομακρυσμένων γραμματοσειρών σε αυτή την ιστοσελίδα", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Κάντε κλικ για να μην μπλοκάρετε πλέον απομακρυσμένες γραμματοσειρές σε αυτήν την ιστοσελίδα", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Κάντε κλικ για να απενεργοποιήσετε το JavaScript σε αυτήν την ιστοσελίδα", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Κάντε κλικ για να μην απενεργοποιείται πλέον η JavaScript σε αυτή την τοποθεσία", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Αναδυόμενα παράθυρα", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Στοιχεία μεγάλων πολυμέσων", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Καλλωπιστικά φίλτρα", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Απομακρυσμένες γραμματοσειρές", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Περισσότερα", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Λιγότερα", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Καθολικοί κανόνες: αυτή η στήλη είναι για κανόνες με εφαρμογή σε όλες τις τοποθεσίες.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Τοπικοί κανόνες: αυτή η στήλη είναι για κανόνες με εφαρμογή στην τρέχουσα τοποθεσία μόνο.\nΟι τοπικοί κανόνες παραμερίζουν τους καθολικούς κανόνες.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Πατήστε για να κάνετε τις αλλαγές σας μόνιμες.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Πατήστε για να αντιστρέψετε τις αλλαγές σας.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "όλα", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Εικόνες", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "πόροι ιστότοπων τρίτων", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/Εικόνες τρίτων", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts τρέχοντος ιστότοπου", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts ιστότοπων τρίτων", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames ιστότοπων τρίτων", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "συνδεδεμένοι τομείς", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} από {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Έκδοση", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "δέσμη ενεργειών", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "πλαίσιο", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Δημιουργία", + "description": "English: Create" + }, + "pickerPick": { + "message": "Επιλογή", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Κλείσιμο", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Προεπισκόπηση", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Φίλτρα δικτύου", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Κοσμητικά φίλτρα", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Κλικ, Ctrl-κλικ", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Φραγή στοιχείου...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Απόκρυψη κρατημένων πεδίων από αποκλεισμένα στοιχεία", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Εμφάνιση του αριθμού αποκλεισμένων αιτημάτων στο εικονίδιο", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Απενεργοποίηση υποδείξεων", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Να γίνεται χρήση του αναδυόμενου μενού, όπου ενδείκνυται", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Λειτουργία φιλική προς χρήστες με αχρωματοψία", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Εμφάνιση", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Θέμα", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Προσαρμοσμένο χρώμα έμφασης", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Ενεργοποίηση υποστήριξης cloud storage", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Είμαι προχωρημένος χρήστης (Aπαραίτητη ανάγνωση)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Απενεργοποίηση προ-φόρτωσης (για να αποτραπεί κάθε σύνδεση σε αποκλεισμένες αιτήσεις δικτύου)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Απενεργοποίηση ελέγχου/διόπτευσης υπερσυνδέσμων", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Αποτρέψτε το WebRTC από το να διαρρέει την τοπική διεύθυνση IP", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Προεπιλεγμένη συμπεριφορά", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Αυτές οι προεπιλεγμένες συμπεριφορές μπορούν να παρακαμφθούν ανά τοποθεσία", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Απενεργοποίηση διακοσμητικού φιλτραρίσματος", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Φραγή στοιχείων πολυμέσων μεγαλύτερων από {{input:number}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Φραγή απομακρυσμένων γραμματοσειρών", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Απενεργοποίηση JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Φραγή αναφορών CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Ξεσκέπασμα/εμφάνιση κανονικών ονομάτων CNAME", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Για προχωρημένους", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Χαρακτηριστικά κατάλληλα μόνο για τεχνικούς χρήστες.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "ρυθμίσεις για προχωρημένους", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Τελευταία ανάκτηση:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Τελευταίο αντίγραφο ασφαλείας:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} φίλτρα δικτύου+ {{cosmeticFilterCount}} κοσμητικά φίλτρα από:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} σε χρήση από {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Αυτόματη ενημέρωση λιστών φίλτρων.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Ενημέρωση τώρα", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Εκκαθάριση προσωρινής μνήμης κάθε λίστας", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Ανάλυση και επιβολή κοσμητικών φίλτρων.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Τα καλλωπιστικά φίλτρα χρησιμεύουν για να κρύβουν εκείνα τα στοιχεία σε μια ιστοσελίδα που οπτικά θεωρούνται ενοχλητικά, και τα οποία δεν μπορούν να αποκλειστούν με τις μηχανές φιλτραρίσματος που βασίζονται σε αιτήματα δικτύου.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Παράβλεψη γενικών κοσμητικών φίλτρων", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Τα γενικά κοσμητικά φίλτρα είναι εκείνα τα κοσμητικά φίλτρα που εφαρμόζονται σε όλες τις ιστοσελίδες.

Αν και γίνεται αποτελεσματική διαχείρισή τους από το uBlock₀, τα γενικά κοσμητικά φίλτρα ενδέχεται να καταναλώσουν σημαντική μνήμη και να υπερφορτώσουν τη CPU σε μερικές ιστοσελίδες, ειδικά για μεγάλες μακροχρόνιες.

Η ενεργοποίηση αυτής της επιλογής θα εξαλείψει την υπερφόρτωση μνήμης και CPU στις ιστοσελίδες ως αποτέλεσμα της διαχείρισης γενικών κοσμητικών φίλτρων, ενώ ενδέχεται να μειώσει την κατανάλωση μνήμης του ίδιου του uBlock₀.

Προτείνεται η ενεργοποίηση αυτής της επιλογής στις λιγότερο ισχυρές συσκευές.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Αναστολή της δραστηριότητας δικτύου μέχρι να φορτωθούν όλες οι λίστες φίλτρων", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Λίστες αποκλεισμένων hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Εφαρμογή αλλαγών", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Τοπικά", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Διαφημίσεις", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Ιδιωτικό απόρρητο", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Τομείς κακόβουλου λογισμικού", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Ενοχλήσεις", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Πολλαπλών χρήσεων", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Περιοχές, γλώσσες", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Προσαρμοσμένη", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Εισαγωγή...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Ένα URL ανά γραμμή. Γραμμές με το πρόθεμα ‘!’ θα παραβλέπονται. Άκυρα URL θα παρακάμπτονται σιωπηλά.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "απαρχαιωμένη.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "εμφάνιση περιεχομένου", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Τελευταία ενημέρωση: {{ago}}.\nΚάντε κλικ για επιβολή ενημέρωσης.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ενημέρωση...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ένα σφάλμα δικτύου εμπόδισε την ενημέρωση του πόρου.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ένα φίλτρο ανά γραμμή. Ένα φίλτρο μπορεί να είναι ένα απλό όνομα κεντρικού υπολογιστή ή ένα φίλτρο συμβατό με την EasyList. Οι γραμμές με πρόθεμα ! θα παραβλέπονται.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Να μην προστίθενται φίλτρα από μη αξιόπιστες πηγές.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Εισαγωγή και προσάρτηση", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Εξαγωγή", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "τα-στατικά-ublock-φίλτρα-μου_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Εφαρμογή αλλαγών", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Μόνιμοι κανόνες", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Προσωρινοί κανόνες", + "description": "header" + }, + "rulesRevert": { + "message": "Επαναφορά", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Επικύρωση", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Επεξεργασία", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Αποθήκευση", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Απόρριψη", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Εισαγωγή από αρχείο…", + "description": "" + }, + "rulesExport": { + "message": "Εξαγωγή σε αρχείο…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "οι-δυναμικοί-ublock-κανόνες-μου_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Λίστα δυναμικών κανόνων φιλτραρίσματος.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Συντακτικό κανόνων: προέλευση προορισμός τύπος ενέργεια (πλήρης τεκμηρίωση).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ταξινόμηση:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Τύπος κανόνα", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Προέλευση", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Προορισμός", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Η λίστα σας με τα ονόματα κόμβων (host names) στα οποία το uBlock θα είναι απενεργοποιημένο. Μια καταχώρηση ανά γραμμή. Άκυρα ονόματα κόμβων θα παρακάμπτονται σιωπηλά.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Εισαγωγή και προσάρτηση", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Εξαγωγή", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-έμπιστες-τοποθεσίες_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Εφαρμογή αλλαγών", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Τύπος", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Τομέας", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Φίλτρο", + "description": "English: Filter" + }, + "logAll": { + "message": "Όλα", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Παρασκήνιο", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Τρέχουσα καρτέλα", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Επαναφόρτωση του περιεχόμενου της καρτέλας", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Εναλλαγή του επιθεωρητή DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Εναλλαγή του αναδυόμενου πίνακα", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Ο καταγραφέας", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Καθαρισμός καταγραφέα", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Παύση καταγραφέα (απόρριψη όλων των εισερχόμενων δεδομένων)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Κατάργηση παύσης καταγραφέα", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Εναλλαγή φίλτρου καταγραφέα", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "φιλτράρισμα των καταχωρήσεων", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Ρυθμίσης φιλτραρίσματος καταγραφέα", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Δεν", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "μπλοκαρισμένο", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "επιτρέπεται", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "επεξεργασμένο", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Πρωτομερής", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Τριτομερής", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Λεπτομέρειες", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Φίλτρο", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Λίστα φίλτρων", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Κανόνας", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Συμφραζόμενα", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Πλαίσιο ρίζας", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Μέρος αιτήματος", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Τύπος", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Κανόνας URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Περιεχόμενο:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Τύπος:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Στατικό φιλτράρισμα", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} τα δικτυακά αιτήματα {{type}} {{br}} των οποίων η διεύθυνση ταιριάζει με {{url}} {{br}} και προέρχεται από {{origin}},{{br}}{{importance}} υπάρχει ένα ταιριαστό φίλτρο για εξαίρεση.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Φραγή", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Αποδοχή", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "τύπος “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "οποιοσδήποτε τύπος", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "από “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "από οπουδήποτε", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "εκτός όταν", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "ακόμη και αν", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Στατικό φίλτρο {{filter}} βρέθηκε σε:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Το στατικό φίλτρο δεν βρέθηκε σε καμία από τις λίστες φίλτρων που έχουν ενεργοποιηθεί αυτήν τη στιγμή", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Οι καταχωρίσεις στον καταγραφέα που δεν εκπληρούν και τις τρεις συνθήκες θα απορρίπτονται αυτόματα:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Διατηρήσε καταχωρήσεις από τα {{input}} τελευταία λεπτά", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Διατηρήσε το πολύ {{input}} page loads ανά καρτέλα", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Διατηρήσε το πολύ {{input}} καταχωρήσεις ανά καρτέλα", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Χρησιμοποιήστε {{input}} γραμμές ανά καταχώριση σε κατακόρυφη λειτουργία", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Απόκρυψη στηλών:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Ώρα", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Φίλτρο/κανόνας", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Περιεχόμενο", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} μέρος αιτήματος", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Λίστα", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Πίνακας", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Απλό", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Άνοιγμα", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Δημιουργία νέας αναφοράς", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Βρείτε παρόμοιες αναφορές", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Οδηγίες", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Διαβάστε τις οδηγίες στο uBlock/wiki για να μάθετε για όλες τις δυνατότητες του uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Ερωτήσεις και υποστήριξη", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Απαντήσεις σε ερωτήσεις και άλλα είδη υποστήριξης βοήθειας παρέχονται στο subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Προβλήματα φίλτρου/ιστότοπος είναι κατεστραμμένος", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Αναφέρετε προβλήματα φίλτρου με συγκεκριμένους ιστότοπους στο uBlockOrigin/uAssets issue tracker. Απαιτείται λογαριασμός GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Σημαντικό: Αποφύγετε τη χρήση άλλων blocker με παρόμοιο σκοπό μαζί με το uBlock Origin, καθώς αυτό μπορεί να προκαλέσει προβλήματα φιλτραρίσματος σε συγκεκριμένους ιστότοπους.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Συμβουλές: Βεβαιωθείτε ότι οι λίστες φίλτρων σας είναι ενημερωμένες. Ο καταγραφέας είναι το κύριο εργαλείο για τη διάγνωση προβλημάτων που σχετίζονται με το φίλτρο.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Αναφορά σφαλμάτων", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Αναφέρετε προβλήματα με το ίδιο το uBlock Origin στο uBlockOrigin/uBlock-issue issue tracker. Απαιτείται λογαριασμός GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Πληροφορίες αντιμετώπισης προβλημάτων", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Παρακάτω υπάρχουν τεχνικές πληροφορίες που μπορεί να είναι χρήσιμες όταν εθελοντές προσπαθούν να σας βοηθήσουν να λύσετε ένα πρόβλημα.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Σημαντικό: Πιθανώς ιδιωτικές ή ευαίσθητες πληροφορίες αναπροσαρμόζονται από προεπιλογή. Οι αναδιατυπωμένες πληροφορίες ενδέχεται να δυσκολέψουν την επίλυση ενός προβλήματος.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Αναφέρετε ένα πρόβλημα φίλτρου", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Για να αποφύγετε την επιβάρυνση των εθελοντών με διπλές αναφορές, βεβαιωθείτε ότι το ζήτημα δεν έχει ήδη αναφερθεί.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Οι λίστες φίλτρων ενημερώνονται καθημερινά. Βεβαιωθείτε ότι το πρόβλημά σας δεν έχει ήδη αντιμετωπιστεί στις πιο πρόσφατες λίστες φίλτρων.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Βεβαιωθείτε ότι το πρόβλημα εξακολουθεί να υπάρχει μετά τη φόρτωση εκ νέου της προβληματικής ιστοσελίδας.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Διεύθυνση της ιστοσελίδας:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Η ιστοσελίδα...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Επιλέξτε μια καταχώρηση --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Εμφανίζει διαφημίσεις ή υπολείμματα διαφημίσεων", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Έχει επικαλύψεις ή άλλες ενοχλήσεις", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Ανιχνεύει το uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Έχει ζητήματα που σχετίζονται με το απόρρητο", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Μη λειτουργικό όταν το uBlock Origin είναι ενεργοποιημένο", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Ανοίγει ανεπιθύμητες καρτέλες ή παράθυρα", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Επισημάνετε την ιστοσελίδα ως “NSFW” (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Πολιτική απορρήτου", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Αρχείο καταγραφής αλλαγών", + "description": "" + }, + "aboutCode": { + "message": "Πηγαίος κώδικας (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Συνεισφέροντες", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Πηγαίος κώδικας", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Μεταφράσεις", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Λίστες φίλτρων", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Εξωτερικές εξαρτήσεις (συμβατές με GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Οι λίστες φίλτρων του uBO φιλοξενούνται ελεύθερα στα ακόλουθα CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ένα τυχαία επιλεγμένο CDN χρησιμοποιείται όταν πρέπει να ενημερωθεί μια λίστα φίλτρων", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Δημιουργία αντιγράφου ασφαλείας σε αρχείο...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "το-ublock-αντίγραφο-ασφαλείας-μου_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Επαναφορά από αρχείο…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Επαναφορά στις προεπιλεγμένες ρυθμίσεις…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Όλες οι ρυθμίσεις σας θα αντικατασταθούν χρησιμοποιώντας τα δεδομένα του αντιγράφου ασφαλείας που δημιουργήθηκε κατά ημ/νία και ώρα: {{time}} και θα ακολουθήσει επανεκκίνηση του uBlock.", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Τα δεδομένα ήταν αδύνατο να αναγνωστούν ή είναι άκυρα", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Όλες οι ρυθμίσεις σας θα καταργηθούν και θα γίνει επανεκκίνηση του uBlock.\n\nΕπαναφορά του uBlock στις εργοστασιακές ρυθμίσεις;", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Σφάλμα δικτύου: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Προσθήκη της ακόλουθης διεύθυνσης URL στις λίστες προσαρμοσμένων φίλτρων σας;\n\nΤίτλος: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Εγγραφή", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "πριν από ένα λεπτό", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "πριν από {{value}} λεπτά", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "πριν από μια ώρα", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "πριν από {{value}} ώρες", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "πριν από μια ημέρα", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "πριν από {{value}} ημέρες", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Προβολή Πίνακα Εργαλείων", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Προβολή Αρχείου Καταγραφών Αιτημάτων Δικτύου", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "απενεργοποιημένο", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Η σελίδα αποκλείστηκε", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "Το uBlock₀ έχει αποτρέψει τη φόρτωση της παρακάτω σελίδας:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Εξαιτίας του ακόλουθου φίλτρου", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Βρέθηκε σε:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Επιστροφή", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Κλείσιμο του παραθύρου", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Να μην προειδοποιηθώ ξανά για αυτόν τον ιστότοπο", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Απενεργοποίηση αυστηρής φραγής για το {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Προσωρινά", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Μόνιμα", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Συνέχεια", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Εξαγωγή στο cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Εισαγωγή από cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Εισαγωγή αποθηκευμένων στο νέφος ρυθμίσεων και συγχώνευση στις τρέχουσες ρυθμίσεις", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Όνομα αυτής της συσκευής:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Προειδοποίηση! Αλλάξτε αυτές τις ρυθμίσεις για προχωρημένους με δική σας ευθύνη.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Υποβολή", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Εφαρμογή αλλαγών", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Επαναφορά", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Στοιχείο μπλοκ στο πλαίσιο...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Εγγραφή σε λιστα φιλτρων", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Να επιτρέπονται προσωρινά μεγάλα στοιχεία πολυμέσων", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Προβολή πηγαίου κώδικα…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Πληκτρολογήστε μια συντόμευση", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Εναλλαγή κλειδώματος ολίσθησης", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Αντιγραφή στο πρόχειρο", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Επιλογή όλων", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Εναλλαγή διακοσμητικού φιλτραρίσματος", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Χαλάρωση κατάστασης φραγής", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Χώρος σε χρήση: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Κάντε κλικ για φόρτωση", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Σφάλματα: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Δεν ήταν δυνατό το σωστό φιλτράρισμα κατά την εκκίνηση του προγράμματος περιήγησης.\nΦορτώστε ξανά τη σελίδα για να διασφαλίσετε το σωστό φιλτράρισμα", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Αυτή η καταχώρηση θα πρέπει να είναι τελευταία", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json new file mode 100644 index 0000000..b894121 --- /dev/null +++ b/src/_locales/en/messages.json @@ -0,0 +1,1292 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finally, an efficient blocker. Easy on CPU and memory.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warning! You have unsaved changes", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Settings", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filter lists", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "My filters", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "My rules", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trusted sites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "About", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Advanced settings", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requests blocked", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "or", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Open the dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "all", + "description": "" + }, + "popupImageRulePrompt": { + "message": "images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Create", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pick", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quit", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Update now", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Ads", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "All", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "a minute ago", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutes ago", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "an hour ago", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a day ago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} days ago", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Go back", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporarily", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanently", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "This device name:", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/en_GB/messages.json b/src/_locales/en_GB/messages.json new file mode 100644 index 0000000..cb79ea5 --- /dev/null +++ b/src/_locales/en_GB/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finally, an efficient blocker. Easy on CPU and memory.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warning! You have unsaved changes", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Settings", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filter lists", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "My filters", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "My rules", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trusted sites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "About", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Advanced settings", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requests blocked", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "or", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Open the dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all pop-ups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all pop-ups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all pop-ups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "all", + "description": "" + }, + "popupImageRulePrompt": { + "message": "images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Create", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pick", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quit", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Colour-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent colour", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behaviour", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviours can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Update now", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Ads", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware domains", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multi-purpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "All", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the pop-up panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Logger entries which do not fulfil all three conditions below will be automatically discarded:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "a minute ago", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutes ago", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "an hour ago", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a day ago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} days ago", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Go back", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporarily", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanently", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "This device name:", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/eo/messages.json b/src/_locales/eo/messages.json new file mode 100644 index 0000000..6e63e04 --- /dev/null +++ b/src/_locales/eo/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finfine rendimenta reklamoblokilo. Afabla por ĉefprocesoro kaj memoro.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Panelo", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Averto! Vi havas nekonservitajn ŝanĝojn", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Resti", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignori", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Agordoj", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listoj de filtriloj", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Miaj filtriloj", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Miaj reguloj", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Permeslisto", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Alirklavoj", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Protokolilo", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Pri", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Subteno", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Montrilo de rimedoj", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Altgradaj agordoj", + "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.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Alklaku premante la stirklavo por malŝalti uBlock₀ nur en tiu ĉi retejo.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Alklaku por aktivigi uBlock₀ en tiu ĉi retejo.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokitaj petoj", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "en ĉi tiu paĝo", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} aŭ {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "ekde instalado", + "description": "English: since install" + }, + "popupOr": { + "message": "aŭ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokita ĉe ĉi tiu paĝo", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokita ekde instalo", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Konektitaj domajnoj", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Klaku por malfermi la panelon", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Eniri la reĝimon de forigo de elementoj", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Malfermi reĝimon de elementoselektilo", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Malfermi la protokolilon", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Raporti problemon ĉe ĉi tiu retejo", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Baskuligi la blokadon de ŝprucfenestroj por ĉi tiu retejo", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Alklaku por bloki ĉiujn ŝprucfenestrojn en tiu ĉi retejo", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Alklaku por ne plu bloki ĉiujn ŝprucfenestrojn en tiu ĉi retejo", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Baskuligi la blokadon de grandaj aŭdvideaj elementoj por ĉi tiu retejo", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Alklaku por bloki grandajn aŭdvidajn elementojn en tiu ĉi retejo", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Alklaku por ne plu bloki grandajn aŭdvidajn elementojn en tiu ĉi retejo", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Baskuligi ornaman filtradon por ĉi tiu retejo", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Alklaku por malaktivigi kosmetikan filtradon en tiu ĉi retejo", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Alklaku por aktivigi kosmetikan filtradon en tiu ĉi retejo", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Baskuligi la blokadon de foraj tiparoj por ĉi tiu retejo", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Alklaku por bloki forajn tiparojn en tiu ĉi retejo", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Alklaku por ne plu bloki forajn tiparojn en tiu ĉi retejo", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Alklaku por malaktivigi JavaScript en tiu ĉi retejo", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Alklaku por ne plu malaktivigi JavaScript en tiu ĉi retejo", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ŝprucfenestroj", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Grandaj aŭdvidaj elementoj", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Ornama filtrado", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Foraj tiparoj", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Pli", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Malpli", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Ĝeneralaj reguloj: ĉi tiu kolumno estas por reguloj, kiuj aplikas al ĉiuj retejoj.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokaj reguloj: ĉi tiu kolumno estas por reguloj, kiuj aplikas nur al la nuna retejo.\nLokaj reguloj transpasas ĝeneralajn regulojn.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klaku por fari viajn ŝanĝojn konstante.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klaku por malfari viajn ŝanĝojn.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "ĉio", + "description": "" + }, + "popupImageRulePrompt": { + "message": "bildoj", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "De eksteraj liverantoj", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/bildoj de eksteraj liverantoj", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "entekstaj skriptoj", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Skriptoj de propraj liverantoj", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skriptoj de eksteraj liverantoj", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Kadroj de eksteraj liverantoj", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "konektitaj domajnoj", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versio", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skripto", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "kadro", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Krei", + "description": "English: Create" + }, + "pickerPick": { + "message": "Elekti", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Forlasi", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Antaŭrigardo", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Retaj filtriloj", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Ornamaj filtriloj", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klako, Stir-klako", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloki elementon", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Kaŝi lokokupilojn de blokitaj elementoj", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Montri la nombron de la blokitaj petoj sur la bildsimbolo", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Malŝalti butonajn informojn", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Uzi kuntekstan menuon laŭeble", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Afabla por kolorblinduloj", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aspekto", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Etoso", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Propra akcenta koloro", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Ŝalti subtenon por nelokdependa konservado", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Mi estas sperta uzanto", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Malŝalti antaŭvenigadon (por preventi ajnan konekton de blokitaj retaj petoj)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Malŝalti ekzamenadon de ligiloj", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Preventi likado de WebRTC de lokaj IP-adresoj", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Norma konduto", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Oni povas superregi la normajn kondutojn depende de la retejo", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Malŝalti ornaman filtradon", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloki aŭdvideajn elementojn pli granda ol {{input:number}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloki forajn tiparojn", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Malŝalti JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloki CSP-raportojn", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Malkaŝi ĉefnomojn", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Altnivelaĵoj", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkcioj taŭgaj nur por spertuloj", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "altgradaj agordoj", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Lasta restaŭro:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Lasta savkopio:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} retaj filtriloj kaj {{cosmeticFilterCount}} ornamaj filtriloj de:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} estas uzita de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Ĝisdatigi listojn de filtriloj aŭtomate.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Ĝisdatigi nun", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Malplenigi ĉiujn kaŝmemorojn", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizi kaj eltrudi ornamajn filtrilojn.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Ĉi tiu opcio ŝaltas la analizadon kaj eltrudadon de la Adblock Plus-kongruaj “elementokaŝadaj” filtriloj. Ĉi tiuj filtriloj estas nur ornama kaj servas por kaŝi elementojn en retpaĝoj kiuj estas opiniite vidaj ĝenaĵoj kaj ne blokeblaj de la reta peta filtrado.

Ŝalti ĉi tiun trajton pligrandigas la memoruzadon de uBlock₀.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignori ĝeneralajn ornamajn filtrilojn", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apliki ŝanĝojn", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Interna", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamoj", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privateco", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domajno kun fiprogramaro", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Ĝenoj", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Plurcela", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regionoj, lingvoj", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Tajlorita", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importi...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Unu regulo por ĉiu linio. Prefiksitaj linioj kun ‘!’ estos ignorataj. Nevalidaj ligiloj estos ignorataj silente.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "malaktuala", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "vidi enhavon", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Lasta ĝisdatigo: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ĝisdatigo...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Reta eraro malhelpis ĝisdatigon de la resurso.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Unu filtrilo por ĉiu linio. Filtrilo povas esti ordinara gastignomo aŭ Adblock Plus-kongrua filtrilo. Prefiksitaj linioj kun ‘!’ estos ignorataj.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importi kaj postaldoni", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksporti", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "miaj-statikaj-ublock-filtriloj_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apliki ŝanĝojn", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Daŭraj reguloj", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Nedaŭraj reguloj", + "description": "header" + }, + "rulesRevert": { + "message": "Malfari", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Apliki", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Redakti", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Konservi", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Nuligi", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importi el dosiero...", + "description": "" + }, + "rulesExport": { + "message": "Eksporti al dosiero", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "miaj-dinamikaj-ublock-reguloj_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Listo de viaj dinamikaj filtradaj reguloj.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintakso de reguloj: fonto celo tipo ago (kompleta dokumentado).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordigi:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Speco de regulo", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Fonto", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Celo", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Via listo de gastignomoj por kiuj uBlock₀ estos malŝaltata. Unu gastignomo por ĉiu linio. Nevalidaj gastignomoj estos ignorataj silente.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importi kaj postaldoni", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksporti", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mia-ublock-blanklisto_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apliki ŝanĝojn", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domajno", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Ligilo", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtrilo", + "description": "English: Filter" + }, + "logAll": { + "message": "Ĉio", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Fonaj petoj", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Nuna langeto", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reŝargi la langetan enhavon", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Baskuligi la DOM-inspektilon", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Baskuligi la ŝprucpanelon", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "Dokumentaro de uBlock Origin: la protokolilo", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Klariĝi protokolilon", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Paŭzigi protokolilon (forĵeti ĉiujn envenantajn datenojn)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Malpaŭzigi protokolilon", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Baskuligi filtradon de protokolilo", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtri protokolerojn", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opcioj pri filtrado de protokolilo", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ne", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokita", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permesata", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modifita", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "rekta", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "nerekta", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detaloj", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtrilo", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Listo de filtriloj", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regulo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kunteksto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Ĉefa kunteksto", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Nivelo de rekteco", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Retadreso", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dinamika filtrado de ligiloj", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kunteksto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statika filtrado", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} retaj petoj de {{type}} {{br}}kiu ligilo estas la sama kiel {{url}} {{br}}kaj kiu devenas el {{origin}},{{br}}{{importance}} estas kongrua escepta filtrilo.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloki", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permesi", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ajna tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "de “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "de ie ajn", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "krom se", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "eĉ se", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statika filtrilo {{filter}} estas trovita en:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Kaŝi kolumnojn:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} tempo", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} filtrilo/regulo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} kunteksto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} rekteco", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Listo", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabulo", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Simpla", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Malfermi", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Krei novan raporton", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Serĉi similajn raportojn", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentaro", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Legu la dokumentaron ĉe uBlock/wiki por lerni ĉiujn funkciojn de uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Demandoj kaj subtenado", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemoj pri filtrilo / la retejo misfunkcias", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "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" + }, + "supportS3P2": { + "message": "Important: Avoid using other similarly-purposed blockers along with uBlock Origin, as this may cause filter issues on specific websites.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Raporto pri cimo", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Raportu problemojn pri uBlock Origin mem ĉe la cimspurilo uBlockOrigin/uBlock-issue. Tio postulas konton ĉe GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informoj pri problemsolvado", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Jen teknikaj informoj eble utilaj al tiuj volontuloj, kiuj helpas vin solvi problemon.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Raporti problemon pri filtrado", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adreso de la retpaĝo:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "La retpaĝo…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Elektu ion --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Montras reklamojn aŭ restaĵojn de reklamoj", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Havas plustavolojn aŭ aliajn ĝenaĵojn", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detektas uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Havas problemojn pri privateco", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Misfunkcias, se uBlock Origin estas ŝaltita ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Malfermas nedeziratajn langetojn aŭ fenestrojn", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Marki la paĝon kiel «nelabortaŭgan»", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Reguloj pri privateco", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Ŝanĝoprotokolo", + "description": "" + }, + "aboutCode": { + "message": "Fontkodo (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Kontribuantoj", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Fontkodo", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tradukoj", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listoj de filtriloj", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Eksteraj dependaĵoj (kongruaj kun GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "La proprajn filtrilojn de uBO gastigas la jenaj enhavo-liverantaj retoj:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Kiam filtrilo postulas ĝisdatigon, hazarde elektita enhavo-liveranta reto estas uzata.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Savkopii al dosiero", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "mia-ublock-savkopio_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaŭri el dosiero...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Remeti normajn agordojn...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Ĉiuj viaj agordoj estos anstataŭigitaj per via savkopio kreita je {{time}} kaj uBlock₀ restartigos.\n\nĈu vi volas anstataŭigi ĉiujn de viaj ekzistantaj agordoj uzita la savkopio?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "La datumoj ne legeblas aŭ ĝi estas nevalida", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Ĉiuj viaj agordoj estos forigita kaj uBlock₀ restartigos.\n\nĈu vi volas reagordi uBlock₀ al la defaŭltaj agordoj?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "{{url}} ne konekteblas", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Ĉu vi volas aldoni la sekvan ligilon al viaj tajloritaj listoj de filtriloj?\n\nTitolo: \"{{title}}\"\nLigilo: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Sekvi", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "antaŭ 1 minuto", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "antaŭ {{value}} minutoj", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "antaŭ 1 horo", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "antaŭ {{value}} horoj", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "antaŭ 1 tago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "antaŭ {{value}} tagoj", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Montri panelon", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Montri protokolilon", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "ne aktiva", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Paĝo blokita", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ preventis la ŝarĝadon de la sekva paĝo:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Pro la sekva filtrilo", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sen parametroj", + "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": "Trovita en:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Reen", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Fermi ĉi tiun fenestron", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Malŝalti striktan blokadon por {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Nedaŭra", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Daŭra", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Procedi", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksporti al nuba konservado", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importi el nuba konservado", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importi el nuba konservado kaj kunfandi kun nunaj agordoj", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nomo de ĉi tiu aparato:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Averto! Tiuj altnivelaj opcioj esta eble danĝeraj.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Sendi", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apliki ŝanĝojn", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Malfari", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajtoj", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloki elementon en kadro…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Aboni filtrilon…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permesi grandajn aŭdvideajn elementojn nedaŭre", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Vidi fontkodon...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Tajpu alirklavon", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Baskuligi ŝlositan rulumadon", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopii al tondujo", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Elekti ĉiujn", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Baskuligi ornaman filtradon", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Malstriktigi blokadan reĝimon", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Uzata memoro: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "kB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Alklaku por ŝarĝi", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Eraroj: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json new file mode 100644 index 0000000..17652b9 --- /dev/null +++ b/src/_locales/es/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Por fin, un bloqueador eficiente con uso mínimo de procesador y memoria.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Panel de control", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "¡Atención! Tienes cambios sin guardar", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Conservar", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorar", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Configuración", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listas de filtros", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mis filtros", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mis reglas", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Sitios de confianza", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Atajos", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Registro de peticiones", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Acerca de", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Soporte", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visor de recursos", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Configuración avanzada", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clic: deshabilitar/habilitar uBlock₀ en este sitio.\n\nCtrl+clic: deshabilitar uBlock₀ solo en esta página.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Clic para deshabilitar uBlock₀ en este sitio.\n\nCtrl+clic para deshabilitar uBlock₀ solo en esta página.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clic para habilitar uBlock₀ en este sitio.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "peticiones bloqueadas", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "en esta página", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} o {{percent}} %", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "desde que se instaló", + "description": "English: since install" + }, + "popupOr": { + "message": "o", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloqueado en esta página", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloqueado desde que se instaló", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Dominios conectados", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Abrir panel de control", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Entrar al modo eliminación de elementos", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Entrar al modo selección de elementos", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Ir al registro de peticiones", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Reportar un problema en este sitio web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alternar bloqueo de todas las ventanas emergentes en este sitio", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clic para bloquear todas las ventanas emergentes en este sitio", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clic para no bloquear más todas las ventanas emergentes en este sitio", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Alternar bloqueo de elementos multimedia grandes en este sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clic para bloquear elementos multimedia grandes en este sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clic para no bloquear más elementos multimedia grandes en este sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Alternar el filtrado cosmético en este sitio", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Clic para deshabilitar el filtrado cosmético en este sitio", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Clic para habilitar el filtrado cosmético en este sitio", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Alternar bloqueo de fuentes remotas en este sitio", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clic para bloquear fuentes remotas en este sitio", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clic para no bloquear más fuentes remotas en este sitio", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Clic para deshabilitar JavaScript en este sitio", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Clic para no deshabilitar más JavaScript en este sitio", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ventanas emergentes", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elementos multimedia grandes", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtrado cosmético", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fuentes remotas", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Más", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menos", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Reglas globales: las reglas en esta columna se aplican a todos los sitios.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Haz clic para hacer tus cambios permanentes.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Haz clic para revertir tus cambios.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "todo", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imágenes", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "peticiones de terceros", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/imágenes de terceros", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripts integrados", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts del dominio", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts de terceros", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames de terceros", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "dominios conectados", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versión", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Crear", + "description": "English: Create" + }, + "pickerPick": { + "message": "Elegir", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Salir", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Vista previa", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtros de red", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtros cosméticos", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clic, Ctrl-clic", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloquear elemento…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ocultar marcadores de posición de los elementos bloqueados", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Mostrar el número de peticiones bloqueadas en el icono", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Deshabilitar las descripciones emergentes", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Hacer uso del menú contextual cuando sea posible", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Accesible para daltónicos", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Apariencia", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Tono de color personalizado", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Habilitar almacenamiento en la nube", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Soy usuario avanzado", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Deshabilitar pre-carga de sitios (previene cualquier conexión para peticiones de red bloqueadas)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Deshabilitar auditoría de hipervínculos", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Impedir que WebRTC divulgue la dirección IP local", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportamiento predeterminado", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Es posible anular el comportamiento predeterminado para cada sitio", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Deshabilitar el filtrado cosmético", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloquear elementos multimedia mayores que {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloquear fuentes remotas", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Deshabilitar JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloquear reportes CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Desvelar nombres canónicos", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avanzado", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Características aptas solo para usuarios técnicos", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "configuración avanzada", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Última restauración:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Último respaldo:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtros de red y {{cosmeticFilterCount}} filtros cosméticos de:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} utilizados de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Actualizar automáticamente las listas de filtros", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Actualizar ahora", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Vaciar todas las memorias caché", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizar y aplicar filtros cosméticos", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Los filtros cosméticos sirven para ocultar elementos que se consideran una molestia visual en una página web, y que no pueden ser bloqueados por los motores de filtrado basados ​​en peticiones de red.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorar los filtros cosméticos genéricos", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Los filtros cosméticos genéricos son aquellos filtros cosméticos que se aplican a todos los sitios web. Al habilitar esta opción se elimina el riesgo de sobrecarga a la CPU y exceso de uso de la memoria que resulta del procesamiento de los filtros cosméticos genéricos.\n\nSe recomienda habilitar esta opción en dispositivos poco potentes.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspender actividad de la red hasta que todas las listas de filtros estén cargadas", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista de dominios bloqueados", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar cambios", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Incluidos", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Anuncios", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacidad", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Protección de malware, seguridad", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Elementos molestos", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multiusos", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regiones, idiomas", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizado", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importar…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Una URL por línea. Las URL no válidas serán ignoradas.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Desactualizado.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ver contenido", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Última actualización: {{ago}}.\nHaz clic para actualizar ahora.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Actualizando…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Un error de red impide que se actualicen los recursos.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Un filtro por línea. El filtro puede ser un nombre de dominio, o un filtro compatible con EasyList. Las líneas que comiencen con ! serán ignoradas.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "No añadir filtros de fuentes no confiables.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importar y anexar…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportar…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-mis-filtros-estaticos_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar cambios", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Reglas permanentes", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Reglas temporales", + "description": "header" + }, + "rulesRevert": { + "message": "Revertir", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Establecer", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Editar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Guardar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Descartar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importar desde archivo…", + "description": "" + }, + "rulesExport": { + "message": "Exportar a archivo…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-mis-reglas-dinamicas_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista de tus reglas de filtrado dinámico.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaxis de las reglas: origen destino tipo acción (documentación completa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordenar:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipo de regla", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Fuente", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destino", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Sitios de confianza para los cuales se deshabilitará uBlock Origin. Una entrada por línea.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importar y anexar…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportar…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-mis-sitios-de-confianza_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar cambios", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Dominio", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtro", + "description": "English: Filter" + }, + "logAll": { + "message": "Todo", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Sin pestaña", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Pestaña actual", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Recargar contenido de la pestaña", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Alternar el inspector DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Alternar el panel emergente", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Registro de peticiones", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Borrar el registro de peticiones", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausar registro de peticiones (descarta todos los datos entrantes)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Continuar con el registro de peticiones", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Alternar el filtrado del registro de peticiones", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrar contenido", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opciones de filtrado del registro de peticiones", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "No", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "destacado", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloqueado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permitido", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "petición del dominio", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "petición de tercero", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalles", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtro", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista de filtros", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regla", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contexto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contexto raíz", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Tipo de petición", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Regla de URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contexto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtro estático", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} peticiones de red de {{type}} {{br}}cuya dirección URL contenga {{url}} {{br}}y que se origine {{origin}},{{br}}{{importance}} exista una regla de excepción aplicable.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloquear", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permitir", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "cualquier tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "desde “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "desde cualquier lugar", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "excepto cuando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "incluso cuando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtro estático {{filter}} encontrado en:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "No se pudo encontrar el filtro estático en ninguna de las listas de filtros actualmente habilitadas", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Las entradas del registro de peticiones que no cumplan las tres condiciones a continuación se descartarán automáticamente:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Conservar entradas de los últimos {{input}} minutos", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Conservar como máximo {{input}} cargas de página por pestaña", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Conservar como máximo {{input}} entradas por pestaña", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Usar {{input}} líneas por entrada en modo expandido verticalmente", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ocultar columnas:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Hora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtro/regla", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contexto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Tipo de petición", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabla", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Sin formato", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Formato markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Abrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Crear nuevo reporte", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Encontrar reportes similares", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentación", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lee la documentación en uBlock/wiki para aprender sobre todas las características de uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Preguntas y soporte", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Respuestas a preguntas y otros tipos de ayuda se proporcionan en el sub-reddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemas de filtros/sitio web roto", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Reportar problemas de filtros con sitios web específicos en el registro de problemas uBlockOrigin/uAssets. Requiere una cuenta en GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Importante: evita utilizar otros bloqueadores con propósito similar junto con uBlock Origin, ya que esto puede causar problemas de filtros en sitios web específicos.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Consejos: asegúrate de que tus listas de filtros estén actualizadas. El registro de peticiones es la principal herramienta para diagnosticar problemas relacionados con los filtros.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Reportar error", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Reportar problemas con uBlock Origin en el registro de problemas uBlockOrigin/uBlock-issue. Requiere una cuenta en GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Información para solucionar problemas", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "A continuación encontrarás información técnica que puede ser útil cuando los voluntarios intenten ayudarte a resolver un problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Importante: la información potencialmente privada o sensible se redacta de forma predeterminada. La información redactada puede dificultar la resolución de un problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Reportar un problema de filtro", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Para evitar sobrecargar a voluntarios con reportes duplicados, verifica que el problema no haya sido reportado.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Las listas de filtros se actualizan diariamente. Asegúrate de que tu problema no haya sido abordado en las listas de filtros más recientes.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifica que el problema aún exista después de recargar la página web problemática.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Dirección de la página web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "La página web…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Elige una entrada --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Muestra anuncios o restos de anuncios", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Tiene superposiciones u otras molestias", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detecta uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Tiene problemas relacionados con la privacidad", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Se rompe cuando uBlock Origin está habilitado", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Abre pestañas o ventanas no deseadas", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Etiquetar la página web como “NSFW” (“no es seguro/apropiado para el trabajo”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redactar", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Sin redactar", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Política de privacidad", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Registro de cambios", + "description": "" + }, + "aboutCode": { + "message": "Código fuente (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Colaboradores", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Código fuente", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traducciones", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listas de filtros", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependencias externas (compatibles con GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Las listas de filtros propias de uBO se alojan de forma gratuita en las siguientes CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Se utilizará una CDN elegida al azar cuando sea necesario actualizar una lista de filtros.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Respaldar en archivo…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-mi-respaldo_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaurar desde archivo…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Restablecer ajustes predeterminados…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Toda la configuración se sobrescribirá utilizando datos respaldados en {{time}} y uBlock₀ se reiniciará.\n\n¿Sobrescribir toda la configuración existente utilizando los datos de respaldo?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Los datos no se pueden leer o no son válidos", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Se borrará todas tus configuraciones y uBlock₀ se reiniciará.\n\n¿Restablecer uBlock₀ a la configuración predeterminada?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Error de red: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "¿Deseas añadir la siguiente URL a tus listas de filtros personalizados?\n\nTítulo: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Suscribirse", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "hace un minuto", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "hace {{value}} minutos", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "hace 1 hora", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "hace {{value}} horas", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "hace un día", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "hace {{value}} días", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Mostrar panel de control", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Mostrar registro de peticiones", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "deshabilitado", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Página bloqueada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin impidió la carga de la página:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Como resultado del siguiente filtro:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sin parámetros", + "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 en:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Regresar", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Cerrar esta ventana", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "No me adviertas de nuevo sobre este sitio", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Deshabilitar bloqueo estricto para {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporalmente", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentemente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Continuar", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportar datos a la nube", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importar datos de la nube", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importar desde la nube y anexar a la configuración actual", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nombre de este dispositivo:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "¡Atención! Cambia estas configuraciones avanzadas bajo tu propio riesgo.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Enviar", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplicar cambios", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revertir", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloquear elemento en frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Suscribirse a lista de filtros…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permitir temporalmente elementos multimedia grandes", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Ver código fuente…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Escribe un atajo", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Alternar bloqueo de desplazamiento", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiar al portapapeles", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Seleccionar todo", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Alternar filtrado cosmético", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Modo de bloqueo relajado", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Almacenamiento usado: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clic para cargar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errores: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "No se puede filtrar correctamente al iniciar el navegador. Recarga la página para garantizar el filtrado correcto.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Esta entrada debe ser la última", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/et/messages.json b/src/_locales/et/messages.json new file mode 100644 index 0000000..07d5abd --- /dev/null +++ b/src/_locales/et/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Lõpuks on valminud tõhus blokeerija. Protsessori- ja mälusõbralik.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Töölaud", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Hoiatus! Sul on salvestamata muutusi", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Jää lehele", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Eira", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Seaded", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtriloendid", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Minu filtrid", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Minu reeglid", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Usaldatud saidid", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Kiirklahvid", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logija", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Teave", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Tugi", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — vara vaatur", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Täpsemad seaded", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klõps: keela/luba uBlock₀ sellel saidil.\n\nCtrl+klõps: keela uBlock₀ ainult sellel lehel.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klõpsa, et keelata uBlock₀ sellel saidil.\n\nCtrl+klõps, et keelata uBlock₀ ainult sellel lehel.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klõpsa, et lubada uBlock₀ sellel saidil.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokeeritud taotlusi", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "sellel lehel", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} või {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "paigaldamise algusest", + "description": "English: since install" + }, + "popupOr": { + "message": "või", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Sellel lehel blokeeritud", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Paigaldamise algusest blokeeritud", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domeene ühendatud", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Ava töölaud", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Sisene elemendi hävitusrežiimi", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Sisene elemendi valikuolekusse", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Ava logija", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Teavita selle veebilehe probleemist", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Keela hüpikaknad sellel saidil", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klõpsa, et keelata kõik hüpikaknad sellel saidil", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klõpsa, et lõpetada hüpikakende keelamine sellel saidil", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Lülita mahukate meediaelementide blokeerimine siin saidil sisse/välja", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klõpsa, et keelata mahukad meediaelemendid sellel saidil", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klõpsa, et lõpetada mahukate meediaelementide keelamine sellel saidil", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Keela ilufiltrid sellel saidil", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klõpsa, et keelata ilufiltrid sellel saidil", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klõpsa, et lubada ilufiltrid sellel saidil", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Luba väliste fontide blokeerimine sellel saidil", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klõpsa, et keelata välisfondid sellel saidil", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klõpsa, et lõpetada välisfontide keelamine sellel saidil", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klõpsa, et keelata JavaScript sellel saidil", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klõpsa, et lõpetada sellel saidil JavaScripti keelamine", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Hüpikaknad", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Suured meediaelemendid", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Ilufiltrid", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Välised fondid", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Rohkem", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Vähem", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Üldised reeglid: selle veeru reeglid kehtivad kõikidele saitidele.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klõpsa, et teha oma muudatused püsivaks.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klõpsa, et võtta muudatused tagasi.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "kõik", + "description": "" + }, + "popupImageRulePrompt": { + "message": "pildid", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3. osapool", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3. osapoole CSS/pildid", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "tekstisisesed skriptid", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1. osapoole skriptid", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3. osapoole skriptid", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3. osapoole raamid", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "ühendatud domeene", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}}/{{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versioon", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "raam", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Loo", + "description": "English: Create" + }, + "pickerPick": { + "message": "Vali", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Välju", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Eelvaade", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Võrgufiltrid", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Ilufiltrid", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klõps, Ctrl-klõps", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokeeri element...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Peida blokeeritud elementide asukohad", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Kuva ikoonil blokeeritud elementide arv", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Keela näpunäited", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Kasuta sobivusel kontekstmenüüd", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Värvipimeduse-sõbralik", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Välimus", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Teema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Kohandatud rõhuvärv", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Luba pilves hoiustamise tugi", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Olen kogenud kasutaja", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Keela eellaadimine (et vältida ühendusi blokeeritud võrgutaotlustele)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Keela hüperlingi auditeerimine", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Tõkesta WebRTC'l kohalike IP-aadresside lekitamist", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Vaikeväärtused", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Neid vaikeväärtusi saab saitide põhiselt eraldi määrata", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Keela ilufiltrid", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokeeri meediaelemendid, mis on suuremad kui {{input}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Keela välised fondid", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Keela JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Keela lehe turvareeglite (CSP-de) aruanded", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Kanooniliste nimede tuvastamine", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Täpsemad", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funktsioonid, mis on sobilikud vaid tehnikas pädevatele kasutajatele.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "täpsemad seaded", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Viimane taastus:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Viimane varundus:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} võrgufiltrit + {{cosmeticFilterCount}} ilufiltrit:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "kasutusel {{used}}/{{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Uuenda filtriloendeid automaatselt.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Uuenda kohe", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Tühjenda kõik vahemälud", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Tuvasta ja rakenda ilufiltrid.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Ilufiltrid peidavad veebilehe elemente, mis häirivad visuaalselt ning mida ei saa blokeerida võrgutaotlustel põhinevate filtreerimismootoritega.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Eira üldiseid ilufiltreid.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Üldised ilufiltrid on need ilufiltrid, mis töötavad kõikidel veebisaitidel. Selle valiku lubamine vähendab veebisaitidel üldiste ilufiltrite kasutamisest tulenevat mälu ja protsessori koormust.\n\nSelle valiku lubamine on soovitatav vähem võimekates seadmetes.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Peata võrguliiklus kõikide filtriloendite laadimiseni", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Blokeeritud domeenide loendid", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Kinnita muudatused", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Sisseehitatud", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklaamid", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privaatsus", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Pahavara kaitse, turvalisus", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Tüütused", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Mitmeotstarbelised", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regioonid, keeled", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Kohandatud", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Impordi...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Üks URL rea kohta. Vigaseid URLe eiratakse hoiatuseta.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "vananenud", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "vaata sisu", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Viimane uuendus: {{ago}}.\nUuendamiseks vajutage.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Uuendamine...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ressursi uuendamist takistas võrgu viga.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Üks filter rea kohta. Filtriks võib olla tavaline hostinimi või EasyListiga ühilduv filter. Eesliitega ! algavaid ridu eiratakse.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Ära lisa filtreid tundmatutest allikatest.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Impordi ja lisa…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Ekspordi…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "minu-ublocki-staatilised-filtrid_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Kinnita muudatused", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Igavesed reeglid", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Ajutised reeglid", + "description": "header" + }, + "rulesRevert": { + "message": "Ennista", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Rakenda", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Muuda", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Salvesta", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Tühista", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Impordi failist...", + "description": "" + }, + "rulesExport": { + "message": "Ekspordi faili…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "minu-ublocki-dünaamilised-reeglid_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Sinu dünaamiliste filtrite reeglide nimekiri.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Reegli süntaks: allikas sihtkoht tüüp tegevus (kogu dokumentatsioon).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sorteeri:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Reegli tüüp", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Allikas", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Sihtkoht", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Usaldatud saitide direktiivid määravad, millistel veebilehtedel peaks uBlock Origin keelatud olema. Üks kirje rea kohta.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Impordi ja lisa…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Ekspordi…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "minu-ublocki-usaldatud-saidid_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Kinnita muudatused", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tüüp", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domeen", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Kõik", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Kaardivaba", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Praegune kaart", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Laadi kaardi sisu uuesti", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Lülita sisse DOM-inspektor", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Lülita sisse hüpikpaneel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin'i viki: Logija", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Tühjenda logija", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Peata logija (ignoreeri sissetulevaid andmeid)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Jätka logimist", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Lülita sisse logija filtreerimine", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtreeri logija sisu", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logija filtreerimise valikud", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Mitte", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "oluline", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokeeritud", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "lubatud", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "muudetud", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1. osapool", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3. osapool", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Andmed", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filtriloend", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Reegel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Juurkontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Osapool", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tüüp", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL'i reegel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tüüp:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Staatiline filtreerimine", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} võrgupäringud {{type}} {{br}}mille URL-aadress vastab väärtusele {{url}} {{br}}ja mis pärineb {{origin}},{{br}}{{importance}} on olemas vastav erandfilter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokeeri", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Luba", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tüübiga “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "mistahes tüübiga", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "domeenilt “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "mistahes domeenilt", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "välja arvatud, kui", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "isegi, kui", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Staatiline filter {{filter}} asub:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Staatilist filtrit ei leitud ühegi hetkel lubatud filtrite loendist", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Logija kirjeid, mis ei vasta kõigile kolmele alumisele tingimusele, eiratakse automaatselt:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Säilita viimase {{input}} minuti kirjed", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Säilita kuni {{input}} lehe laadimist vahekaardi kohta", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Säilita kuni {{input}} kirjet vahekaardi kohta", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Kasuta {{input}} rida kirje kohta vertikaalses laiendatud režiimis", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Peida veerud:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} aeg", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} filter/reegel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} osapool", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Loend", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Lihttekst", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Ava", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Loo uus aruanne", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Leia sarnaseid aruandeid", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumendid", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Loe dokumente kohas uBlock/wiki, et avastada kõik uBlock Origini võimalusi.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Küsimused ja tugi", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Vastused küsimustele ja muud sorti kliendituge pakutakse subredditis /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filtrivead/veebileht on katki", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Teata kindlate veebilehtede filtrivigadest uBlockOrigin/uAssets veahalduris. Nõuab GitHubi kontot.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Oluline: väldi teiste sarnaselt toimivate blokeerijate kasutamist koos uBlock Originiga, see võib põhjustada teatud lehtedel filtrivigu.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Nõuanne: veendu, et filtrinimekirjad on ajakohased. Logija on peamine tööriist filtritega seotud vigade diagnoosimiseks.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Veast teatamine", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Teata uBlock Origini vigadest uBlockOrigin/uBlock-issue veahalduris. Nõuab GitHubi kontot.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Tõrkeotsingu teave", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Allpool on tehniline info, mis võib olla kasulik, kui vabatahtlikud aitavad sul probleemi lahendada.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Oluline: potentsiaalselt privaatne või tundlik info on vaikimisi kaetud. Kaetud info võib probleemi lahendamist raskendada.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Teavita filtri veast", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Vabatahtlike koormuse vähendamiseks veendu, et probleemi pole juba teatatud.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filtriloendeid uuendatakse iga päev. Kindlasti veenduge, kas probleem on juba lahendatud uusimates filtriloendites.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Kontrollige probleemi olemasolu veel kord, laadides muret tekitav veebileht uuesti.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Veebilehe aadress:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Veebileht...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Vali kirje --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Kuvab reklaame või reklaami kohatäitjaid", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Omab ülekatteid või teisi nuhtlusi", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Tuvastab uBlock Origini", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Omab privaatsusega seonduvaid probleeme", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Läheb uBlock Origini olemasolul katki", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Avab soovimatuid kaarte või aknaid", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Sildista veebileht kui „NSFW“ (“tööks sobimatu”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Kata info", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Ära kata infot", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privaatsusteatis", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Muudatuste logi", + "description": "" + }, + "aboutCode": { + "message": "Lähtekood (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Toetajad", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Lähtekood", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tõlked", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filtriloendid", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Välised sõltuvused (ühilduvad GPLv3-ga):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO enda filtriloendid on vabalt hostitud järgnevates sisuedastusvõrkudes:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Filtriloendi uuendamiseks kasutatakse juhuslikult valitud sisuedastusvõrku.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Varunda faili…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "minu-ublocki-varundus_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Taasta failist...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Alusta nullist...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Kõik seaded kirjutatakse üle, kasutades varundust kuupäevast {{time}} ning uBlock₀ taaskäivitatakse.\n\nKirjutan üle kõik praegused seaded varundusandmetega?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Andmeid ei suudetud lugeda või on vigased", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Kõik seaded kustutatakse ning uBlock₀ taaskäivitatakse.\n\nTaastan uBlock₀'i algseadetele?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Võrgu viga: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Kas lisada järgnev URL sinu kohandatud filtrite nimekirja?\n\nPealkiri: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Telli", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "minuti eest", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuti eest", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "tunni eest", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} tunni eest", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "eile", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} päeva tagasi", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Kuva töölaud", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Kuva logija", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "väljas", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Leht blokeeritud", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin on keelanud järgneva lehe laadimise:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Järgneva filtri tõttu", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "parameetriteta", + "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": "Asub filtrites:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Mine tagasi", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Sulge see aken", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ära selle saidi puhul enam hoiata", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Keela karm blokeerimine {{hostname}} jaoks", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Ajutiselt", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Püsivalt", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Jätka", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Ekspordi pilvehoidlasse", + "description": "tooltip" + }, + "cloudPull": { + "message": "Impordi pilvehoidlast", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Impordi pilvekettalt ja ühilda praeguste seadetega", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Selle seadme nimi:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Hoiatus! Muuda täpsemaid seadeid oma vastutusel.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Saada", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Kinnita muudatused", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Ennista", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "baiti", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokeeri raamis olev element...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Telli filtriloend...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Luba ajutiselt mahukad meediaelemendid", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Vaata lähtekoodi…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Kirjuta kiirklahv", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Lülita sisse lukustatud kerimine", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopeeri lõikelauale", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Vali kõik", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Lülita kosmeetilist filtreerimist", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Rahulik blokeerimisrežiim", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Mahtu kasutatud: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klõpsa laadimiseks", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Vigu: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Brauseri avamisel korralikult filtreerimine ebaõnnestus. Selle parandamiseks laadi leht uuesti.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "See sisestus peab olema viimane", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/eu/messages.json b/src/_locales/eu/messages.json new file mode 100644 index 0000000..051bfd9 --- /dev/null +++ b/src/_locales/eu/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Behingoz, blokeatzaile eraginkor bat. PUZ eta memorian arina.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Kontrol panela", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Abisua! Gorde gabeko aldaketak dituzu", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Geratu", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ezikusi", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ezarpenak", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Iragazki-zerrendak", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Nire iragazkiak", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Nire arauak", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Konfidantzazko webguneak", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Lasterbideak", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Egunkaria", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Honi buruz", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Laguntza", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Aktibo-ikuslea", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Ezarpen aurreratuak", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: gaitu/ezgaitu uBlock₀ gune honetan.\n\nKtrl+klik: ezgaitu uBlock₀ orri honetan soilik.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klik: Gaitu/ezgaitu uBlock₀ gune honetan.\n\nKtrl+klik: Desgaitu uBlock₀ orri honetan soilik.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik: Gaitu uBlock₀ gune honetan.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokeatutako eskariak", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "orri honetan", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} edo %{{percent}}", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "instalaziotik", + "description": "English: since install" + }, + "popupOr": { + "message": "edo", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokeatuta orri honetan", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokeatuta instalaziotik", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Konektatutako domeinuak", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Ireki kontrol panela", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Elementuak lekuz aldatzeko modua", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Elementuak hautatzeko modua", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Ireki egunkaria", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Webgune honetan arazo baten berri eman", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Txandakatu laster-leihoen blokeoa gune honetan", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik: Blokeatu gune honetako laster leiho guztiak", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik: Utzi gune honetako laster-leihoak blokeatzeari", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Txandakatu multimedia elementu handiak blokeatzea gune honetan", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik: Blokeatu gune honetako tamaina handiko elementuak", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik: Utzi gune honetako tamaina handiko elementuak blokeatzeari", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Txandakatu iragazki kosmetikoa gune honetan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik: Desgaitu iragazki kosmetikoak gune honetan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik: Gaitu iragazki kosmetikoak gune honetan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Txandakatu urruneko letra tipoen blokeoa gune honetan", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik: Blokeatu urruneko letra-tipoak gune honetan", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik: Utzi urruneko letra-tipoak gune honetan blokeatzeari", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Egin klik gune honetan JavaScript desgaitzeko", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Egin klik gune honetan JavaScript desgaitzeari uzteko", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Laster-leihoak", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Multimedia elementu handiak", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Iragazki kosmetikoak", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Urruneko tipografiak", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Gehiago", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Gutxiago", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Arau orokorrak: Zutabe hau gune guztietan aplikatzen diren arauentzat da.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Sakatu aldaketak gordetzeko.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Sakatu aldaketak desegiteko.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "guztiak", + "description": "" + }, + "popupImageRulePrompt": { + "message": "irudiak", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Hirugarrengoak", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Hirugarrengoen CSS/Irudiak", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "barne scriptak", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "bertako scriptak", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "hirugarrengoen scriptak", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "hirugarrengoen markoak", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "konektatutako domeinuak", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} / {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Bertsioa", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "scripta", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "markoa", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Sortu", + "description": "English: Create" + }, + "pickerPick": { + "message": "Hautatu", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Irten", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Aurreikusi", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Sare iragazkiak", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Iragazki kosmetikoak", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ktrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokeatu elementua...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ezkutatu blokeatutako elementuen hutsuneak", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Bistaratu blokeatutako eskari kopurua ikonoan", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Desgaitu argibideak", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Erabili laster-menua egokia denean", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Kolore-itsuentzat egokia", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Itxura", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Azala", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Azentu-kolore pertsonalizatua", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Gaitu hodei biltegiratzearen euskarria", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Erabiltzaile aurreratua naiz (Irakurri beharrekoa)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Desgaitu aurrez-kargatzea (blokeatutako sare eskaeretako edozein konexio galarazteko)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Desgaitu loturen auditoretza", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Galarazi WebRTCk tokiko IP helbidea iragartzea", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Lehenetsitako portaera", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Lehenetsitako portaera hauek gunez gune gainidatzi daitezke", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Desgaitu iragazki kosmetikoa", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokeatu {{input:number}} kB baino handiagoak diren multimedia elementuak", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokeatu urruneko letra-tipoak", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Desgaitu JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokeatu CSP txostenak", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Erakutsi izen kanonikoak", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Aurreratua", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Erabiltzaile teknikoentzat soilik egokiak diren funtzioak", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "ezarpen aurreratuak", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Azken berreskuratzea:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Azken babeskopia:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} sare iragazki + {{cosmeticFilterCount}} iragazki kosmetiko hemendik:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} erabilita, guztira {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatikoki eguneratu iragazkien zerrenda.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Eguneratu orain", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Garbitu cache guztiak", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Prozesatu eta ezarri iragazki kosmetikoak.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Aukera honek Adblock Plusekin bateragarriak diren “elementuak ezkutatzeko” iragazkiak prozesatzea eta ezartzea gaitzen du. Iragazki hauek nagusiki kosmetikoak dira, web orri batean itsusitzat jo diren eta sare iragazkien bidez blokeatzerik ez dauden elementuak ezkutatzeko balio dute.

Ezaugarri hau gaitzeak uBlock₀en memoria erabilera handitzen du.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ezikusi iragazki kosmetiko orokorrak", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Iragazki kosmetiko orokorrak webgune guztietan aplikatzeko sortu diren iragazki kosmetikoak dira.

uBlock₀ aplikazioak ongi kudeatzen baditu ere iragazki kosmetiko orokorrek wegune batzuetan memoria edo PUZ erabilera nabarmena ekar dezakete handiak eta antzinakoak diren horietan gehienbat.

Aukera hau gaituz iragazki kosmetiko orokorren erabileraren ondoriozko memoria eta PUZ erabilera gehigarria sahiestuko da, eta baita uBlock₀ beraren memoria erabilera gutxiagotu.

Ahalmen gutxiagoko gailuetan aukera hau gaitzea aholkatzen da.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Eten sarearen jarduera iragazki-zerrenda guztiak kargatuta egon arte", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplikatu aldaketak", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Barnekoa", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Iragarkiak", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Pribatutasuna", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware domeinuak", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Eragozpenak", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Helburu anitzekoak", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Eskualdeak, hizkuntzak", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Pertsonala", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Inportatu...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "URL bat lerroko. Baliogabeko URL-ak ezikusiko dira.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zaharkituta.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ikusi edukia", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Azken eguneraketa: {{ago}}.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Eguneratzen...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Sare errore batek baliabidea eguneratzea eragotzi du.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Iragazki bat lerroko. Iragazkia hostalari izen soila izan daiteke, edo Adblock Plusekin bateragarria den iragazki bat. Hasieran ! duten lerroak ezikusiko dira.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Inportatu eta gehitu", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Esportatu", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "nire-ublock-iragazki-estatikoak_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplikatu aldaketak", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Behin betiko arauak", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Behin behineko arauak", + "description": "header" + }, + "rulesRevert": { + "message": "Baztertu", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Behin betiko bihurtu", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Aldatu", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Gorde", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Baztertu", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Inportatu fitxategitik...", + "description": "" + }, + "rulesExport": { + "message": "Esportatu fitxategira", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "nire-ublock-arau-dinamikoak_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Zure iragazki dinamikoen arau zerrenda.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Arauen sintaxia: jatorria helburua mota ekintza(Dokumentazio osoa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordena:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Arau mota", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Iturria", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Helburua", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Zerrenda zuriaren direktibek uBlock zeintzu web orrietan desgaituko den zehazten dute. Sarrera bat lerroko. Baliogabeko ostalari izenak ezikusiko dira.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Inportatu eta gehitu", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Esportatu", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "nire-ublock-zerrendazuria_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplikatu aldaketak", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Mota", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domeinua", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Iragazkia", + "description": "English: Filter" + }, + "logAll": { + "message": "Guztiak", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Atzeko planoan", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Uneko fitxa", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Birkargatu fitxako edukia", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Txandakatu DOM ikuskatzailea", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Txandakatu laster-leiho panela", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Egunkaria", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Garbitu egunkaria", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausatu egunkaria (baztertu jasotako informazioa)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Kendu pausa egunkariari", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Txandakatu egunkariaren iragazkia", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "iragazi egunkariko sarrerak", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Egunkaria iragazteko aukerak", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ez", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokeatuta", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "baimenduta", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "aldatua", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Lehen eskukoa", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Hirugarrengoa", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Xehetasunak", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Iragazkia", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Iragazki-zerrendak", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Araua", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Testuingurua", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Erro testuingurua", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Jatorria", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Mota", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URLa", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL araua", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Testuingurua:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Mota:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Iragazketa estatikoa", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} {{type}} motako sare eskariak {{br}}URL helbidea {{url}} helbidearekin bat datorrenean {{br}}eta jatorria {{origin}} denean,{{br}}{{importance}} bat datorren salbuespen iragazki bat badago.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokeatu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Baimendu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "mota “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "edozein mota", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "hemendik “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "edonondik", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "kenduta", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "nahiz eta", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "{{filter}} iragazki estatikoa aurkitu da hemen:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "{{filter}} iragazki estatikoa ezin izan da aurkitu orain aktibatutako iragazki zerrendetan", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Beheko hiru baldintzak betetzen ez dituzten egunkariko sarrerak automatikoki ezikusiko dira:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Mantendu azken {{input}} minutuetako sarrerak", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Mantendu gehienez {{input}} orrien kargak fitxako", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Mantendu gehienez {{input}} sarrera fitxako", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Erabili {{input}} errenkada sarrerako bertikalki hedatutako moduan", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ezkutatu zutabeak:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Denbora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Iragazkia/araua", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Testuingurua", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} jatorria", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Zerrenda", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Taula", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Laua", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Ireki", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Txosten berri bat sortu", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Antzeko txostenak aurkitu", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentazioa", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Irakurri dokumentazioa uBlock/wiki helbidean, uBlock Originen funtzio guztiak ezagutzeko.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Galderak eta laguntza", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "/r/uBlockOrigin azpidian galderen erantzunak eta beste laguntza mota batzuk eskaintzen dira.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Arazoak iragazkiekin/webguneak ez du funtzionatzen", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Web-gune espezifikoekin iragazteko arazoak jakinaraz iezaguzu hemen: uBlockOrigin/uAssets issue tracker. GitHub kontu bat behar da", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Kontuan izan: Ez erabili antzeko helburua duten beste blokeatzaile batzuk uBlock Originekin batera, horrek arazoak sor baititzake webgune espezifikoetan iragazteko.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Aholkuak Ziurtatu zure iragazki-zerrendak eguneratuta daudela. Erregistratzailea da iragazkiekin lotutako arazoak diagnostikatzeko tresna nagusia.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Errore-txostena", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Arazoak jakinarazi uBlock Originekin arazoen erregistroan uBlockOrigin/uBlock-issueissue tracker. GitHub kontua beharrezkoa da.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Arazoen konponbideari buruzko informazioa", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Jarraian, boluntarioek arazo bat konpontzen laguntzen saiatzen direnean baliagarria izan daitekeen informazio teknikoa aurkituko duzu.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Garrantzitsua: Pribatua edo sentikorra izan daitekeen informazioa modu lehenetsian idazten da. Idatzitako informazioak arazo bat konpontzea zaildu dezake.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Iragazkiko arazo baten berri eman", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Txosten bikoiztuak dituzten boluntarioak ez gainkargatzeko, mesedez egiaztatu arazoa ez dela jakinarazi.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Web orriaren helbidea:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Webgunea...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Aukeratu sarrera bat --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Iragarkiak edo iragarkien hondarrak erakusten ditu", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Gainjartzeak edo bestelako eragozpenak ditu", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin detektatzen du", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Pribatutasun-arazoak ditu", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Funtzionamendu-akatsak uBlock Origin aktibatuta dagoenean", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Ireki nahi ez diren erlaitzak edo leihoak", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Web orria «NSFW» moduan jarri (“Not Safe For Work” )", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Erredaktatu", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Desegin erredakzioa", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Pribatutasun politika", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Aldaketa egunkaria", + "description": "" + }, + "aboutCode": { + "message": "Iturburu kodea (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Parte-hartzaileak", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Iturburu-kodea", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Itzulpenak", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Iragazki-zerrendak", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Kanpo menpekotasunak (GPLv3 lizentziarekin bateragarriak):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBOren iragazki zerrendan CDN hauetan daude:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ausaz aukeratutako CDN bat erabiltzen da iragazki zerrenda bat eguneratu behar denean", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Egin babeskopia fitxategian", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "nire-ublock-babeskopia_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Berreskuratu fitxategitik...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Leheneratu lehenetsitako ezarpenetara...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Zure ezarpen guztiak gainidatziko dira {{time}}ko datuak erabiliz, eta uBlock₀ berrabiaraziko da.\n\nGainidatzi ezarpen guztiak babeskopiako datuekin?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Datuak ezin dira irakurri edo baliogabeak dira", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Zure ezarpen guztiak ezabatuko dira, eta uBlock₀ berrabiaraziko da.\n\nLeheneratu uBlock₀ jatorrizko ezarpenetara?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Sare-errorea: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Gehitu honako URL hauek zure iragazki pertsonalizatuen zerrendara?\n\nIzenburua: \"{{title}}\"\nURLa: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Harpidetu", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "duela minutu bat", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "duela {{value}} minutu", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "duela ordu bat", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "duela {{value}} ordu", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "duela egun bat", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "duela {{value}} egun", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Bistaratu kontrol panela", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Bistaratu egunkaria", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "itzalita", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Blokeatutako orrialdea", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ek orri hau kargatzea galarazi du:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Iragazki hau dela eta", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "parametrorik gabe", + "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": "Hemen aurkitua:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Atzera", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Itxi leiho hau", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ez esan ezer berriz ere orrialde honi buruz", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Ezgaitu blokeatze zorrotza {{hostname}} gunean", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Une batez", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Behin betiko", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Aurrera", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Esportatu hodei biltegiratzera", + "description": "tooltip" + }, + "cloudPull": { + "message": "Inportatu hodei biltegiratzetik", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Inportatu hodeiko biltegiratzetik eta nahastu oraingo ezarpenekin", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Gailu honen izena:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Abisua! Ez aldatu ezarpen aurreratu hauek zertan ari zaren ez badakizu.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Bidali", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplikatu aldaketak", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Baztertu", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Marko bateko elementua blokeatu...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Harpidetu iragazki zerrenda batera...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Une batez baimendu multimedia elementu handiak", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Ikusi iturburu kodea…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Idatzi lasterbide bat", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Txandakatu korritze blokeatua", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiatu arbelera", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Hautatu dena", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Iragazte kosmetikoa txandakatu", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Baretu blokeatze-modua", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Erabilitako biltegiratzea: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Sakatu kargatzeko", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erroreak: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/fa/messages.json b/src/_locales/fa/messages.json new file mode 100644 index 0000000..7736f8d --- /dev/null +++ b/src/_locales/fa/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "بالاخره، یک بلاکر کارآمد. کم حجم بر روی پردازنده و حافظه.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — داشبورد", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "هشدار! شما تنطیمات ذخیره نشده دارید", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "بمان", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "نادیده بگیر", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "تنظیمات", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "لیست‌های فیلتر", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "فیلترهای من", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "قوانین من", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "لیست سپید", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "میانبرها", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — واقعه‌نگار", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "در باره", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "پشتیبانی", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — نماینگر دارایی", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "تنظیمات پیشرفته", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "کلیک: غیر فعال/ فعال کردن uBlock₀ برای این سایت.\n\nکنترل+کلیک: غیر فعال کردن uBlock₀ فقط برای همین صفحه.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "کلیک کنید تا uBlock₀ برای این سایت غیر فعال شود.\n\nهمزمان کلیدکنترل را نگهدارید و کلیک کنید تا uBlock₀ فقط برای این صفحه غیر فعال شود.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "کلیک کنید تا uBlock₀ برای این سایت فعال شود.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "درخواست مسدود شده", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "در این صفحه", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} یا {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "از زمان نصب", + "description": "English: since install" + }, + "popupOr": { + "message": "یا", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "بلاک‌شده در این صفحه", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "بلاک شده از زمان نصب", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "دامنه‌های متصل‌شده", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "باز کردن داشبورد", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "ورود به حالت له کردن اشیاء", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "ورود به حالت انتخاب اشیاء", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "بازکردن واقعه‌نگار", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "گزارش یک اشکال در خصوص این وبسایت", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "تغییر وضعیت انسداد همه‌ی پنجره های بالاپَر برای این سایت", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "کلیک کنید تا همۀ پنجره های بالاپَر در این سایت مسدود شوند", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "کلیک کنید تا دیگر هیچ کدام از پنجره های بالاپَر این سایت مسدود نشوند", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "تغییر وضعیت مسدود کردن عناصر رسانه ای حجیم برای این سایت", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "کلیک کنید تا عناصر رسانه ای حجیم بر روی این سایت مسدود شوند", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "کلیک کنید تا از این به بعد عناصر رسانه ای حجیم روی این سایت مسدود نشوند", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "تغییر وضعیت فیلترزیباسازی برای این سایت", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "کلیک کنید تا فیلتر زیبا سازی بر روی این سایت غیر فعال شود", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "کلیک کنید تا فیلتر زیبا سازی بر روی این سایت فعال شود", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "تغییر وضعیت انسداد فونت های راه دور برای این سایت", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "کلیک کنید تا فونت های راه دور در این سایت مسدود شوند", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "کلیک کنید تا از این به بعد فونت های راه دور در این سایت مسدود نشوند", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "کلیک کنید تا جاوا اسکریپت در این سایت غیرفعال شود", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "کلیک کنید تا جاوا اسکریپت دیگر در این سایت غیرفعال نشود", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "پنجره‌ی پاپ‌آپ", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "اِلمان‌های دارای مدیای بزرگ", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "فیلترهای انتخابی", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "فونت‌های راه دور", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "جاوااسکریپت", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "بیشتر", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "کمتر", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "قوانین همگانی: این ستون برای قوانینی است که برای همۀ سایت ها اعمال می شوند.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "قوانین محلی: این ستون برای قوانینی است که تنها در این وب‌گاه اعمال می شود.\nقوانین محلی بر قوانین سراسری برتری دارد.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "برای دائمی سازی تغییرات کلیک کنید.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "برای دور انداختن تغییراتی که اعمال کرده اید کلیک کنید.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "همه", + "description": "" + }, + "popupImageRulePrompt": { + "message": "تصاویر", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "تصاویر/css سایت های ثالث", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "اسکریپت های درون خطی", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "اسکریپت های 1st-party", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "اسکریپت های 3rd-party", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "فریم های 3rd-party", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "دامنه های دست خورده", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "تعداد {{count}} از {{total}} تا", + "description": "appears in popup" + }, + "popupVersion": { + "message": "نگارش", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "اسکریپت", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "چارچوب", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "ایجاد", + "description": "English: Create" + }, + "pickerPick": { + "message": "انتخاب", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "خروج", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "پیش نمایش", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "فیلترهای شبکه", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "فیلترهای انتخابی", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "کلیک، کنترل-کلیک", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "بلاک کردن این بخش", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "مخفی کردن نگاهدارنده اشیاء بلاک شده", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "نمایش تعداد درخواست های بلاک شده بر روی آیکون", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "غیر فعال سازی راهنماها", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "استفاده از منوی متنی در زمانهای لازم", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "بهینه سازی کور رنگی", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "ظاهر", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "پوسته", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "رنگ اصلی دلخواه", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "فعال سازی پشتیبانی ذخیره سازی ابری", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "من کاربر حرفه ای هستم (لازم است بخوانید)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "غیر فعال کردن واکشی اولیه (برای جلوگیری از هر گونه اتصال برای درخواست های مسدود شدۀ شبکه)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "غیرفعال کردن حسابرسی پیوند", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "جلوگیری کردن از WebRTC از افشاسازی آدرس های IP محلی", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "رفتار پیش فرض", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "تنظیمات مخصوص هر سایت این تنظیمات پیش فرض را لغو می‌کند", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "غیر فعال‌سازی فیلتر زیبا سازی", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "انسداد عناصر رسانه ای حجیم تر از {{input:number}} کیلوبایت", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "انسداد فونت های راه دور", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "غیرفعال کردن جاوا اسکریپت", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "مسدود کردن براساس گزارشات سیاست امنیت محتوا", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "اسامی متعارف را از حالت قفل خارج کنید", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "پیشرفته", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "قابلیت‌های مناسب برای کاربران فنی", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "تنظیمات پیشرفته", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "آخرین بازیابی:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "آخرین پشتیبانی:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} فیلتر های شبکه + {{cosmeticFilterCount}} فرم های فیلتر انتخابی:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "تعداد {{used}} از {{total}} مورد استفاده شده", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "بروز رسانی خودکار لیست فیلتر.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "اکنون به روز رسانی شود", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "پاکسازی تمام انبارها", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "تجزیه و اجرای فیلترهای انتخابی.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

این گزینه فیلترهای “مخفی‌کردن اشیا” سازگار با ادبلاک پلاس را تجزیه و اجرا میکند. این فیلتر ها اساساً فنی هستند، آنها اشیاء موجود در صفحه وب را که مزاحم تلقی میشوند و با موتور فیلترینگ شبکه قابل بلاک کردن نیستند را حذف میکنند.

فعال کردن این قابلیت مصرف حافظه ی uBlock را افزایش میدهد.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "نادیده گرفتن فیلترهای زیبا سازی عمومی", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

فیلترهای زیبا سازی عمومی، آن دسته از فیلترهای زیبا سازی هستند که در همه وب سایت ها کاربرد دارند.\n

اگر چه بصورت موثر توسط uBlock₀ انجام شده، ولی فیلترهای عمومی زیبا سازی هنوز هم ممکن است سربار حافظه قابل اندازه گیری و سربار پردازنده در برخی از صفحات وب به جای بگذارد، به ویژه برای صفحات وب بزرگ و طولانی مدت.

فعال کردن این گزینه سربارهای حافظه و پردازنده را که به صفحات اضافه شده به عنوان نتیجۀ اجرای فیلترهای عمومی زیبا سازی برطرف می‌کند، و همچنین ردپای حافظۀ خود uBlock₀ را کمتر می‌کند

توصیه می شود این گزینه را در دستگاه های با قدرت کمتر فعال کنید.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "تا وقتی همه‌ی فیلترها لود نشده‌اند ارتباط شبکه را قطع کن", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "فهرست میزبان های مسدود شده", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "اعمال تغییرات", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "داخلی", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "تبلیغات", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "حریم خصوصی", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "دامنه های مخرب", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "مزاحم‌ها", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "چند منظوره", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "مناطق، زبانها", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "سفارشی", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "وارد شده", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "هر آدرس در یک خط. خطوطی با پیشوند ‘!’ در نظر گرفته نمیشوند. آدرس های نامعتبر نیز در سکوت نادیده گرفته میشوند.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "منقضی شده.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "نمایش محتویات", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "آخرین به روز رسانی: {{ago}}.\nبرای یک به روز رسانی اجباری کلیک کنید.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "درحال بروزرسانی...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "یک خطای شبکه از بروزشدن این منبع جلوگیری کرد.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "یک فیلتر در هر خط. یک فیلتر می تواند آدرس هاست ساده یا فیلتر سازگار با Adblock plus باشد. خطوط با پیشوند ‘!’ نادیده گرفته می شوند.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "وارد کردن و الحاق", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "خروجي گرفتن", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "اعمال تغییرات", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "قوانین دائمی", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "قوانین موقت", + "description": "header" + }, + "rulesRevert": { + "message": "بازگرداندن", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "ذخیره در منبع", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "ویرایش", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "ذخيره", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "لغو", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "وارد کردن از فایل...", + "description": "" + }, + "rulesExport": { + "message": "خروجی گرفتن به فایل...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "لیست قوانین فیلترینگ پویای شما.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "نحوه استفاده: source destination type action (مستندات کامل).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "مرتب‌سازی:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "نوع قانون", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "منبع ", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "مقصد", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "دستور العمل‌های لیست سفید حکم می‌کند که uBlock₀ باید بر روی کدام یک از صفحات وب غیر فعال باشد. در هر خط فقط یک مورد. دستور العمل‌های نامعتبر بدون اشاره ای نادیده گرفته شده و بیرون انداخته می‌شوند.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "وارد کردن و الحاق", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "خروجي گرفتن", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "اعمال تغییرات", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "نوع", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "دامنه", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "آدرس", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "فیلتر", + "description": "English: Filter" + }, + "logAll": { + "message": "همه", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "پشت صحنه", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "برگۀ فعلی", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "بارگیری مجدد محتوای صفحه", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "تغییر وضعیت جستجوگر DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "تغییر وضعیت پنل پاپ‌آپ", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "ویکی uBlock Origin: ثبت‌کننده رویداد‌ها", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "پاک‌کردن رویداد‌ها", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "توقف ثبت رویداد‌ها (تمام داده‌های ورودی را نادیده بگیر)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "از سرگیری ثبت رویداد‌ها", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "تغییر وضعیت فیلتر ثبت رویداد‌ها", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "فیلتر کردن محتوای لاگ", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "گزینه‌های فیلتر ثبت رویداد‌ها", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "نفی", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "مسدود شده", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "مجاز", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "تغییر کرده", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "طرف سوم", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "جزئیات", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "فیلتر", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "لیست فیلتر", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "قانون", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "محتوا", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "محتوای ریشه", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "نوع", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "آدرس", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "فیلترینگ پویای آدرس اینترنتی", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "زمینه:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "نوع:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "فیلترینگ ایستا", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} درخواست های شبکه از نوع {{type}}{{br}} که مطابقت دارد با آدرس اینترنی {{url}}{{br}} و سرچشمه می‌گیرد از {{origin}}،{{br}}{{importance}} اینها یک فیلتر استثناء از تطبیق هستند.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "انسداد", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "مجاز", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "نوع “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "هر نوعی", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "از “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "از هر جایی", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "بجز وقتی", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "حتی اگر", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "انسداد ایستا {{filter}} یافت شد در:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "فیلتر ایستا {{filter}} در هیچ یک از لیست‌های فیلتر فعال پیدا نشد", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "رویدادهای ورودی که مطابق سه شرط زیر نباشند، بصورت خودکار نادیده گرفته خواهند شد:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "ورودی‌های {{input}} دقیقه اخیر را نگه دار", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "لطفا در هر تب حداکثر {{input}} مدخل نگه‌دارید", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "پنهان‌سازی ستون", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} زمان", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} فیلتر/قانون", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "لیست", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "جدول", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "ساده", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "مارک‌داون", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "باز کردن", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "ایجاد گزارش جدید", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "یافتن گزارش‌های مشابه", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "مستندات", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "مستنداتی که در uBlock/wiki هست را بخوانید تا با تمام امکانات uBlock Origin آشنا شوید.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "سوال‌ها و پشتیبانی", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "پاسخ به سوالات و انواع راهنمایی‌ها در ساب‌ردیت /r/uBlockOrigin ارائه می‌شود.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "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.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "مهم: از مسدودکننده‌های مشابه دیگر در کنار یوبلاک اوریجین استفاده نکنید. این کار ممکن است باعث ایجاد مشکل در فیلترها برای برخی سایت‌ها شود.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "اطلاعات مشکل‌گشایی", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "در زیر اطلاعات فنی آمده که ممکن است برای داوطلبانی که می‌خواهند در حل یک مشکل کمک کنند مفید باشد.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "مهم: اطلاعات شخصی یا حساس به طور پیشفرض ویرایش و مبهم می‌شوند. اطلاعات مبهم‌شده ممکن است حل مشکل را سخت‌تر کند.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "گزارش یک اشکال در فیلتر", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "برای این که وقت داوطلبان با گزارش‌های تکراری گرفته نشوند، لطفا مطمئن شوید که این اشکال قبلا گزارش نشده باشد.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "آدرس صفحه‌ی وب:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "این صفحه‌ی وب...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- یک گزینه را انتخاب کنید --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "تبلیغات یا باقی‌مانده‌هایی از آن نشان می‌دهد", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "یوبلاک اوریجین را تشخیص می‌دهد", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "دارای ایراد مربوط به حریم خصوصی است", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "وقتی یوبلاک اوریجین فعال است عملکرد درستی ندارد", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "تب یا پنجره‌ی ناخواسته باز می‌کند", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "علامت زدن صفحه به عنوان \"NSFW\" (\"نامناسب برای کار\")", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "قوانین حریم خصوصی", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "تغییرات اخیر", + "description": "" + }, + "aboutCode": { + "message": "سورس کد (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "مشارکت کنندگان", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "کد منبع", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "ترجمه‌ها", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "لیست‌های فیلتر", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "وابستگی‌های خارجی (سازگار با GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "لیست‌های فیلتر اصلی uBlock Origin به صورت آزاد در این شبکه‌های تحویل محتوا میزبانی می‌شوند.", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "وقتی که لازم باشد تا یک لیست فیلتر به روزرسانی شود، از یکی از شبکه‌های تحویل محتوا به صورت تصادفی استفاده می‌شود", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "پشتیبان گیری در فایل", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "بازیابی از فایل...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "تنظیم مجدد تنظیمات پیش فرض...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "تمام تنظیمات با استفاده از پشتیبان گیری در {{time}}، رونویسی شده و uBlock₀ مجدد راه اندازی میشود.\n\nتمام تنظیمات موجود با استفاده از داده های پشتیبانی رونویسی شود؟", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "داده ها نمی تواند خوانده شوند و یا نامعتبر اند", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "تمام تنظیمات شما حذف شده و uBlock₀ دوباره راه اندازی خواهد شد.\n\nتنظیم مجدد uBlock₀ به تنظیمات کارخانه؟", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "خطای شبکه: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: آدرس اینترنتی زیر به فهرست فیلتر های سفارشی شما اضافه شود؟\n\nعنوان: \"{{title}}\"\nآدرس: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "آبونه شدن", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 دقیقه پیش", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} دقیقه پیش", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "یک ساعت پیش", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ساعت قبل", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "دیروز", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} روز قبل", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "نمایش داشبورد", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "نمایش واقعه‌نگار", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "خاموش", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ از بارگذاری این صفحات جلوگیری کرده:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "بخاطر فیلتر زیر", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "یافته شده در:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "بازگشت به عقب", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "بستن این پنجره", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "غیر فعال کردن بلاک برای {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "موقتا", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "دائمی", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "صدور به فضای ذخیره سازی ابری", + "description": "tooltip" + }, + "cloudPull": { + "message": "وارد کردن از فضای ذخیره سازی ابری", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "وارد کردن از فضای ذخیره سازی ابری و ادغام با تنظیمات فعلی", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "نام این وسیله:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "هشدار! این تنظیمات پیشرفته را با مسئولیت خود تغییر دهید.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "ارسال", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "اعمال تغییرات", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "بازگرداندن", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "بایت", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "بلاک‌کردن اِلمان در فریم...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "اجازه موقت عناصر رسانه‌ای حجیم", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "یک میانبر وارد کنید", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "تغییر وضعیت پیمایش قفل شده", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "کپی به کلیپ‌بورد", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "انتخاب همه", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "حالت بلاک‌کردن غیرسخت‌گیر", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "فضای مصرفی: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "کیلوبایت", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "مگابایت", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "گیگابایت", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "برای بازکردن کلیک نمایید", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "این باید آخرین مطلب باشد", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/fi/messages.json b/src/_locales/fi/messages.json new file mode 100644 index 0000000..fb3028e --- /dev/null +++ b/src/_locales/fi/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Viimeinkin tehokas estotyökalu, joka ei kuormita prosessoria ja muistia.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Hallintapaneeli", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Varoitus! Olet tehnyt muutoksia, joita ei ole vielä tallennettu", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Älä poistu", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ohita", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Asetukset", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Suodatinlistat", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Omat suodattimet", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Omat säännöt", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Luotetut sivustot", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Pikanäppäimet", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Pyyntöhistoria", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Tietoja", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Tuki", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Resurssien katselu", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Lisäasetukset", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Painallus: poista uBlock₀ käytöstä/ota se käyttöön tällä sivustolla.\n\nCtrl+painallus: poista uBlock₀ käytöstä vain tällä sivulla.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Poista uBlock₀ käytöstä tällä sivustolla painamalla tästä.\n\nCtrl+painallus poistaa uBlock₀:n käytöstä vain tällä sivulla.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Ota uBlock₀ käyttöön tällä sivustolla painamalla tästä.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "pyyntöjä estetty", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "tällä sivulla", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "asennuksen jälkeen", + "description": "English: since install" + }, + "popupOr": { + "message": "tai", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Estetty tällä sivulla", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Estetty asennuksen jälkeen", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Verkkotunnuksia yhdistetty", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Avaa hallintapaneeli", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Avaa elementtien piilotustila", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Avaa elementtien valintatila", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Näytä pyyntöhistoria", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Ilmoita ongelmasta tällä verkkosivustolla", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Muuta ponnahduseston tilaa tällä sivustolla", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Estä kaikki ponnahdukset tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Salli kaikki ponnahdukset tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Muuta suurten mediaelementtien eston tilaa tällä sivustolla", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Estä suuret mediaelementit tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Salli suuret mediaelementit tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Muuta kosmeettisen suodatuksen tilaa tällä sivustolla", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Poista kosmeettinen suodatus käytöstä tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Ota kosmeettinen suodatus käyttöön tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Muuta ulkoisten fonttien lataustilaa tällä sivustolla", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Estä ulkoisten fonttien lataus tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Salli ulkoisten fonttien lataus tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Estä JavaScript tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Salli JavaScript tällä sivustolla painamalla tästä", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ponnahdukset", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Suuret mediaelementit", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmeettinen suodatus", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Ulkoiset fontit", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Enemmän", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Vähemmän", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Yleiset säännöt: Sarake säännöille, joita käytetään kaikilla sivustoilla.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Tee muutoksistasi pysyviä painamalla tästä.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kumoa muutoksesi painamalla tästä.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "kaikki", + "description": "" + }, + "popupImageRulePrompt": { + "message": "kuvat", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3. osapuoli", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Kolmannen osapuolen css/kuvat", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "upotetut komentosarjat", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1. osapuolen komentosarjat", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3. osapuolen komentosarjat", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3. osapuolen kehykset", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "verkkotunnuksia yhdistetty", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}}/{{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versio", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "komentosarja", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "kehys", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Luo", + "description": "English: Create" + }, + "pickerPick": { + "message": "Valitse", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Lopeta", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Esikatsele", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Verkkosuodattimet", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmeettiset suodattimet", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Painallus, Ctrl-painallus", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Estä elementti…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Piilota estettyjen elementtien paikkamerkit", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Näytä estettyjen pyyntöjen määrä", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Älä näytä työkaluvihjeitä", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Käytä kontekstivalikkoa tarvittaessa", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Värisokeille sopiva tila", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Ulkoasu", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Teema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Oma korostusväri", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Käytä pilvitallennusta", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Olen edistynyt käyttäjä", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Älä käytä esihakua (estää kaikki yhteydet estetyiltä verkkopyynnöiltä)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Älä salli hyperlinkkien käytönseurantaa", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Estä paikallisen IP-osoitteen vuoto WebRTC:n välityksellä", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Oletuskäytännöt", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Nämä oletuskäytännöt voidaan ohittaa sivustokohtaisesti", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Älä käytä kosmeetista suodatusta", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Estä mediaelementit, jotka ovat suurempia kuin {{input:number}} kt", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Estä ulkoisten fonttien lataus", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Poista JavaScript käytöstä", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Estä CSP-raportit", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Paljasta kanoniset nimet (CNAME-uncloaking)", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Lisäasetukset", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Teknisille käyttäjille sopivat ominaisuudet", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Lisäasetukset", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Viimeisin palautus:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Viimeisin varmuuskopio:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} verkkosuodatinta + {{cosmeticFilterCount}} kosmeettista suodatinta:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "Käytössä {{used}}/{{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Päivitä suodatinlistat automaattisesti", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Päivitä nyt", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Tyhjennä kaikki välimuistit", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Jäsennä ja pakota kosmeettiset suodattimet", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmeettisten suodattimien tehtävä on piilottaa sivujen elementtejä, jotka on luokiteltu visuaalisiksi ärsykkeiksi ja joiden esto ei ole mahdollista verkkopyyntöjen estoon perustuvien suodatusmoottoreiden avulla.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ohita kosmeettiset yleissuodattimet", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Kosmeettiset yleissuodattimet ovat sellaisia kosmeettisia suodattimia, jotka on tarkoitettu käytettäväksi kaikilla verkkosivustoilla. Tämä asetus poistaa tällaisten suodattimien käsittelystä verkkosivuille aiheutuvan, korkeamman keskusmuistin ja suorittimen kuormituksen.\n\nAsetuksen käyttö on suositeltavaa heikkotehoisilla laitteilla.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Keskeytä verkon toiminta, kunnes kaikki suodatinlistat on ladattu", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista estetyistä osoitteista", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Vahvista muutokset", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Laajennukseen sisältyvät", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Mainokset", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Tietosuoja", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Haittaohjelmasuojaus, tietoturva", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Ärsykkeet", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Yleishyödylliset", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Alueet, kielet", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Muut listat", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Tuo…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Yksi URL-osoite riviä kohden. Virheelliset osoitteet ohitetaan huomaamattomasti.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Vanhentunut", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Näytä sisältö", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Viimeisin päivitys: {{ago}}.\nPakota päivitys painamalla tästä.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Päivitetään…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Verkkovirhe esti resurssin päivityksen.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Yksi suodatin riviä kohden. Suodatin voi olla pelkkä osoite tai EasyList-yhteensopiva suodatin. Rivit, joiden alussa on !, ohitetaan.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Älä lisää suodattimia lähteistä, joihin et luota.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Tuo ja lisää…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Vie…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "omat-staattiset-ublock-suodattimet_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Vahvista muutokset", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Pysyvät säännöt", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Tilapäiset säännöt", + "description": "header" + }, + "rulesRevert": { + "message": "Palauta", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Pysyväksi", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Muokkaa", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Tallenna", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Hylkää", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Tuo tiedostosta…", + "description": "" + }, + "rulesExport": { + "message": "Vie tiedostoon…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "omat-dynaamiset-ublock-saannot_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Listaus dynaamisista suodatussäännöistä.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sääntösyntaksi: lähde kohde tyyppi toiminto (täysi ohje).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Järjestys:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Säännön tyyppi", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Lähde", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Kohde", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Luotettu sivusto -luokitukset määrittelevät millä sivuilla uBlock Originia ei käytetä. Yksi osoite riviä kohden.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Tuo ja lisää…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Vie…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "omat-luotetut-ublock-sivustot_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Vahvista muutokset", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tyyppi", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Verkkotunnus", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Suodatin", + "description": "English: Filter" + }, + "logAll": { + "message": "Kaikki", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Piilotetut", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Nykyinen välilehti", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Lataa välilehden sisältö uudelleen", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Kytke DOM-rakennenäkymä", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Kytke ponnahduspaneeli", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Pyyntöhistoria", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Tyhjennä pyyntöhistoria", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pysäytä pyyntöhistoria (ohita kaikki saapuva tietoliikenne)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Käynnistä pyyntöhistoria", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Muuta pyyntöhistorian suodatusta", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "Suodata pyyntöhistoriaa", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Pyyntöhistorian suodatusvalinnat", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ei", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "tapahtumarikas", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "estetty", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "sallittu", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "muokattu", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1. osapuoli", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3. osapuoli", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Tiedot", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Suodatin", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Suodatinlista", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Sääntö", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteksti", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Juurikonteksti", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Osapuoli", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tyyppi", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL-sääntö", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteksti: ", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tyyppi: ", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Staattinen suodatus", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} verkkopyynnöt, joiden tyyppi on {{type}}, {{br}}URL vastaa osoitetta {{url}} {{br}}ja joiden lähde on {{origin}},{{br}}{{importance}} vastaava poikkeussuodatin.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Estä", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Salli", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "{{type}}", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "mikä tahansa", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "{{origin}}", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "mikä tahansa", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "paitsi, kun löytyy", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "vaikka löytyisi", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Staattinen suodatin {{filter}} löydettiin:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Staattista suodatinta ei löytynyt tällä hetkellä käytössä olevilta suodatinlistoilta", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Merkinnät, jotka eivät täytä alla olevista kolmesta ehdosta jokaista, ohitetaan automaattisesti:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Säilytä merkinnät viimeisten {{input}} minuutin ajalta", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Säilytä enintään {{input}} sivulatausta välilehteä kohden", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Säilytä enintään {{input}} pyyntöä välilehteä kohden", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Näytä pyynnöille {{input}} riviä pystysuutaan laajennetussa tilassa", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Piilota sarakkeita:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Aika", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Suodatin/sääntö", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteksti", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Osapuoli", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Taulukko", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Pelkkä teksti", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown-kieli", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Avaa", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Luo uusi ilmoitus", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Etsi samankaltaisia ilmoituksia", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Ohje", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lue ohjeet sijainnista uBlock/wiki tutustuaksesi uBlock Originin kaikkiin ominaisuuksiin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Kysymykset ja tuki", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Vastauksia kysymyksiin ja muuta tukea on saatavilla /r/uBlockOrigin-subredditistä.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Suodatusongelma/sivusto on hajonnut", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Ilmoita ongelmista suodatuksessa tietyillä sivustoilla uBlockOrigin/uAssets-ongelmaseurannassa. Vaatii GitHub-tilin.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Tärkeää: Vältä muiden vastaavien estotyökalujen samanaikaista käyttöä uBlock Originin kanssa, koska se voi aiheuttaa ongelmia joillakin sivustoilla.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Vinkkejä: Varmista, että suodatinlistasi ovat ajan tasalla. Pyyntöhistoria on pääasiallinen työkalu suodattimiin liittyvien ongelmien selvityksessä.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Virheilmoitus", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Ilmoita uBlock Origin -laajennuksen ongelmista uBlockOrigin/uBlock-ongelmaseurannanssa. Vaatii GitHub-tilin.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Vianmääritystiedot", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Alla on teknisiä tietoja, joista voi olla hyötyä vapaaehtoisille, jotka pyrkivät auttamaan ongelmasi ratkaisussa.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Tärkeää: Mahdolliset yksityiset ja arkaluonteiset tiedot poistetaan oletusarvoisesti. Tietojen puuttuminen saattaa vaikeuttaa ongelman ratkaisemista.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Ilmoita suodatinongelmasta", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Välttääksesi vapaaehtoisten kuormittamisen ylimääräisillä ilmoituksilla, tarkista ensin onko ongelmasta jo ilmoitettu.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Suodatinlistoja päivitetään päivittäin. Varmista, ettei ongelmaasi ole jo korjattu listojen uusissa versioissa.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Vahvista ongelman edelleen esiintyvän kyseisellä verkkosivulla.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Verkkosivun osoite:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Verkkosivu…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Valitse aihe --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Näyttää mainoksia tai niiden jäänteitä", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Sisältää peiteruutuja tai muita ärsykkeitä", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Havaitsee uBlock Originin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Sisältää tietosuojaan liittyviä ongelmia", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Hajoaa, kun uBlock Origin on käytössä", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Avaa ei-toivottuja välilehtiä tai ikkunoita", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Luokittele verkkosivu ns. työpaikalle sopimattomaksi, \"NSFW\" (\"Not Safe For Work\")", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Älä sisällytä", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Sisällytä", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Tietosuojakäytäntö", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Muutoshistoria", + "description": "" + }, + "aboutCode": { + "message": "Lähdekoodi (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Avustajat", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Lähdekoodi", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Käännökset", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Suodatinlistat", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Ulkopuoliset riippuvuudet (GPLv3-yhteensopiva):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO:n omat suodatinlistat ovat vapaasti saatavilla seuraavista sisällönjakeluverkoista:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Suodatinlistat päivitetään satunnaisesti valitusta sisällönjakeluverkosta (CDN).", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Varmuuskopioi tiedostoon…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "oma-ublock-varmuuskopio_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Palauta tiedostosta…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Palauta oletusasetukset…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Kaikki asetuksesi korvataan {{time}} varmuuskopioiduilla tiedoilla ja uBlock₀ käynnistyy uudelleen.\n\nKorvataanko kaikki nykyiset asetukset varmuuskopioduilla tiedoilla?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Tietoja ei voitu lukea tai ne ovat virheellisiä", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Kaikki asetuksesi poistetaan ja uBlock₀ käynnistyy uudelleen. \n\nPalautetaanko uBlock₀ oletusasetuksiin?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Verkkovirhe: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Lisätäänkö seuraava URL-osoite omiin suodatinlistoihisi?\n\nOtsikko: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Tilaa", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "minuutti sitten", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuuttia sitten", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "tunti sitten", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} tuntia sitten", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "päivä sitten", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} päivää sitten", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Näytä Hallintapaneeli", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Näytä pyyntöhistoria", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "ei käytössä", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Sivu estetty", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ on estänyt seuraavan sivun latauksen:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Seuraavan suodattimen vuoksi:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "ilman parametrejä", + "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": "Sisältyy listoihin:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Palaa takaisin", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Sulje tämä ikkuna", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Älä varoita tästä sivustosta uudelleen", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Älä käytä tiukkaa estoa osoitteelle {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Tilapäisesti", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Pysyvästi", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Jatka", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Vie pilvitallennustilaan", + "description": "tooltip" + }, + "cloudPull": { + "message": "Tuo pilvitallennustilasta", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Tuo pilvitallennustilasta ja yhdistä nykyisiin asetuksiin", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Tämän laitteen nimi:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Varoitus! Muuta näitä lisäasetuksia omalla vastuullasi.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Lähetä", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Vahvista muutokset", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Palauta", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "tavua", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Estä elementti kehyksestä…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Tilaa suodatinlista…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Salli suuret mediaelementit tilapäisesti", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Näytä lähdekoodi…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Syötä näppäinyhdistelmä", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Kytke puoliskojen välisen vierityksen lukitus", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopioi leikepöydälle", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Valitse kaikki", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kytke kosmeettinen suodatus", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Kevennetty estotila", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Tallennustilan käyttö: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "kt", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "Mt", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "Gt", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Lataa painamalla tästä", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Virheitä: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Suodatus ei onnistunut kunnolla selaimen käynnistyessä. Päivitä sivu varmistaaksesi kunnollisen suodatuksen.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Tämän on oltava viimeinen merkintä", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/fil/messages.json b/src/_locales/fil/messages.json new file mode 100644 index 0000000..e5b679d --- /dev/null +++ b/src/_locales/fil/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Mainam na pangharang sa content. Magaan sa CPU at memorya.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Babala! Hindi pa na-save ang ilan mong mga pagbabago", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Manatili", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Balewalain", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Mga Setting", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listahan ng mga filter", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mga filter ko", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mga patakaran ko", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Mga pinagkakatiwalaang site", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Mga Shortcut", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Talaan", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Tungkol", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Suporta", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Tingnan ang mga Asset", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Karagdagang mga setting", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Click: patayin/paandarin ang uBlock₀ para sa site na ito.\n\nCtrl+click: patayin ang uBlock₀ sa pahinang ito lang.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "I-click para patayin ang uBlock₀ sa site na ito.\n\nI-Ctrl+click para patayin ang uBlock₀ sa pahinang ito lang.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "I-click para paandarin ang uBlock₀ sa site na ito.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "mga hinarang na hiling", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "sa pahinang ito", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "mula pagka-install", + "description": "English: since install" + }, + "popupOr": { + "message": "o", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Hinarang sa pahinang ito", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Hinarang mula pagka-install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Mga konektadong domain", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Buksan ang dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Buksan ang pantanggal sa mga elemento", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Buksan ang tagapili sa mga elemento", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Buksan ang talaan", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Mag-ulat ng isyu sa website na ito", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Paandarin/patayin ang pagharang sa mga popup sa site na ito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Pindutin upang harangin lahat ng mga popup sa site na ito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Pindutin upang payagan lahat ng mga popup sa site na ito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Paandarin/patayin ang pagharang sa mga malalaking elemento ng media sa site na ito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Pindutin upang harangin ang mga malalaking elemento ng media sa site na ito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Pindutin upang ihinto ang pagharang sa mga malalaking elemento ng media sa site na ito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Paandarin/patayin ang kosmetikong pagfi-filter sa site na ito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Pindutin upang ihinto ang kosmetikong pagfi-filter sa site na ito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Pindutin upang paandarin ang kosmetikong pagfi-filter sa site na ito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Paandarin/patayin ang pagharang sa remote fonts sa site na ito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Pindutin upang harangin ang remote fonts sa site na ito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Pindutin upang ihinto ang pagharang sa remote fonts sa site na ito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Pindutin upang harangin ang JavaScript sa site na ito", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Pindutin upang paandarin ang JavaScript sa site na ito", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Mga window na nagpa-pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Malalaking mga elemento ng media", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetikong pagfi-filter", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Higit pa", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mas konti", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Mga pangkalahatang patakaran: ang hanay na ito ay para sa mga patakarang ipinapatupad sa lahat ng mga site.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Pindutin upang maging permanente ang mga pagbabago mo.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Pindutin upang kanselahin ang mga pagbabago mo.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "lahat", + "description": "" + }, + "popupImageRulePrompt": { + "message": "mga larawan", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "mga 3rd-party na CSS/larawan", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "mga nakapaloob na script", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "mga 1st-party na script", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "mga 3rd-party na script", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "mga 3rd-party na frame", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "mga konektadong domain", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} sa {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Bersyon", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Lumikha", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pumili", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Umalis", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Silipin", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Mga filter sa network", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Mga kosmetikong filter", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "I-click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Harangin ang elemento…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Itago ang placeholder ng mga hinarang na mga elemento", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Ipakita kung ilan ang mga naharang na hiling sa icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Huwag magpakita ng mga tooltip", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Gamitin ang menu sa konteksto kung naaangkop", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Para sa color-blind", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Hitsura", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Pinasadyang kulay ng accent", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Paandarin ang suporta sa imbakan sa cloud", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Isa akong advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Pigilan ang browser na mag-preload ng mga pahinang iniisip nito na baka bisitahin mo (upang pigilan ang koneksyon sa mga hinarang na site)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Pigilan ang pag-audit sa hyperlink", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Pigilan ang WebRTC na magkalat ng mga lokal na IP address", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default na ugali", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Mas sinusunod ang mga per-site na ugali kaysa sa default na ugali", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Ihinto ang kosmetikong pagfi-filter", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Harangin ang mga elemento ng media na mas malaki sa {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Harangin ang remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Harangin ang JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Harangin ang mga ulat ng CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Ilantad ang totoong pagkakakilanlan ng mga kanonikal na pangalan (CNAME)", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Mga feature na angkop lang sa mga gumagamit na maraming alam", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "karagdagang mga setting", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Huling pag-restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Huling pag-backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} (na) mga network filter + {{cosmeticFilterCount}} (na) mga kosmetikong filter mula sa:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} ginagamit sa {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Awtomatikong i-update ang listahan ng mga filter", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "I-update ngayon", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Tanggalin lahat ng mga cache", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Iproseso at ipatupad ang mga kosmetikong filter", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Hinaharang ng kosmetikong filter ang mga elemento sa web page na nakakaabala at hindi maharang ng mga pangharang na nakabase sa mga hiling sa network.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Huwag pansinin ang mga generikong kosmetikong filter", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Ang generikong kosmetikong filter ay ang mga kosmetikong filter na para sa lahat ng mga website. Nakakatipid ito ng memorya at CPU sapagkat ihihinto ang pagproseso sa mga generikong kosmetikong filter.\n\nMainam na gamitin ang opsyong ito sa mga device na hindi ganoon kalakas.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Itigil ang lahat ng mga aktibidad sa network hanggang sa ma-load ang lahat ng mga listahan ng mga filter", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listahan ng mga naharang na host", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Ilapat ang mga pagbabago", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Mga ad", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Pagkapribado", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Mga domain na may malware", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Mga nakakaabalang bagay", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Maraming-mapaggagamitan", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Mga rehiyon o wika", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Ipinasadya", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Mag-import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Isang URL kada linya. Hindi papansinin ang mga invalid na URL.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Luma na", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "tingnan ang nilalaman", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Huling update: {{ago}}.\nPindutin upang pilitin ang pag-update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ina-update…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Hindi na-update ang resource dahil sa isang network error.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Isang filter kada linya. Pwedeng simpleng hostname o EasyList-compatible ang filter. Hindi papansinin ang mga linyang nagsisimula sa !.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Huwag magdagdag ng pangsala mula sa mga hindi katiwa-tiwalang pinagmulan.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "I-import at idagdag", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "I-export", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mga-static-filter-ko-sa-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Ilapat ang mga pagbabago", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Mga permanenteng patakaran", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Mga panandaliang patakaran", + "description": "header" + }, + "rulesRevert": { + "message": "Ibalik", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Ilapat", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Baguhin", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "I-save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Itapon", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Mag-import mula sa file…", + "description": "" + }, + "rulesExport": { + "message": "I-export sa file", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mga-dynamikong-patakaran-ko-sa-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Listahan ng mga dynamikong patakaran mo sa pagfi-filter.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Format ng patakaran: pinagmulan patutunguhan uri aksyon (kumpletong dokumentasyon [sa Ingles]).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Pagsunud-sunurin:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Uri ng patakaran", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Pinagmulan", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Patutunguhan", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Idinidikta nito kung sa aling mga webpage papatayin ang uBlock Origin. Isang entry kada linya.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "I-import at idagdag", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "I-export", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mga-pinagkakatiwalaan-kong-site-sa-ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Ilapat ang mga pagbabago", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Uri", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Lahat", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Walang tab", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Kasalukuyang tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "I-reload ang nilalaman ng tab", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Buksan/isara ang inspektor ng DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Buksan/isara ang popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "wiki ng uBlock Origin: Ang talaan", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Linisin ang talaan", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Ihinto ang tagatala (itapon ang lahat ng papasok na datos)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Ituloy ang pagtatala", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Paandarin/patayin ang pagfi-filter ng talaan", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "nilalaman ng filter sa pagtatala", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Mga opsyon sa pagfi-filter ng talaan", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Hindi", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "inaksyunan", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "hinarang", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "pinayagan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "binago", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Mga detalye", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Listahan ng filter", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Patakaran", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteksto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Pangunahing konteksto", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Pagkapartido", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Uri", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Patakaran sa URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteksto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Uri:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statikong filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} ang mga hiling sa network na {{type}} {{br}}kung tumutugma ang URL address nito sa {{url}} {{br}}at nagmumula ito sa {{origin}},{{br}}{{importance}} may tugmang exception filter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Harangin", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Payagan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "uri “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "anumang uri", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "mula sa “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "mula saanman", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "maliban na lang kung", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "kahit na", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statikong filter {{filter}} sa:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Hindi mahanap ang statikong filter sa mga kasalukuyang ipinapatupad na listahan ng mga filter", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Awtomatikong itatapon ang mga entry sa talaan na hindi nakakasunod sa lahat ng mga kondisyon sa ibaba:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Panatilihin ang mga entry mula sa huling {{input}} (na mga) minuto", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Panatilihin ang hanggang sa {{input}} page load kada tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Panatilihin ang hanggang sa {{input}} entry kada tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Gumamit ng {{input}} (na mga) linya kada entry sa mode na pinalaki patayo", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Itago ang mga hanay:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Oras", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/patakaran", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteksto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Pagkapartido", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Listahan", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Talahanayan", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Buksan", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Gumawa ng bagong ulat", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Maghanap ng mga magkahawig na ulat", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentasyon", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Basahin ang dokumentasyon sa uBlock/wiki upang matuto tungkol sa lahat ng mga feature ng uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Mga tanong at suporta", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Makakapagtanong at sasagutin ka, o makakahingi ka ng higit pang tulong sa subreddit na /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Mga problema sa filter/may problema sa website", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Iulat ang mga problema sa filter sa iilang mga website sa issue tracker ng uBlockOrigin/uAssets. Kailangan mo ng account sa GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Mahalaga: Upang maiwasan ang mga problema sa ilang mga website, iwasang gumamit ng iba pang mga katulad na pangharang sa content kasabay ng uBlock Origin.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tip: Siguraduhing updated ang listahan mo ng mga filter. Gamitin mo ang talaan upang ayusin ang mga problemang naidudulot ng ilang mga filter.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Mag-ulat ng problema", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Iulat ang mga problema ng mismong uBlock Origin sa issue tracker ng uBlockOrigin/uBlock-issues. Kailangan mo ng account sa GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Impormasyon para sa Pag-aayos ng Problema", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Nasa ibaba ang mga teknikal na impormasyon na maaaring makatulong sa mga volunteer na tumutulong masolusyonan ang problema mo.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Mahalaga: Sa default, nakatago ang mga pribado o sensitibong impormasyon. Maaaring mas mahirap masolusyonan ang mga problema dahil sa pagtatago ng pribadong impormasyon.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Mag-ulat ng problema ng filter", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Ang listahan ng pangsala ng kontent ay araw-araw binabago at dinadag-dagan. Siguruhin na ang iyong isyu ay hindi pa napauukulan sa mga pinakabagong update sa listahan ng pangsala. ", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Kumpirmahin na nanatili ang isyu pagkatapos i-reload ang nagkaproblema na pahina ng web.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address ng web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Ang web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pumili rito --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Nagpapakita ng mga ad o mga tira-tira ng ad", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "May overlay o iba pang mga panggulo", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Nade-detect ang uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "May mga problema sa pagkapribado", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Nasisira kung umaandar ang uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Kung anu-anong mga tab o window ang binubuksan", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Markahan bilang hindi dapat tinitignan sa pook-trabahuan (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Itago", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Huwag itago", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Patakaran sa pagkapribado", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Talaan ng mga pagbabago", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Mga nag-ambag", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Mga pagsasalin", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listahan ng mga filter", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Mga panlabas na dependency (angkop sa GPLv3)", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Naka-host sa mga CDN na ito ang mga listahan ng mga filter ng uBO:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Random na pumipili ng CDN ang uBO kung may listahan ng mga filter na kailangang i-update", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "I-back up sa file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup-ko_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Ibalik mula sa file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "I-reset sa mga default na setting…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Papalitan ng datos na binack-up noong {{time}} ang mga setting mo, at magre-restart ang uBlock₀.\n\nPayagang palitan ng naka-back up na data ang kasalukuyan mong mga setting?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Hindi mabasa o invalid ang datos", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Tatanggalin lahat ng mga setting mo, at magre-restart ang uBlock₀.\n\nI-reset ang uBlock₀ sa default na mga setting?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Error sa network: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Idagdag ang sumusunod na mga URL sa iyong listahan ng mga pinasadyang filter?\n\nPangalan: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subaybayan", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "isang minuto ang nakalipas", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} (na) mga minuto ang nakalipas", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "isang oras ang nakalipas", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} (na) mga oras ang nakalipas", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "isang araw ang nakalipas", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} (na) mga araw ang nakalipas", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Ipakita ang Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Ipakita ang Talaan", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "hindi umaandar", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Hinarang ang pahina", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "Hinarang ng uBlock Origin ang sumusunod na pahina sa paglo-load:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Dahil sa sumusunod na filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "kung walang mga parameter", + "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": "Nahanap sa:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Bumalik", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Isarado ang window na ito", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Huwag na akong balaan ulit tungkol sa site na ito", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Patayin ang striktong pagharang para sa {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Pansamantala", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Tumuloy", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "I-export sa imbakan sa cloud", + "description": "tooltip" + }, + "cloudPull": { + "message": "Mag-export mula sa imbakan sa cloud", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Mag-export mula sa imbakan sa cloud at ihalo sa mga kasalukuyang setting", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Itong pangalan ng device:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Babala! Mag-ingat kung babaguhin mo ang mga advanced na setting.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "I-submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Ilapat ang mga pagbabago", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Ibalik", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "(na) mga byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Harangin ang elemento sa frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subaybayan ang listahan ng filter…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Pansamantalang payagan ang mga malalaking elemento ng media", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Tingnan ang source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Magsulat ng shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Paandarin/patayin ang naka-lock na pagso-scroll", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopyahin sa clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Piliin lahat", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Paandarin/patayin ang kosmetikong pagfi-filter", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Babaan ang lebel ng pagharang", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Nagamit na imbakan: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Pindutin upang i-load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Hindi nakapagsala ng maayos nung binuksan ang browser. I-reload ang pahina upang masiguro ang tamang proseso ng pagsasala.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Dapat mahuli ang entry na ito", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json new file mode 100644 index 0000000..8b8cfc5 --- /dev/null +++ b/src/_locales/fr/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Un bloqueur de nuisances efficace, qui ménagera votre processeur et votre mémoire vive.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Tableau de bord", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Attention, vous avez des changements non enregistrés !", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Rester ici", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorer", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Paramètres", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listes de filtres", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mes filtres", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mon filtrage dynamique", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Sites Web fiables", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Raccourcis", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Journal des requêtes réseau", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "À propos", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visionneuse d'éléments", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Paramètres avancés", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clic : Désactiver/Activer uBlock₀ pour ce site.\n\nCtrl+clic : Désactiver uBlock₀ uniquement sur cette page.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Cliquez pour désactiver uBlock₀ pour ce site\n\nCtrl+Clic pour désactiver uBlock₀ uniquement pour cette page", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Cliquez pour activer uBlock₀ pour ce site", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "Requêtes bloquées", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "sur cette page :", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}}, soit {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "depuis toujours :", + "description": "English: since install" + }, + "popupOr": { + "message": "soit", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloqués sur cette page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloqués depuis l'installation", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domaines connectés", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Ouvrir le Tableau de bord", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Entrer en mode Zappeur", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Entrer en mode Sélecteur", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Ouvrir le journal des requêtes", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Rapporter un problème sur ce site Web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Activer/Désactiver le blocage des fenêtres pop-ups pour ce site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Cliquez pour bloquer toutes les pop-ups de ce site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Cliquez pour cesser de bloquer toutes les pop-ups de ce site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Bloquer/Autoriser le chargement d'éléments médias à taille plus importante pour ce site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Cliquez pour bloquer les médias de grande taille sur ce site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Cliquez pour cesser de bloquer les médias de grande taille sur ce site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Activer/Désactiver le filtrage esthétique pour ce site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Cliquez pour désactiver le filtrage esthétique sur ce site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Cliquez pour activer le filtrage esthétique sur ce site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Autoriser/Bloquer le téléchargement des polices d'écriture distantes pour ce site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Cliquez pour bloquer les polices d'écriture distantes sur ce site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Cliquez pour cesser de bloquer les polices d'écriture distantes sur ce site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Cliquez pour désactiver JavaScript sur ce site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Cliquez pour cesser de désactiver JavaScript sur ce site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Fenêtres pop-ups", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Médias de grande taille", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtrage esthétique", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Polices d'écriture distantes", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Plus", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Moins", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Règles globales : Cette colonne concerne des règles qui s'appliquent partout.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Règles locales : Cette colonne concerne des règles qui ne s'appliquent que sur le site actuellement visité.\nLes règles locales supplantent les règles globales.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Cliquez pour rendre les changements opérés permanents.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Cliquez pour annuler les changements opérés.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Tout", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Tierce-partie", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/Images de tierce-partie", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Scripts embarqués", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Scripts du domaine de la page", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Scripts de tierce-partie", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Cadres de tierce-partie", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "Domaines connectés", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} sur un total de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "cadre", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Créer", + "description": "English: Create" + }, + "pickerPick": { + "message": "Cibler", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quitter", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Aperçu", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtres de réseau", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtres esthétiques", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clic, Ctrl-clic", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloquer l'élément", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Cacher les espaces réservés aux éléments bloqués", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Afficher le nombre de requêtes bloquées sur l'icône", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Désactiver les infobulles", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Utiliser le menu contextuel si possible", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Mode Daltonien", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Apparence", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Thème", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Couleur d'accentuation personnalisée", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Activer le stockage des paramètres dans le nuage", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Je suis un utilisateur/une utilisatrice avancé(e)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Désactiver la prédiction des actions sur le réseau (afin d'empêcher toute connexion pour les requêtes réseau bloquées)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Désactiver l'audit hyperlien", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Empêcher la fuite des adresses IP locales via WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportement par défaut", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ces comportements par défaut peuvent être remplacés au cas par cas", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Désactiver le filtrage esthétique", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloquer les éléments médias d'une taille supérieure à {{input}} Ko", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloquer les polices d'écriture distantes", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Désactiver JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloquer les rapports CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Révéler les noms canoniques", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avancé", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Fonctionnalités convenant uniquement aux utilisateurs avancés", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Paramètres avancés", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Date de la dernière restauration :", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Date de la dernière sauvegarde :", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtre(s) réseau et {{cosmeticFilterCount}} filtre(s) esthétique(s) sont actuellement en vigueur :", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} utilisé(s) sur un total de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Mettre à jour les listes de filtres sélectionnées automatiquement", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Mettre à jour maintenant", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Vider tous les caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Utiliser en plus les règles esthétiques", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Les filtres esthétiques servent à cacher des éléments d'une page Web considérés comme une nuisance visuelle, et qui ne peuvent pas être bloqués par le filtrage réseau basé sur les requêtes.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorer les filtres esthétiques génériques", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Les filtres esthétiques génériques sont des filtres esthétiques conçus pour être appliqués sur tous les sites Web. Activer cette option réduira l'utilisation en mémoire et en processeur sur les pages Web.\n\nIl est recommandé d'activer ce paramètre sur des appareils à la puissance modeste.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspendre l'activité réseau jusqu'au chargement de toutes les listes de filtres", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listes prédéfinies d'hôtes à bloquer", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Appliquer", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Intégrées", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Publicités", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Confidentialité", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Protection anti-malware et sécurité", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Nuisances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Tout usage", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Régions, langues", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Vos propres listes", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importer", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Une adresse Web par ligne. Les adresses Web invalides seront ignorées sans avertissement.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Obsolète", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Voir le contenu", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Dernière mise à jour effectuée : {{ago}}\nCliquez pour forcer la mise à jour", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Mise à jour en cours…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Une erreur réseau a empêché la mise à jour de la ressource.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Une règle par ligne. Une règle peut être un simple nom d'hôte, ou encore une règle compatible EasyList. Les lignes débutant par ! seront ignorées.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Il est recommandé de ne pas ajouter de filtres en provenance de sources non fiables.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importer", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exporter", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mes-filtres-statiques-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Appliquer", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Règles permanentes", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Règles temporaires", + "description": "header" + }, + "rulesRevert": { + "message": "Rétablir", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Appliquer", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Éditer", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Enregistrer", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Annuler", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importer à partir du fichier…", + "description": "" + }, + "rulesExport": { + "message": "Exporter vers un fichier", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mes-regles-de-filtrage-dynamique-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Liste de vos règles de filtrage dynamique", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Syntaxe : source destination type action (Documentation complète en anglais)", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Trier :", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Type de règle", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Les directives de site de confiance indiquent sur quelles pages Web uBlock Origin devrait être désactivée. Une entrée par ligne.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importer", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exporter", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mes-sites-fiables-ublock-{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Appliquer", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domaine", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtre", + "description": "English: Filter" + }, + "logAll": { + "message": "Tout", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "En coulisses", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Onglet courant", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Recharger le contenu de l'onglet", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Activer/Désactiver l'Inspecteur DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Activer/Désactiver le panneau pop-up", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "Page Wiki uBlock Origin : Le journal", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Vider le journal", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Mettre en pause le journal (désactive toutes les données entrantes)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Terminer la mise en pause du journal", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Activer le filtrage du journal", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "Filtrer le contenu du journal", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Options de filtrage du journal", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Pas", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "dynamique", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloquée", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "autorisée", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "Modifié", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Domaine de la page", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Tierce-partie", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Détails", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtre", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Liste de filtres", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Règle", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contexte", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contexte racine", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Niveau de partie", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Lien", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Règle de lien", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contexte :", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type :", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtre statique", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} les requêtes réseau de {{type}} {{br}} dont l'adresse Web correspond à {{url}} {{br}} qui provient du domaine {{origin}}, {{br}}{{importance}} il y a un filtre d'exception correspondant", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloquer", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Autoriser", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "tout type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "de n'importe où", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "sauf quand", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "même s'", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtre statique {{filter}} trouvé dans :", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Filtre statique introuvable parmi les listes de filtre actives", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Les entrées du journal ne remplissant aucune des trois conditions ci-dessous seront automatiquement abandonnées :", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Conserver les entrées des {{input}} dernières minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Préserver {{input}} chargements de page maximum par onglet", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Préserver {{input}} entrées maximum par onglet", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Utiliser {{input}} lignes par entrée dans le mode développé verticalement", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Cacher les colonnes :", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Heure", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtre/Règle", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contexte", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Niveau de partie", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Liste", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tableau", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Brut", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Ouvrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Créer un rapport", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Trouver des rapports similaires", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lisez la documentation à uBlock/wiki pour apprendre toutes les fonctionnalités d'uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions et support", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Les réponses aux questions et autres formes d'assistance sont fournies dans le subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problèmes de filtrage/Site Web non fonctionnel", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Rapportez les problèmes de filtrage avec des sites Web spécifiques dans le suivi des problèmes. Nécessite un compte GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Important : Evitez d'utiliser des bloqueurs similaires à uBlock Origin en même temps que ce dernier, car cela peut causer des problèmes de filtrage sur certains sites Web.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Astuces : Assurez-vous que vos listes de filtres sont à jour. Le journal des requêtes est l'outil principal pour diagnostiquer des problèmes liés au filtrage.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Rapporter un bogue", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Rapportez des problèmes avec l'extension uBlock Origin elle-même dans le suivi des problèmes. Nécessite un compte GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informations de dépannage", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Veuillez trouver ci-dessous les informations techniques pouvant aider les bénévoles à vous assister dans la résolution de problème.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important : Les informations potentiellement privées ou sensibles sont retirées par défaut. Ainsi éditées, elles peuvent compliquer la résolution de problème.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Rapporter un problème de filtre", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Pour éviter d'encombrer les contributeurs avec des rapports en double, veuillez vérifier que le problème n'a pas déjà été rapporté.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Les listes de filtres sont actualisées tous les jours. Assurez-vous que votre problème n'ait pas déjà été résolu dans les listes de filtres les plus récentes.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Vérifiez que le problème persiste après avoir rechargé la page Web problématique.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresse de la page Web :", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "La page Web…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Choisir un type --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "affiche des publicités ou des résidus de publicité", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "a une surcouche ou d'autres nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "détecte uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "a des problèmes de confidentialité", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "ne fonctionne pas correctement quand uBlock Origin est activée", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "ouvre des onglets ou fenêtres indésirables", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Marquer le site Web en tant que \"NSFW\" (\"Not Safe For Work\", c'est-à-dire pour public averti/inapproprié au travail)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Retirer les informations potentiellement privées ou sensibles", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Restaurer les informations potentiellement privées ou sensibles", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Politique de confidentialité", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Journal des changements", + "description": "" + }, + "aboutCode": { + "message": "Code Source (Licence GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributeurs", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Code source", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traductions", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listes de filtres", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dépendances externes (compatibles GPLv3) :", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Les propres listes de filtres d'uBO sont hébergées gratuitement sur les RDC suivants :", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Un RDC choisi aléatoirement est utilisé lorsqu'une liste de filtres doit être mise à jour.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Exporter vers un fichier", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "mes-donnees-ublock_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaurer depuis un fichier…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Réinitialiser les réglages", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Vos paramètres seront remplacés par les données sauvegardées le {{time}}, puis uBlock₀ redémarrera.\n\nProcéder à l'importation ?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Les données ne peuvent être lues ou sont invalides", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Vos paramètres seront effacés, puis uBlock₀ redémarrera.\n\nProcéder à la réinitialisation des paramètres ?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Erreur réseau : {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Ajouter le lien suivant à votre sélection de listes de filtrage ?\n\nTitre : \"{{title}}\"\nLien : {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Souscrire", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "Il y a une minute", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "Il y a {{value}} minutes", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "Il y a une heure", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "Il y a {{value}} heures", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "Il y a un jour", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "Il y a {{value}} jours", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Afficher le Tableau de bord", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Voir le Journal", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "Arrêt", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page bloquée", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ a empêché le chargement de la page suivante :", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "À cause du filtre suivant :", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sans 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": { + "message": "Trouvé dans :", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Retour", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Fermer cette fenêtre", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ne plus m'avertir à propos de ce site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Désactiver le blocage strict du domaine {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "De manière temporaire", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "De manière définitive", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Poursuivre", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exporter vers le stockage dans le nuage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importer depuis le stockage dans le nuage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importer depuis le stockage dans le nuage et fusionner avec les réglages actuels", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nom de ce périphérique :", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Attention, modifiez ces paramètres avancés à vos risques et périls.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Appliquer", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Appliquer", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Rétablir", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "octets", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloquer l'élément dans le cadre", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Souscrire à la liste de filtres", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Autoriser temporairement le chargement d'éléments médias à taille plus importante", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Voir la source…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Saisir un raccourci", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Verrouiller/Déverrouiller le défilement", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copier vers le presse-papier", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Sélectionner tout", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Commuter le filtrage esthétique", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Détendre le mode de blocage", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Espace de stockage utilisé : {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "Ko", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "Mo", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "Go", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Cliquez pour charger", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erreurs : {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Échec du filtrage au lancement du navigateur. Rechargez la page pour assurer un filtrage correct.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/fy/messages.json b/src/_locales/fy/messages.json new file mode 100644 index 0000000..886b764 --- /dev/null +++ b/src/_locales/fy/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "Einlik, in effisjinte adblocker. Brûkt hast gjin prosessorkrêft of ûnthâld.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboerd", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warskôging! Net bewarre wizigingen", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Bliuwe", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Negearje", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ynstellingen", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlisten", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Myn filters", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Myn rigels", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Whitelist", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Fluchtoetsen", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Lochboek", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Oer", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Stipe", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ – Middelenviewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Avansearre ynstellingen", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klikke: uBlock₀ foar dizze website yn-/útskeakelje.\n\nCtrl+klikke: uBlock₀ inkeld foar dizze side útskeakelje.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klik om uBlock₀ foar dizze website út te skeakeljen.\n\nCtrl+klik om uBlock₀ inkeld foar dizze side út te skeakeljen.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik om uBlock₀ foar dizze website yn te skeakeljen.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokkearre fersiken", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "op dizze side", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} fan {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "sûnt ynstallaasje", + "description": "English: since install" + }, + "popupOr": { + "message": "of", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokkearre op dizze side", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokkearre sûnt ynstallaasje", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Ferbûne domeinen", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Dashboerd iepenje", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Elemintwiskmodus iepenje", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Elemintkiesmodus iepenje", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Lochboek iepenje", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "In probleem op dizze website melde", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alle pop-ups foar dizze website yn-/útskeakelje", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik om alle pop-ups op dizze website te blokkearjen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik om alle pop-ups op dizze website net mear te blokkearjen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Grutte media-eleminten foar dizze website yn-/útskeakelje", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik om grutte media-eleminten op dizze website te blokkearjen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik om grutte media-eleminten op dizze website net mear te blokkearjen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Kosmetyske filters foar dizze website yn-/útskeakelje", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik om kosmetyske filters op dizze website út te skeakeljen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik om kosmetyske filters op dizze website yn te skeakeljen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Blokkearjen fan eksterne lettertypen foar dizze website yn-/útskeakelje", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik om eksterne lettertypen op dizze website te blokkearjen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik om eksterne lettertypen op dizze website net mear te blokkearjen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klik om JavaScript op dizze website út te skeakeljen", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klik om JavaScript op dizze website net mear út te skeakeljen", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-upfinsters", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Grutte media-eleminten", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetyske filters", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Eksterne lettertypen", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mear", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Minder", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globale rigels: dizze kolom is foar rigels dy't op alle websites fan tapassing binne.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klik om jo wizigingen permanint te meitsjen.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klik om jo wizigingen werom te draaien.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "alles", + "description": "" + }, + "popupImageRulePrompt": { + "message": "ôfbyldingen", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "fan tredden", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/ôfbyldingen fan tredden", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ynline skripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skripts fan de websites sels", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skripts fan tredden", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames fan tredden", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "ferbûne domeinen", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} fan de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Ferzje", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Meitsje", + "description": "English: Create" + }, + "pickerPick": { + "message": "Kieze", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Slute", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Foarbyld", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Netfilters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetyske filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Elemint blokkearje…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Tydlike oantsjutting fan blokkearre eleminten ferstopje", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "It tal blokkearre oanfragen op it ikoan toane", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Tooltips útskeakelje", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Wêr mooglik gebrûk meitsje fan it kontekstmenu", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Kleureblynfreonlik", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Foarmjouwing", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Oanpaste aksintkleur", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Stipe foar cloudûnthâld ynskeakelje", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ik bin in betûfte brûker (Lês dit earst)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Pre-fetching útskeakelje (om eltse ferbining foar blokkearre netwurkfersiken foar te kommen)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Auditing fan keppelingen útskeakelje", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "It lekken fan it lokale IP-adres fia WebRTC opkeare", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standertgedrach", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Dizze standertgedragingen kinne foar eltse website oerskreaun wurde", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Kosmetyske filters útskeakelje", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Media-eleminten grutter as {{input}} KB blokkearje", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Eksterne lettertypen blokkearje", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript útskeakelje", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP-rapporten blokkearje", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Kanonike nammen toane", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avansearre", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Allinnich foar technyske brûkers geskikte funksjes.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "avansearre ynstellingen", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Lêste werstel:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Lêste reservekopy:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} netwurkfilters + {{cosmeticFilterCount}} kosmetyske filters fan:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} gebrûk fan {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Filterlisten automatysk fernije.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "No fernije", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Alle buffers leegje", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Kosmetyske filters ynlêze en tapasse.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetyske filters binne foar it ferstopjen fan eleminten yn in webside dy't fisueel steurend wêze kinne en net troch de op netwurkoanfragen basearre filter-masinen blokkearre wurde kinne.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Algemiene kosmetyske filters negearje", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Algemiene kosmetyske filters binne dy kosmetyske filters dy't bedoeld binne om op alle websites tapast te wurden. It ynskeakeljen fan dizze opsje eliminearret de oan websiden tafoege ûnthâld- en cpu-oerhead as gefolch fan it ferwurkjen fan algemiene kosmetyske filters.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Netwurkaktiviteit ûnderbrekke oant alle filterlisten laden binne", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "List fan blokkearre hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Wizigingen tapasse", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Lokaal", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Advertinsjes", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malwaredomeinen", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Ungeriif", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multifunksjoneel", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Gebieden, talen", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Oanpast", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Ymportearje…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Ien URL per rigel. Unjildige URL's wurde stil negearre.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Ferâldere.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ynhâld werjaan", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Lêste fernijing: {{ago}}.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Fernijt…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "In netwurkflater hat opkeard dat de boarne bywurke waard.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ien filter per rigel. In filter kin in gewoane hostnamme of in Adblock Plus-kompatibel filter wêze. Rigels begjinnend mei ! wurde negearre.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Foegje gjin filters fan ûnbekende boarnen ta.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Ymportearje en tafoegje", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksportearje", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "myn-ublock-statyske-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Wizigingen tapasse", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permaninte rigels", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Tydlike rigels", + "description": "header" + }, + "rulesRevert": { + "message": "Tebeksette", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Tapasse", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Bewurkje", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Bewarje", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Annulearje", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Ut bestân ymportearje…", + "description": "" + }, + "rulesExport": { + "message": "Nei bestân eksportearje", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "myn-ublock-dynamyske-rigels_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List fan jo dynamyske filterrigels.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rigelsyntaks: boarne bestimming type aksje (folsleine dokumintaasje).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortearje:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rigeltype", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Boarne", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Bestimming", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "De fertroude-website-ynstruksjes skriuwe foar op hokker websiden uBlock Origin útskeakele wurde moat. Ien fermelding per rigel.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Ymportearje en tafoegje", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksportearje", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "myn-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Wizigingen tapasse", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domein", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alles", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Efter de skermen", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktuele ljepblêd", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "De ljepblêdynhâld fernije", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "De DOM-inspector yn-/útskeakelje", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "It pop-uppaniel yn-/útskeakelje", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin-wiki: de logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Logger wiskje", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Lochboek pauzearje (alle ynkommende gegevens negearje)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Lochboek ferfetsje", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Loggerfiltering yn-/útskeakelje", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "loggerynhâld filterje", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opsjes foar loggerfiltering", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Net", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "ôfwikseljend", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokkearre", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "tastien", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "oanpast", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "aktuele domein", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "fan tredden", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterlist", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rigel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Haadkontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "1e/3e partij", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dynamyske URL-filtering", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statysk filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} netwurkfersiken fan {{type}} {{br}}wêrfan de URL lyk is oan {{url}} {{br}}en dy komme fan {{origin}},{{br}}{{importance}} der is in oerienkomstich útsûnderingsfilter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokkearje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Tastean", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "elts type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "fan “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "fan oeral wei", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "útsein as", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "sels as", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statysk filter {{filter}} fûn yn:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statysk filter koe net yn ien fan de op dit stuit ynskeakele filterlisten fûn wurde", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggerfermeldingen dy't net oan alle trije fan de ûndersteande betingsten foldogge, wurde automatysk negearre:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Fermeldingen fan de lêste {{input}} minuten behâlde", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Maksimaal {{input}} sideladingen per ljepblêd behâlde", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Maksimaal {{input}} fermeldingen per ljepblêd behâlde", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "{{input}} rigels per fermelding yn fertikaal útklappe modus brûke", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Kolommen ferstopje:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tiid", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rigel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} 1e/3e partij", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plat", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Iepenje", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Nije melding meitsje", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Soartgelikense meldingen sykje", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumintaasje", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lês de dokumintaasje op uBlock/wiki foar mear ynfo oer alle funksjes fan uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Fragen en stipe", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Antwurden op fragen en oare soarten stipe wurde levere op de subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterproblemen/website wurket net", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Meld filterproblemen mei spesifike websites op de probleemtracker. Fereasket in GitHub-account.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Wichtich: mij it gebrûk fan oare adblockers foar itselde doel yn kombinaasje mei uBlock Origin, omdat dit op bepaalde websites problemen jaan kin.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: soargje derfoar dat jo filterlisten by-de-tiid binne. De logger is it primêre helpmiddel foar it analysearjen fan filterrelatearre problemen.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bugmelding", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Meld problemen mei uBlock Origin sels by de probleemtracker. Fereasket in GitHub-account.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Probleemoplossingsynformaasje", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Hjirûnder stiet technyske ynformaasje dy't handich wêze kin wannear't frijwilligers jo probearje te helpen by it oplossen fan in probleem.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Wichtich: mooglik gefoelige of priveegegevens wurde standert redigearre. Redigearre gegevens kinne it oplossen fan in probleem swierder meitsje.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "In filterprobleem melde", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Kontrolearje oft it probleem net earder meld is om foar te kommen dat frijwilligers mei dûbele meldingen belêst wurde.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlisten wurde elke dei bywurke. Kontrolearje oft jo probleem net al yn de meast resinte filterlisten ferholpen is.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Kontrolearje oft it probleem noch hieltyd bestiet nei opnij laden fan de problematyske webside.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adres fan de webside:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "De webside...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Meitsje in kar --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Toant advertinsjes of restanten", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Hat oerlapingen of oare ûngemakken", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detektearret uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Hat privacy-relatearre problemen", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Wurket net as uBlock Origin ynskeakele is", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Iepenet net-winske ljepblêden of finsters", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "De webside labelje as ‘NSFW’ (‘Not Safe For Work’)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redigearje", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Redigearje ûngedien meitsje", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacybelied", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Wizigingenlochboek", + "description": "" + }, + "aboutCode": { + "message": "Boarnekoade (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Meiwurkers", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Boarnekoade", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Oersettingen", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlisten", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Eksterne ôfhinklikheden (GPLv3-kompatibel):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO’s eigen filterlisten binne fergees beskikber op de folgjende CDN’s:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "As in filterlist bywurke wurde moat, wurdt samar in CDN brûkt", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Reservekopy nei bestân meitsje…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "myn-ublock-reservekopy_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Ut bestân werstelle…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Nei de standertynstellingen weromsette…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Al jo ynstellingen sille oerskreaun wurde mei de reservekopygegevens fan {{time}} en uBlock₀ sil werstart wurde.\n\nBinne jo wis dat jo alle besteande ynstellingen oerskriuwe wolle mei de reservekopygegevens?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "De gegevens koene net lêzen wurde of binne ûnjildich", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Al jo ynstellingen sille fuortsmiten wurde, wêrnei uBlock₀ werstart.\n\nYnstellingen dochs werstelle nei de standertwearden?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Netwurkflater: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: De folgjende URL oan jo oanpaste filterlisten tafoegje?\n\nTitel: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonnearje", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "in minút lyn", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuten lyn", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "in oere lyn", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} oeren lyn", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "in dei lyn", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dagen lyn", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Dashboerd toane", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Lochboek toane", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "útskeakele", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Side blokkearre", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin hat it laden fan de folgjende side opkeard:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Fanwege it folgjende filter", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sûnder parameters", + "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": "Fûn yn:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Tebekgean", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Dit finster slute", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "My net mear warskôgje oer dizze website", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Strikte blokkearring foar {{hostname}} útskeakelje", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Tydlik", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanint", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Trochgean", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksportearje nei cloudûnthâld", + "description": "tooltip" + }, + "cloudPull": { + "message": "Ymportearje fan cloudûnthâld", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Ut cloudopslach ymportearje en gearfoegje mei aktuele ynstellingen", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Apparaatnamme:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Warskôging! Wizigje dizze avansearre ynstellingen op eigen risiko.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Ferstjoere", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Wizigingen tapasse", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Tebeksette", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Elemint yn frame blokkearje...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonnearje op filterlist...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Grutte media-eleminten tydlik tastean", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Boarnekoade besjen…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Typ in fluchtoets", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Beskoattele skowe yn-/útskeakelje", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiearje nei klamboerd", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Alles selektearje", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kosmetyske filters yn-/útskeakelje", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Blokkearringsmodus beheine", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Brûkte ûnthâldromte {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klik om te laden", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Flaters: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Koe net goed filterje by starten fan browser.\nFernij de side foar in goede filtering.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/gl/messages.json b/src/_locales/gl/messages.json new file mode 100644 index 0000000..b97b2d5 --- /dev/null +++ b/src/_locales/gl/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Ó fin, un bloqueador eficiente que non chupa toda a memoria e o procesador.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Panel de control", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Aviso! ten cambios sen gardar", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Non saír", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorar", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Configuración", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtros de terceiros", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Os meus filtros", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "As miñas regras", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Lista branca", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Atallos", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Rexistro de peticións de rede", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Sobre", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Axuda", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visor de elementos", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Configuración avanzada", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Click: desactivar/activar o uBlock₀ neste sitio.\n\nCtrl+click: desactivar o Block₀ só nesta páxina.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Click: desactivar/activar o uBlock₀ neste sitio.\n\nCtrl+click: desactivar o Block₀ só nesta páxina.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click: activar o uBlock₀ neste sitio.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "peticións bloqueadas", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "nesta páxina", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ou {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "dende a instalación", + "description": "English: since install" + }, + "popupOr": { + "message": "ou", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloqueado nesta páxina", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloqueado desde a instalación", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Dominos conectados", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Fai click para abrir o panel de control", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Activar o modo \"eliminación de elementos\"", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Ir ó modo do selector de elementos", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Ir ó rexistro de peticións", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Informar dun problema nesta web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Activar todas as xanelas emerxentes nesta páxina", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click: bloquear todos os elementos emerxentes neste sitio", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click: deixar de bloquear todos os elementos emerxentes neste sitio", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Activar/desactivar o bloqueo de elementos multimedia grandes para este sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click: bloquear todos elementos multimedia de gran tamaño neste sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click: deixar de bloquear todos elementos multimedia de gran tamaño neste sitio", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Activar o filtrado cosmético nesta páxina", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click: desactivar filtrado cosmético neste sitio", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click: activar filtrado cosmético neste sitio", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Activar o bloqueo de fontes remotas para esta páxina", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click: bloquear fontes remotas neste sitio", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click: deixar de bloquear fontes remotas neste sitio", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Preme para desactivar JavaScript nesta web", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Preme para volver a activar JavaScript nesta web", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ventás emerxentes", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elementos multimedia grandes", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtrado cosmético", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Tipografías remotas", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Máis", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menos", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Reglas globais: esta columna é para as reglas que afectan a todos os sitios.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Fai click para gardar os cambios.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Fai click para desfacer os cambios.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "todo", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imaxes", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "de terceiros", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Imaxes/css de terceiros", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Scripts embebidos", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Scripts de dominio", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Scripts de terceiros", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Frames de terceiros", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "dominios conectados", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versión", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "marco", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Crear", + "description": "English: Create" + }, + "pickerPick": { + "message": "Escoller", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Saír", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Vista previa", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtros da rede", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtros cosméticos", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloquear elemento…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Agochar marcadores de posición dos elementos bloqueados", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Amosar o número de peticións bloqueadas no icono", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Desactivar axuda emerxente", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Empregar o menú contextual cando sexa posible", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Accesible para daltónicos", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aspecto", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Decorado", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Cor destacada personalizada", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Activar soporte para almacenamento na nube", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Son unha persoa experta", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Desactivar a precarga de sitios (prevén calquera conexión para peticións de red bloqueadas)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Desactivar a auditoría de hiperligazóns/señais (beacons)", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Impedir que o WebRTC revele os enderezos IP locais", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportamento predefinido", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Estes comportamentos predefinidos poden ser modificados para cada páxina en particular", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Desactivar o filtrado cosmético", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloquear elementos audiovisuais maiores de {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloquear fontes remotas", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Desactivar JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloquear reportes CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Descubrir nomes canónicos", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avanzadas", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Ferramentas orientadas a persoas con coñecemento técnico", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "configuración avanzada", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Última recuperación:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Última copia de seguridade:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtros de rede + {{cosmeticFilterCount}} filtros cosméticos:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "Empregados {{used}} de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Actualización automática das listas de filtros.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Actualizar agora", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Vaciar todas as cachés", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizar e aplicar filtros cosméticos.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Esta opción permitirache a análise e a aplicación de “filtros de ocultación de elementos” compatibles co Adblock Plus. \nEstes filtros sonche sobre todo cosméticos, serven para agochar elementos visualmente molestos nunha determinada páxina, non sendo posible a súa eliminación cun motor de bloqueo baseado en peticións.

Activar esta opción incrementará o uso de memoria do uBlock₀.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorar os filtros cosméticos xenéricos", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Os filtros cosméticos xenéricos estanche pensados para seren aplicados en todas as páxinas.

Aínda que o uBlock₀ os xestiona dun xeito eficiente, algúns deles precisan de altas cantidades de memoria e sobreemprego da CPU, especialmente nas páxinas grandes e nas máis duradeiras.

Activar esta opción suprimirá os requerimentos de memoria e CPU por causa destes filtros cosméticos xenéricos, así como reducirá a cantidade de memoria ocupada polo uBlock₀ mesmo.

Recomendámosche activar esta opción sobre todo nos dispositivos menos potentes.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspender actividade da rede ata que se carguen todas as listas de filtrado", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista dos servidores bloqueados", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar os cambios", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Local", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Anuncios", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacidade", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Dominios de malware", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Molestias", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipropósito", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Rexións, linguaxes", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizado", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importar...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Un enderezo por liña. Os enderezos inválidos seranche ignorados.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Desactualizada.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ver contido", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Última actualización: {{ago}}\nFai click para forzar a actualización.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Actualizando...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Un erro de rede está a impedir que se actualicen os recursos.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Un filtro por cada liña. O filtro pode ser un nome de servidor, ou un filtro compatible co Adblock Plus. As liñas que comecen con ! seranche ignoradas.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Non engadir filtros de fontes non confiables.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importar e engadir…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportar…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "o-meu-ublock-filtros-estaticos_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar cambios", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Regras permanentes", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Regras temporais", + "description": "header" + }, + "rulesRevert": { + "message": "Reverter", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Estabelecer", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Editar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Gardar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Descartar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importar dun arquivo...", + "description": "" + }, + "rulesExport": { + "message": "Exportar a un arquivo…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "o-meu-ublock-regras-dinamicas_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Listado coas túas regras de filtrado dinámico.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaxe das regras: orixe destino tipo acción (documentación completa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Orde:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipo de regra", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Orixe", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destino", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "As directivas de sitios de confianza indican as páxinas nas que uBlock Origin estará desactivado. Ten unha entrada por cada liña.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importar e anexar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "o-meu-ublock-lista-branca_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar os cambios", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Dominio", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Enderezo", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtro", + "description": "English: Filter" + }, + "logAll": { + "message": "Todas", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Peticións ocultas", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Lapela activa", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Recargar contido da pestana", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Activar inspector do DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Activar panel emerxente", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "wiki de uBlock Origin: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Baleirar rexistro", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausar rexistro (desbotar todos os datos de entrada)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Reactivar rexistro", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Activar filtrado do rexistro", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtras as entradas de rexistro", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opcións do filtrado do rexistro", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Non", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloqueado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permitido", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "da orixe", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "de terceiras partes", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalles", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtrar", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista de filtrado", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regra", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contexto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contexto Root", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Orixe do elemento", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Filtrado dinámico do enderezo", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contexto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtrado estático", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} peticións de rede tipo {{type}} {{br}} nas cales o enderezo contenga {{url}} {{br}}e que teñan como orixe {{origin}},{{br}}{{importance}} haxa un filtro de excepción aplicable.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloquear", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permitir", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "calquera tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "dende “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "dende calquera sitio", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "agás cando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "aínda cando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtro estático {{filter}}atopado en:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Non atopamos filtro estático {{filter}} en ningunha das listas de filtros activas", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "As entradas no rexistro que non cumpran coas tres condicións inferiores desbotaranse automáticamente:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Manter entradas dos últimos {{input}} minutos", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Manter como máximo {{input}} cargas da páxina por pestana", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Manter como máximo {{input}} entradas por pestana", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Usar {{input}} liñas por entrada en modo vertical despregado", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Agochar columnas:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Hora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtro/regra", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contexto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Orixe", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Táboa", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plano", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Abrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Crear nova denuncia", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Atopar denuncias parecidas", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentación", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Le a documentación en uBlock/wiki para saber máis acerca das ferramentas de uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Preguntas e axuda", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "No subreddit /r/uBlockOrigin hai respostas a preguntas e outro tipo de axuda", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemas co filtrado/Esta web non funciona", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Informar de problemas co filtrado en sitios web específicos no uBlockOrigin/uAssets issue tracker.Require unha conta en GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Importante: Evitar usar ao mesmo tempo outros bloqueadores semellantes a uBlock Origin, xa que podería causar problemas co filtrado nalgunhas webs en concreto.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Truco: Mira que as listas de filtrado estean actualizadas.The logger é a ferramenta principal para diagnosticar problemas relacionados co filtrado.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Informar de problemas", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Informar de problemas co filtrado en sitios web específicos no uBlockOrigin/uAssets issue tracker.Require unha conta en GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Información para arranxar problemas", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "A información técnica seguinte podería ser útil para que as persoas que intentan axudar poidan resolver o problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Importante: A potencial información privada ou sensible está editada por defecto. Ao editar a información poderías dificultar a resolución do problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Informar dun problema co filtrado", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Para evitar a sobrecarga de traballo para as persoas voluntarias con duplicados dos problemas, comproba que aínda non se informou acerca do problema.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "As listas de filtrado actualizanse a diario. Comproba que non fose solucionado coa lista de filtrado máis recente.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Comproba que o problema persiste despois de recargar a web problemática.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Enderezo da páxina web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "A páxina web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Escolle unha opción --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Mostra publicidade ou restos dela", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ten capas sobreimpostas ou elementos molestos", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detecta uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ten problemas relacionados coa privacidade", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Funciona mal cando teño uBlock Origin activado", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Abre ventás ou páxinas non desexadas", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Etiqueta a páxina como \"NSFW\" (\"Non é Segura No Traballo\")", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Política de privacidade", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Rexistro de cambios", + "description": "" + }, + "aboutCode": { + "message": "Código fonte (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Colaboradores", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Código fonte", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traducións", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listas de filtrado", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependencias externas (GPLv3-compatible)", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "As listas de filtrado de uBO están aloxadas gratuitamente nos seguintes servidores CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Escóllese un CDN ao chou cando se precisa actualizar a lista.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Facer copia de seguridade nun arquivo", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-copia-seguridade_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Recuperar desde arquivo...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Restabelecer os axustes por defecto...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Todas as túas preferencias serán rescritas, usando os datos rexistrados no {{time}}, e o uBlock₀ reiniciará. Queres sobrescribir toda a configuración existente empregando os datos da copia de seguridade?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Os datos son inválidos ou non poden ser lidos", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Eliminaranse todas as túas preferencias, e reiniciará o uBlock₀. Queres resetear o uBlock₀ á configuración por defecto?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Erro da rede: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Engadir o seguinte enderezo á túa lista de filtros personalizados?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribir", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "fai un minuto", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "fai {{value}} minutos", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "fai unha hora", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "fai {{value}} horas", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "fai un día", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "fai {{value}} días", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Amosar no Panel de control", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Amosar o rexistro de peticións da rede", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "desactivado", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Páxina bloqueada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "O uBlock₀ impediu cargar a seguinte páxina:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Por mor deste filtro:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sen parámetros", + "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": "Atopado en:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Retroceder", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Pechar esta xanela", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Non avisarme máis sobre esta web", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Desactivar o bloqueo estricto en {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporalmente", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentemente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceder", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportar ó almacenamento na nube", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importar dende o almacenamento na nube", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importar dende a nube e combinar coas preferencias actuais", + "description": "tooltip" + }, + "cloudNoData": { + "message": "... ...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "O nome deste dispositivo:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Ollo! Non cambies estas configuracións avanzadas senón sabes ben o que estás a facer.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Enviar", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplicar os cambios", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Reverter", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloquear elemento no marco...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribirse á lista de filtrado...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permitir temporalmente os elementos multimedia grandes", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Ver código fonte...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Introduce un atallo", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Cambiar estado desprazamento", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiar ao portapapeis", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Seleccionar todo", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Activar filtrado cosmético", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaxar o modo de bloqueo", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Almacenaxe usada: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Preme para cargar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erros: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Non se filtrou correctamente ao inicio do navegador. Recarga a páxina para asegurar un filtrado correcto.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Esta ten que ser a derradeira entrada", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/gu/messages.json b/src/_locales/gu/messages.json new file mode 100644 index 0000000..3e3b5db --- /dev/null +++ b/src/_locales/gu/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "અંતે, એક કાર્યક્ષમ અવરોધક. સીપીયુ અને મેમરી પર સરળ.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "ચેતવણી! તમારા ફેરફારો સચવાયેલા નથી ", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "રહો\n", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "અવગણો", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "સેટિંગ્સ", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "ફિલ્ટર યાદીઓ", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "મારા ફિલ્ટર ", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "મારા નિયમો", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trusted sites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "About", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Advanced settings", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requests blocked", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "or", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Open the dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "all", + "description": "" + }, + "popupImageRulePrompt": { + "message": "images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Create", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pick", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quit", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Update now", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Ads", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "All", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "a minute ago", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutes ago", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "an hour ago", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a day ago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} days ago", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Go back", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporarily", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanently", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "This device name:", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json new file mode 100644 index 0000000..3bc7bd2 --- /dev/null +++ b/src/_locales/he/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "סוף סוף, חוסם יעיל. קל על המעבד והזיכרון.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — לוח מחוונים", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "אזהרה! יש לך שינויים שלא שמרת עדיין", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "הישאר", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "התעלם", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "הגדרות", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "רשימות מסננים", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "המסננים שלי", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "החוקים שלי", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "אתרים מהימנים", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "קיצורי דרך", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — מתעד הבקשות", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "אודות", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "תמיכה", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — מציג הנכסים", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "הגדרות מתקדמות", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ רק בדף זה.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "לחץ על מנת להפעיל את uBlock₀ באתר זה.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "בקשות שנחסמו", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "בדף זה", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "מאז ההתקנה", + "description": "English: since install" + }, + "popupOr": { + "message": "או", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "חסומים בדף זה", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "נחסמו מאז ההתקנה", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "דומיינים שהתחברת אליהם", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "פתח את לוח המחוונים", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "היכנס למצב מחיקת אלמנט באופן זמני", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "היכנס למצב בחירת אלמנט", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "פתח את מתעד הבקשות", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "דווח על בעיה באתר אינטרנט זה", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "הפעל/כבה את החסימה של חלונות קופצים באתר זה", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "לחץ על מנת לחסום חלונות קופצים באתר זה", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "לחץ על מנת לבטל את החסימה של חלונות קופצים באתר זה", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "הפעל/כבה את החסימה של אלמנטי מדיה גדולים באתר זה", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "לחץ על מנת לחסום אלמנטי מדיה גדולים באתר זה", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "לחץ על מנת לבטל את החסימה של אלמנטי מדיה גדולים באתר זה", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "הפעל/כבה מסננים קוסמטיים באתר זה", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "לחץ על מנת לכבות מסננים קוסמטיים באתר זה", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "לחץ על מנת להפעיל מסננים קוסמטיים באתר זה", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "הפעל/כבה את החסימה של פונטים חיצוניים באתר זה", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "לחץ על מנת לחסום פונטים חיצוניים באתר זה", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "לחץ על מנת לבטל את החסימה של פונטים חיצוניים באתר זה", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "לחץ על מנת לחסום JavaScript באתר זה", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "לחץ על מנת להפסיק לחסום JavaScript באתר זה", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "חלונות קופצים", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "אלמנטי מדיה גדולים", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "מסננים קוסמטיים", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "פונטים חיצוניים", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "עוד", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "פחות", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "חוקים גלובליים: עמודה זו היא עבור חוקים אשר תקפים לכל האתרים.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "חוקים לוקאליים: עמודה זו היא עבור חוקים אשר תקפים לאתר הנוכחי בלבד.\nחוקים לוקאליים דורסים את החוקים הגלובליים.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "לחץ על מנת להפוך את השינויים שלך לקבועים.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "לחץ על מנת לבטל את השינויים שלך.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "הכל", + "description": "" + }, + "popupImageRulePrompt": { + "message": "תמונות", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "צד-3", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/תמונות צד-3", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "סקריפטים מוטמעים", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "סקריפטים צד-1", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "סקריפטים צד-3", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "מסגרות צד-3", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "דומיינים שהתחברת אליהם", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} מתוך {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "גרסה", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "סקריפט", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "מסגרת", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "צור", + "description": "English: Create" + }, + "pickerPick": { + "message": "בחר", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "צא", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "תצוגה מקדימה", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "מסנני רשת", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "מסננים קוסמטיים", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "לחיצה, Ctrl+לחיצה", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "חסום אלמנט…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "הסתר את המקום שנשאר מחסימה של אלמנטים", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "הראה את מספר הבקשות החסומות על האייקון", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "כבה רמזים צצים", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "הצגת הפריט 'חסום אלמנט' בתפריט הלחצן הימני איפה שאפשר", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "ידידותי לעיוורי צבעים", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "נראות", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "ערכת נושא", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "צבע הדגשה מותאם אישית", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "הפעל אחסון בענן", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "אני משתמש מתקדם", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "כבה אחזור מוקדם של משאבים (על מנת למנוע מחיבורים של בקשות רשת חסומות להישלח)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "חסום Hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "מנע מ WebRTC להדליף כתובות IP לוקאליות", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "התנהגות ברירת מחדל", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "התנהגויות ברירת מחדל אלו יכולות להיקבע עבור כל אתר בנפרד", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "כבה מסננים קוסמטיים", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "חסום אלמנטי מדיה הגדולים מ {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "חסום פונטים חיצוניים", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "חסום JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "חסום דיווחי CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "חשוף רשומות DNS מסוג CNAME", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "מתקדם", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "מאפיינים למשתמשים בעלי ידע טכני בלבד", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "הגדרות מתקדמות", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "שחזור אחרון:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "גיבוי אחרון:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} מסנני רשת + {{cosmeticFilterCount}} מסננים קוסמטיים מתוך:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} בשימוש מתוך {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "עדכן אוטומטית את רשימות המסננים.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "עדכן כעת", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "נקה את כל זיכרוני המטמון", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "פרסר ואפשר מסננים קוסמטיים.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "מסננים קוסמטיים נועדו להסתיר אלמנטים בדף אינטרנט אשר נחשבים למטרד חזותי, ואשר לא יכולים להיחסם על ידי מנוע חסימת בקשות רשת.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "התעלם ממסננים קוסמטיים כלליים", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "מסננים קוסמטיים כלליים - אלה הם המסננים הקוסמטיים, אשר מיועדים להיות מוחלים על כל דפי האינטרנט. אפשור הגדרה זו תוריד את צריכת הזיכרון והמעבד אשר מתווספות לדפי אינטרנט כתוצאה משימוש במסננים קוסמטיים כלליים.\n\nמומלץ לאפשר הגדרה זו במכשירים פחות חזקים.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "השהה פעילות רשת עד לסיום טעינת כל רשימות הסינון", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "רשימה של דומיינים חסומים", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "החל שינויים", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "מובנה", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "פרסומות", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "פרטיות", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "ביטחון והגנה מפני נוזקה", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "מטרדים", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "רב תכליתי", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "אזורים, שפות", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "מותאם אישית", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "ייבא…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "כתובת אינטרנט אחת בכל שורה. כתובות אינטרנט שאינן חוקיות לא יפורשו.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "לא עדכני.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "הצג תוכן", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "עדכון אחרון: {{ago}}.\nלחץ על מנת לאלץ עידכון.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "מעדכן…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "בעיית רשת מנעה מהמשאב להתעדכן.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "מסנן אחד לכל שורה. המסנן יכול להיות דומיין פשוט, או מסנן התואם ל- EasyList. שורות עם קידומת ! לא יפורשו.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "ייבא וצרף", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "ייצוא", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "החל שינויים", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "חוקים קבועים", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "חוקים זמניים", + "description": "header" + }, + "rulesRevert": { + "message": "החזר למצב הקודם", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "החל", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "ערוך", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "שמור", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "בטל", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ייבא מקובץ…", + "description": "" + }, + "rulesExport": { + "message": "ייצא לקובץ...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "רשימת חוקי המסננים הדינאמיים שלך.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "סינטקס חוק: פעולה סוג יעד מקור (תיעוד מלא).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "מיין לפי:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "סוג הרשומה", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "מקור", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "יעד", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "הנחיות אתר מהימנות, מכתיבות באילו עמודי מרשתת יש להשבית את uBlock Origin. רשומה אחת לכול שורה.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "ייבא וצרף", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "ייצוא", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "החל שינויים", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "סוג", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "דומיין", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "כתובת", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "מסנן", + "description": "English: Filter" + }, + "logAll": { + "message": "כל הטאבים", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "מאחורי הקלעים", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "לשונית נוכחית", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "טען מחדש את תוכן הלשונית", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "פתח/סגור את ה DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "הצג/הסתר את הפאנל הקופץ", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin וויקי: מתעד הבקשות", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "נקה בקשות", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "עצור תיעוד של בקשות (התעלם מכל בקשה חדשה)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "המשך תיעוד של בקשות", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "הפעל/כבה סינון של מתעד הבקשות", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "סנן רשומות של מתעד הבקשות", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "הגדרות סינון של מתעד הבקשות", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "לא", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "חסום", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "מאופשר", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "השתנה", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "צד-1", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "צד-3", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "פרטים", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "מסנן", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "רשימת מסננים", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "חוק", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "הקשר", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "ההקשר המקורי", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "צד", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "סוג", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "כתובת", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "סינון URL דינאמי", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "הקשר:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "סוג:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "סינון סטאטי", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} בקשות רשת מסוג {{type}} {{br}} שה URL שלהן הוא {{url}} {{br}} ואשר מגיע מהאתר {{origin}},{{br}}{{importance}} קיים כבר מסנן שמתיר להעביר בקשות רשת אלה.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "חסום", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "אפשר", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "מסוג \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "כל סוג", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "מתוך \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "מכל מקום", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "אך לא כאשר", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "גם אם", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "המסנן הסטאטי {{filter}} נמצא ב:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "המסנן הסטאטי לא נמצא בשום אחת מרשימות המסננים המופעלות כרגע", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "רשומות של מתעד הבקשות שלא תואמות את כל שלושת התנאים הבאים לא ישמרו:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "שמור היסטוריית רשומות של {{input}} הדקות האחרונות", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "שמור היסטוריה של עד {{input}} טעינות עמוד עבור כל לשונית", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "שמור היסטוריה עד {{input}} רשומות עבור כל לשונית", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "השתמש ב {{input}} שורות עבור כל רשומה במצב פרוס אנכית", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "הסתר עמודות:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} זמן", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} מסנן/חוק", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} הקשר", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} צד", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "רשימה", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "טבלה", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "פשוט", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "פורמט Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "לפתוח", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "צור דוח חדש", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "מצא דוחות דומים", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "דוקומנטציה", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "קרא את הדוקומנטציה ב uBlock/wik על מנת ללמוד על כל היכולות של uBlock Origin", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "שאלות ותמיכה", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "תשובות לשאלות ושאר סוגי העזרה ניתן להיעזר בסאברדיט /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "בעיות סינון/אתר שבור", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "דווח על בעיות סינון באתרים קונקרטיים בלוח הבעיות uBlockOrigin/uAssets. נדרש משתמש GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "חשוב: המנע משימוש בחוסמים אחרים שיש להם את אותה המטרה באותו הזמן עם uBlock Origin, שכן זה יכול לגרום לבעיות סינון באתרים ספציפיים.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "טיפים: וודאו כי רשימות המסננים שלכם מעודכנים. מתעד הבקשות הינו הכלי המרכזי לפענוח בעיות הקשורות לרשימות מסננים.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "דיווח על באג", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "דווח על בעיות ב uBlock Origin עצמו ל מעקב הסוגייות uBlockOrigin/uBlock-issue.\nנידרש חשבון גיטהאב (GitHub)", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "מידע לפתרון בעיות", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "ראה מטה מידע טכני שיכול להיות מועיל למתנדב, כאשר הוא מנסה לעזור לך לפתור בעיה.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "חשוב: מידע שהוא פוטנציאלי רגיש או פרטי מוסר בברירת מחדל. המידע שמוסר יכול לגרום לעיכוב בפתרון בעיות.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "דיווח על בעיית מסנן", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "כדי להימנע מהכבדה על מתנדבים בדווחים כפולים, נא לודא שבעיה דומה טרם דווחה.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "רשימות הסינון מתעדכנות מדי יום. וודא שהבעיה שלך עדיין לא טופלה ברשימות הסינון המעודכנות.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "וודא כי הבעיה עדיין קיימת לאחר רענון הדף הבעייתי.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "כתובת דף האינטרנט:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "דף האינטרנט…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- בחר קטגוריה --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "הצגת פרסומות או שאריות שלהן", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "קיים ריבוד או מטרד אחר", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "מזהה את uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "בעיות הקשורות לפרטיות", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "כשל תפעולי כאשר uBlock Origin פעיל", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "נפתחים לשוניות או חלונות לא רצויים", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "תיוג דף האינטרנט כ- לב\"ל ('לא בטוח לעבודה')", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "הסר מידע פרטי או רגיש", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "שחזר מידע פרטי או רגיש", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "מדיניות פרטיות", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "רשימת שינויים", + "description": "" + }, + "aboutCode": { + "message": "קוד מקור (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "תורמים", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "קוד מקור", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "תרגומים", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "רשימות מסננים", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "תלויות חיצוניות (תואם-GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "רשימות המסננים של uBO מופצות בחינם בשירותי ה CDN הבאים:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "שרות CDN אקראי נבחר לשם עדכון רשימת מסננים", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "גבה לקובץ…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "שחזר מקובץ…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "אפס להגדרות ברירת מחדל…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "כל ההגדרות שלך יוחלפו בנתונים שגובו ב {{time}}, ו uBlock₀ יופעל מחדש.\n\nהאם להחליף את כל ההגדרות הקיימות בנתונים המגובים?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "לא הוצלח לקרוא את המידע או שהוא פגום", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "כל ההגדרות שלך יימחקו, ו uBlock₀ יופעל מחדש.\n\nלאפס את uBlock₀ להגדרות ברירת מחדל?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "בעיית רשת: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "הוסף את הכתובת הבאה לרשימת הפילטרים המותאמים אישית שלך?\n\nכותרת: \"{{title}}\"\nכתובת URL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "הירשם כמנוי", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "לפני דקה", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "לפני {{value}} דקות", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "לפני שעה", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "לפני {{value}} שעות", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "לפני יום", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "לפני {{value}} ימים", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "הצג את לוח המחוונים", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "הצג את מתעד הבקשות", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "מכובה", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "הדף חסום", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin מנע מהעמוד הבא להיטען:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "בגלל המסנן הבא", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "נמצא ב:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "חזור אחורה", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "סגור חלון זה", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "אל תתריע לי שוב על אתר זה", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "בטל חסימה נוקשה עבור {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "זמנית", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "לצמיתות", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "המשך", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "ייצא לאחסון ענן", + "description": "tooltip" + }, + "cloudPull": { + "message": "ייבא מאחסון ענן", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "ייבא מהגיבוי בענן ומזג עם ההגדרות הקיימות", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "שם המכשיר:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "אזהרה! שינוי הגדרות אלו על אחריותך בלבד.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "שלח", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "החל שינויים", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "החזר למצב הקודם", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "בתים", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "חסום אלמנט בתוך מסגרת…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "הירשם לרשימת המסננים…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "זמנית אפשר אלמנטי מדיה גדולים", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "צפה בקוד המקור…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "הקלד קיצור דרך", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "הפעל/כבה נעילת גלילה", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "העתק ללוח", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "בחר הכל", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "הפעל/כבה מסננים קוסמטיים", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "הרפה את מצב החסימה הנוכחי", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "אחסון בשימוש: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "לחץ על מנת לטעון", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "שגיאות: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "לא ניתן היה לסנן כראוי בעת הפעלת הדפדפן. טען מחדש את הדף כדי להבטיח סינון מתאים.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "ערך זה חייב להיות האחרון", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json new file mode 100644 index 0000000..0671acb --- /dev/null +++ b/src/_locales/hi/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "आख़िरकार, क्रोमियम-बेस्ड ब्राउज़रों के लिए एक कुशल अवरोधक। CPU और स्मृति पर आसान।", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — डैशबोर्ड", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "चेतावनी! आपके कुछ परिवर्तनों को सहेजना अभी बाकी है", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "रुकें", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "नज़रअंदाज़ करें ", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "सेटिंग्स", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "तृतीय-पक्ष फ़िल्टर", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "मेरे फिल्टर", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "मेरे नियम", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "विश्वस्त साइट सूची", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "शॉर्टकट", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — लॉगर", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "जानकारी", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "सहायता", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — असेट व्यूअर", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "उन्नत सेटिंग्स", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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 को केवल इस पेज पर बंद करने के लिए।", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "इस साईट में uBlock₀ को चालू करने के लिए क्लिक कीजिये।", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "रुके हुए अनुरोध", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "इस पृष्ठ पर", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} या {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "स्थापना से अब तक", + "description": "English: since install" + }, + "popupOr": { + "message": "या", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "इस पेज पर ब्लॉक किया गया ", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "स्थापना के समय से ब्लॉक किया हुआ", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "कनेक्ट हुई डोमेंस", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "डैशबोर्ड खोलें", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "चीजें मिटाने के मोड में जाएं", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "एलिमेंट पिकर मोड में जाएं ", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "लॉगर खोलें", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "इस वेबसाइट पर किसी समस्या की रिपोर्ट करें", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "इस साईट के लिए कोई पॉपअप नहीं", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "इस वेबसाइट पर सभी पॉप-अप्स को ब्लाक करने के लिए क्लिक करें", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "इस वेबसाइट पर सभी पॉप-अप्स को और ब्लाक न करने के लिए क्लिक करें", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "बड़े मीडिया चीजों को रोक दें", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "इस वेबसाइट पर बड़े मीडिया ऐलिमेंटस को ब्लाक करने के लिए क्लिक करें", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "इस वेबसाइट पर बड़े मीडिया ऐलिमेंटस को ब्लाक न करने के लिए क्लिक करें", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "इस वेबसाइट की खूबसूरत फ़िल्टरिंग करें", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "इस साइट पर कॉस्मेटिक फ़िल्टरिंग बंद करने के लिए क्लिक करें", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "इस साइट पर कॉस्मेटिक फ़िल्टरिंग चालू करने के लिए क्लिक करें", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "बाहरी फ़ॉन्ट्स को ब्लॉक करें", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "इस साइट पर रिमोट फोंट को बंद करने के लिए क्लिक करें", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "इस साइट पर रिमोट फोंट अब और नहीं ब्लॉक करने के क्लिक करें ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "जावास्क्रिप्ट को रोकने के के लिए दबाएं", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "जावास्क्रिप्ट को अब और न बंद करने के लिए दबाएं", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "पॉप-अप विंडोज", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "बड़े मीडिया एलिमेंट्स ", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "कॉस्मेटिक फिल्टर", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "रिमोट फोंट्स\n", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "जावास्क्रिप्ट ", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "और", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "कम", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "सार्वत्रिक नियम: इस क़तार के नियम सारे साइट्स पर लागु करने के लिए हैं ", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "निन्मलिखित नियमें सिर्फ इस वेबसाइट पर लागू है", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "अपने परिवर्तनों को पक्का बनाने के लिए क्लिक करें।", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "आपके परिवर्तनों को उलटने के लिए क्लिक करें", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "सभी", + "description": "" + }, + "popupImageRulePrompt": { + "message": "चित्र", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "तृतीय-पक्ष", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "३री-पार्टी CSS/तस्वीरें ", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "लाइन के बीच वाले स्क्रिप्ट्स", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "असली साइट के स्क्रिप्ट्स", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "दूसरी साइट के स्क्रिप्ट्स", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "दूसरी साइट के फ्रेम्स", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "कनेक्ट हुई साइटें ", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} मे से {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "वर्जन", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "स्क्रिप्ट", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "फ़्रेम", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "बनाएँ", + "description": "English: Create" + }, + "pickerPick": { + "message": "चयन", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "बंद करें", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "पूर्व दर्शन", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "नेट फिलटर्स", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "कॉस्मेटिक फिल्टर", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "क्लिक, कंट्रोल - क्लिक", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "इस को ब्लॉक करो", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ब्लॉक किये चीज़ो की प्लेसहोल्डर को हटाओ", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "ब्लॉक कि गयी चीज़ो की गिनती आइकॉन पर दिखाओ", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "टूलटिप्स बंद कीजिऐ", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "जहाँ उपयुक्त हो, संदर्भ मेनू का इस्तेमाल करें", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "वरणांध अनुकूलित ", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "दिखावट", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "थीम", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "निर्मित किए हुए उच्चारण रंग", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "क्लाउड स्टोरेज सपोर्ट चालू करें", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "मैं एक उच्च उपयोगकर्ता हूँ (आवश्यक पठन)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "प्री-फ़ेचिंग बंद करें (कोई भी ब्लॉक किये गए कनेक्शंनो से संपर्क न करने लिए)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "हाइपरलिंक जाँच को बंद करें", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC को स्थानीय IP पतों लीक करने से रोकें ", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "सामान्य व्यवहार", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "ये सामान्य व्यवहारों को प्रति-पृष्ठ आधार पर बदला जा सकता है", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "कॉस्मेटिक फ़िल्टरिंग बंद करें ", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input}} KB से बड़े मीडिया चीजें को बंद करें ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "बाहरी फोंट्स को बंद करें ", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "जावास्क्रिप्ट को बंद करें ", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": " CSP रिपोर्ट्स को ब्लॉक करें ", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "विहित नाम अनलॉक करें", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "उन्नत", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "केवल तकनीकी उपयोगकर्ताओं के लिए उपयुक्त सुविधाएँ.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "उन्नत सेटिंग्स", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": " पिछला रिस्टोर:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "पिछला बैकअप", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} नेटवर्क फिल्टर्स + {{cosmeticFilterCount}} कॉस्मेटिक फिल्टर्स यहां से:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} में से {{used}} का इस्तेमाल किया", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "स्व-अद्यतन फ़िल्टर सूचियां", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "अभी नवीकृत करें", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "सभी अस्थायी मेमोरी को शुद्ध करे", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "कॉस्मेटिक फिल्टर्स को लें और लागू करें", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "यह विकल्प कॉस्मेटिक फिल्टर्स को लेता और उन्हें जारी करता है जो Adblock Plus- \"एलीमेंट हाइड\" से मिलतें-जुलातें हैं। यह उन चीजों को ब्लॉक करतें हैं जो वेब पेज के दिखावत में छोटे- मोटी समस्या पैदा करतें है जो नेटवर्क रिक्वेस्ट-के फिल्टरों से ब्लुक नहीं किए जा सकते। ", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "जेनेरिक कम्सेटिक फिल्टरों को नजरंदाज करें", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "जेनेरिक कॉस्मेटिक फिल्टरस वो कॉस्मेटिक फिल्टरस हैं जो सब वेब साइट्स पर लागू होते हैं। यह विकल्प को चालू कराने से मेमोरी और सीपीयू पर जो उपर का दबाव पड़ता है वो नहीं रहेगा जो कॉस्मेटिक फिल्टरों को जारी करने से हुआ था।\n\nइस विकल्प को कमज़ोर डिवाइसों पर चालू कराने की सलाह दी जाती है।", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "सभी फ़िल्टर सूचियाँ लोड होने तक नेटवर्क गति-विधि को निलंबित करें", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "परिवर्तन लागू करें", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "बिल्ट-इन ", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "विज्ञापन", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "गोपनीयता", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "मैलवेयर डोमेन", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "सतानेवाले विज्ञापन", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "बहुउद्देशीय", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "क्षेत्र, भाषा", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "कस्टम", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "इम्पोर्ट ", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "एक URL हर लाइन में. अमान्य URLs को सीधे से नजरअंदाज किया जायेगा।", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "पुरानी", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "चीजों को देखें ", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "अन्तिम अद्यातन: {{ago}}. कृत्रिम नवीकरण के लिए क्लिक की जिए", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "नवीकरण प्रगति में हैं...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "एक नेटवर्क त्रुटि ने रिसोर्स को अपडेट होने से रोक दिया। ", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "एक लाइन में एक फ़िल्टर। एक फ़िल्टर सीधा होस्टनाम, या एक Adblock Plus- योग्य फ़िल्टर हो सकता है। !से शुरू होने वाली लाइनों को नज़रअंदाज किया जायेगा।", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "अविश्वसनीय स्रोतों से फ़िल्टर न जोड़ें.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "इम्पोर्ट करें और जोड़ें", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "निर्यात करें", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "मेरे-ublock-स्‍थिर-फिल्टेरें_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "परिवर्तन लागू करें", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "स्थायी नियम", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "अस्थायी नियम", + "description": "header" + }, + "rulesRevert": { + "message": "पलटदे", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "पक्का करो", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "एडिट", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "सहेजें", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "रद्द करें", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "फाइल से आयात करे...", + "description": "" + }, + "rulesExport": { + "message": "फाइल में एक्सपोर्ट करें ", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "मेरे-ublock-डायनामिक-नियम_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "मेरे डायनामिक रूल्स की लिस्ट।", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "सिंटेक्स नियम: सोर्स डेस्टिनेशन टाइप एक्शन ( पूरी डॉक्यूमेंटेशन).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "क्रम में लगाये", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "नियम प्रकार", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "स्रोत", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "गंतव्य", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "वाइटलिस्ट के नियम यह बताते हैं कि uBlock Origin को किस वेब पेज पर बंद करना चाहिए। एक एंट्री हर लाइन में। अमान्य नियमों को सीधे-सीधे नजरअंदाज कर दिया जाएगा।", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "इम्पोर्ट करें और जोड़ें", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "निर्यात करें", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "मेरे-उबलॉक-व्हाइटलिस्ट_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "परिवर्तन लागू करें", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "प्रकार", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "डोमेन", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "यू आर एल", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "फिल्टर", + "description": "English: Filter" + }, + "logAll": { + "message": "सब", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "पर्दे के पीछे", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "वर्तमान टैब", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "टैब की चीज़ों को फिर से लोड करें ", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM इंस्पेक्टर को टॉगल करें ", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "पॉप-उप पैनल को टॉगल करें ", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin विकी: लॉग्गर ", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "लॉगर क्लियर करें ", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "लॉग्गर क्लियर करें", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "लोगेर को फिर से चालू करें ", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "लोगर फ़िल्टर को टॉगल करें ", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "लोगर चीज़ों को फिल्टीर करें ", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "लोगर फ़िल्टर के चुनाव ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "नही", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "ब्लॉक किया हुआ ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "स्वीकार किया हुआ ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "परिवर्तित", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "१ली-पार्टी ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "तृतीय-पक्ष", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "विवरण", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "फ़िल्टर ", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "फिल्टीर सूची", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "नियम", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "संदर्भ", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "मूल सन्दर्भ ", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "पर्टिनेस", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "प्रकार", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL नियम ", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "सन्दर्भ:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "प्रकार:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "स्थिर फ़िल्टर", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{type}}{{br}} कि नेटवर्क रिक्वेस्ट्स {{action}} जो मिलती है इस URL पते से {{url}}{{br}} और जो आती है यहां से {{origin}},{{br}}{{importance}} मैचिंग एक्सेप्शन फिल्टर मौजूद है।", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "ब्लॉक", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "अनुमति दें", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "प्रकार \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "कोई भी प्रकार का", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\" से", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "कहि से भी", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "सिवाय जब ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "फिर भी ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "{{filter}} में पाया गया स्थिर फ़िल्टर", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "फिलहाल चालू की गई हुई कोई भी फिल्टर्स सूची में स्थिर फिल्टर नहीं मिल पाया", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "नीचे दी गई तीनों सूचियों से जो नहीं मिलते उनको ऑटोमेटिकली निकाल दिया जाएगा:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "आखरी {{input}} मिनट की जो एंट्रेंस हैं उन्हें बचा कर रखें", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "ज्यादा-से-ज्यादा इतनी पेज लोड्स को बचा कर रखें {{input}}", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "ज्यादा से ज्यादा {{input}} एंट्रीज को रखें", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "{{input}} लाइनों को इस्तेमाल करें पर एंट्री में जो खड़ी स्थिति में हैं", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "कॉलम्स को छिपाएं:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} समय", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} फिल्टर/रूल", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} संदर्भ", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "पर्टीनेस", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "सूची", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "टेबल", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "प्लेन", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "मार्कडाउन", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "खोलें", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "नई रिपोर्ट बनाएं", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "ऐसी ही रिपोर्ट खोजें", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "प्रलेखन", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock की सभी विशेषताओं के बारे में जानने के लिए uBlock/wiki पर दस्तावेज़ पढ़ें।", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "प्रश्न और समर्थन", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "सबरेडिट /r/uBlockOrigin. पर सवालों के जवाब और अन्य प्रकार की सहायता सहायता प्रदान की जाती है", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "फ़िल्टर समस्याएं/वेबसाइट टूट गई है", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "विशिष्ट वेबसाइटों के साथ फ़िल्टर समस्याओं की रिपोर्टuBlockOrigin/uAssets इश्यू ट्रैकर. GitHub खाते की आवश्यकता है। ", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "ध्यान दें :uBlock Origin के साथ समान उद्देश्य वाले अन्य अवरोधकों का उपयोग करने से बचें, क्योंकि इससे विशिष्ट वेबसाइटों पर फ़िल्टर समस्याएँ हो सकती हैं।", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "युक्तियाँ : सुनिश्चित करें कि आपकी फ़िल्टर सूचियाँ नवीनतम हैं। लॉगर आपकी फ़िल्टर से संबंधित समस्याओं के निदान के लिए प्राथमिक टूल है।", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "बग रिपोर्ट", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlock Origin के साथ समस्याओं की रिपोर्ट यहाँ uBlockOrigin/uBlock-issueइश्यू ट्रैकर पर करें। इसके लिए GitHub खाते की आवश्यकता है।", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "समस्या निवारक जानकारी", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "नीचे तकनीकी जानकारी दी गई है जो तब उपयोगी हो सकती है जब स्वयंसेवक किसी समस्या का समाधान करने में आपकी सहायता करने का प्रयास कर रहे हों।", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": " महत्वपूर्ण: संभावित रूप से निजी या संवेदनशील जानकारी को डिफ़ॉल्ट रूप से संशोधित किया जाता है। संशोधित जानकारी किसी समस्या को हल करना अधिक कठिन बना सकती है।", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "फ़िल्टर समस्या की रिपोर्ट करें", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "स्वयंसेवकों पर डुप्लीकेट रिपोर्ट का बोझ डालने से बचने के लिए, कृपया सत्यापित करें कि समस्या की रिपोर्ट पहले ही नहीं की गई है।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "फ़िल्टर सूचियों को रोजाना अपडेट किया जाता है। सुनिश्चित करें कि आपकी समस्या का समाधान पहले से ही नवीनतम फ़िल्टर सूचियों में नहीं किया गया है।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "सत्यापित करें कि समस्यात्मक वेबपेज को रीलोड करने के बाद समस्या अभी भी बनी हुई है।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "वेब पेज का पता:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "वेब पेज...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- एक प्रविष्टि चुनें --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "विज्ञापन या बचा हुआ विज्ञापन दिखाता है", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "ओवरले या अन्य उपद्रव हैं", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin का पता लगाता है", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "गोपनीयता से संबंधित समस्याएं हैं", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin सक्षम होने पर खराबी", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "अवांछित टैब या विंडो खोलता है", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "वेब पेज को इस रूप में लेबल करें “NSFW” (“काम करने के लिए सुरक्षित नहीं”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "संपादन", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "असंशोधित", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "गोपनीयता नीति", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "परिवर्तन सूची", + "description": "" + }, + "aboutCode": { + "message": "सोर्स कोड {GPLv3}", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "योगदानकर्ता", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "सोर्स कोड", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "अनुवाद", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "फिल्टर सूची", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "बाहरी डिपेंडेंसीज (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's स्वयं की फ़िल्टर सूचियाँ निम्नलिखित पर स्वतंत्र रूप से होस्ट की जाती हैं CDNs ", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "बेतरतीब ढंग से चुनी गई सीडीएन का उपयोग तब किया जाता है जब फ़िल्टर सूची को अद्यतन करने की आवश्यकता होती है", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "फ़ाइल में बैकअप लें", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "मेरे-ublock-बैकअप_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "फाइल से वापस करो", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "सेटिंग्स को पहले की तरह करें...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "{{समय}} पर बैकअप किए गए डेटा इस्तेमाल करके आपकी सभी सेटिंग्स को ओवरराइट कर दिया जाएगा, और uBlock₀ फिर से चालू किया जाएगा।\n\nबैकअप डेटा का इस्तेमाल करके सभी मौजूदा सेटिंग्स को ओवरराइट करें?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "डेटा पढ़ा नहीं जा सका या अमान्य है", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "आपकी सारी सेटिंग्स मिटा दी जाएंगी, और uBlock₀ को फिर से चालू किया जाएगा।\n\nuBlock₀ को फ़ैक्टरी सेटिंग्स पर रीसेट करें?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "नेटवर्क त्रुटि : {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: इस यूआरएल को अपने कस्टम लिस्ट में डालें?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "सबˈस्क्राइब्", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "एक मिनट पहले", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} मिनट पहले", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "एक घंटे पहले", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} घंटे पहले", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "एक दिन पहले", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} दिन पहले", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "डैशबोर्ड दिखाओ", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "लॉगर दिखाएं", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "बंद", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "पृष्ठ प्रतिबंधित है", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin ने इस पेज को लोड होने से रोक दिया हैं:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "इस फिल्टर की वजह से ", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "इन में पायी है:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "वापस जाएँ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "इस विंडो को बंद करे", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "इस साइट के बारे में मुझे दोबारा चेतावनी न दें", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "स्ट्रिक्ट ब्लॉकिंग को बंद करें इस साइट पर {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "कुछ समय के लिए", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "स्थायी", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "आगे बढ़ें", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "क्लाउड स्टोरेज में भेजें", + "description": "tooltip" + }, + "cloudPull": { + "message": "क्लाउड स्टोरेज से आयात करें", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "क्लाउड स्टोरेज से डाउनलोड करें और मौजूदा सेटिंग्स के साथ मिलाएं ", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "इस साधन का नाम:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "चेतावनी! इन एडवांस सेटिंग्स को अपने जोखिम पर बदलें", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "पक्का", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "परिवर्तन लागू करें", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "पलटदे", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "बाइट्स", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "फ्रेम में तत्व को ब्लॉक करें...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "फ़िल्टर सूची की सदस्यता लें...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "कुछ समय के लिए विशाल तत्वोंको चलने की अनुमति दे", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "स्रोत कोड देखें", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "शॉर्टकट को टाइप करें ", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "लॉक की हुई स्क्रोलिंग को टोगल करें ", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "क्लिपबोर्ड में कॉपी करें", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "सभी चुनें", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "कॉस्मेटिक फ़िल्टरिंग टॉगल करें", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "ब्लैकिंग मोड को ढील दें", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "इस्तेमाल हुई स्टोरेज:{{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "केबी", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "एमबी", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "जीबी", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "लोड करने के लिए क्लिक करें", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "त्रुटियाँ : {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "ब्राउज़र खोलने पर ठीक से फ़िल्टर नहीं कर सका। उचित फ़िल्टरिंग सुनिश्चित करने के लिए वेबपेज को रीलोड करें।", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/hr/messages.json b/src/_locales/hr/messages.json new file mode 100644 index 0000000..edceb34 --- /dev/null +++ b/src/_locales/hr/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Konačno, efikasan blokator. Lak na CPU i memoriji.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Nadzorna ploča", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Upozorenje! Niste spremili promjene", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Ostani", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignoriraj", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Postavke", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Liste filtera", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Moji filteri", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Moja pravila", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Pouzdane stranice", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Tipkovni prečaci", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Zapisnik mrežnih zahtjeva", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O programu", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Podrška", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Preglednik svojstva", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Napredne postavke", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: trajno onemogućiti/omogućiti uBlock₀ za ovaj sajt.\n\nCtrl+klik: onemogućiti µBlock₀ samo za ovu stranicu.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknite za onemogućiti uBlock₀ za ovaj sajt.\n\nCtrl+klik za onemogućiti uBlock₀ samo za ovu stranicu.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknite za omogućiti uBlock₀ za ovaj sajt.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "zahtjeva blokirano", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na ovoj stranici", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ili {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od instalacije", + "description": "English: since install" + }, + "popupOr": { + "message": "ili", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokirano na ovoj stranici", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokirano od instalacije", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domena povezano", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Otvori upravljačku ploču", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Pokrenite odabir elementa za blokiranje", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Pokrenite odabir elementa", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Odlazak na zapisnik zahtjeva", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Prijavite problem na ovoj web stranici", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Uključi/isključi skočne prozore na ovoj stranici", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknite za blokiranje svih pop-up prozora na ovom sajtu", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknite za ukloniti blokiranje svih pop-up prozora na ovom sajtu", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Namjestite blokiranje velikih medijskih elemenata za ovo mjesto", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknite za blokiranje velikih medijskih elemenata na ovom sajtu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknite za ukloniti blokiranje velikih medijskih elemenata na ovom sajtu", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Uključi/isključi estestko filtriranje na ovoj stranici", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknite kako biste onemogućili estestko filtriranje na ovom sajtu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknite kako biste omogućili estestko filtriranje na ovom sajtu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Uključi/isključi blokiranje udaljenih fontova za ovu stranicu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknite za blokiranje udaljenih fontova na ovom sajtu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknite za ukloniti blokiranje udaljenih fontova na ovom sajtu", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kliknite kako biste onemogućili JavaScript na ovoj stranici", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kliknite kako biste omogućili JavaScript na ovoj stranici", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Skočni prozori", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Veliki medija elementi", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Estetski filteri", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Udaljeni fontovi", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Više", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Manje", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globalna pravila: ovaj stupac je za pravila koja vrijede za sve stranice.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknite kako biste spremili promjene.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknite kako bi vratili promjene.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "sve", + "description": "" + }, + "popupImageRulePrompt": { + "message": "slike", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "treće strane", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/slike trećih strana", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "skripte u liniji", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Skripte prve strane", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skripte trećih strana", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Okviri trećih strana", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domena povezan", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} od {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Verzija", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skripta", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "okvir", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Stvaranje", + "description": "English: Create" + }, + "pickerPick": { + "message": "Odabir", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Izlaz", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Pregled", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Mrežni filteri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Estetski filteri", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokiraj element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Sakrij rezervirana mjesta blokiranih elemenata", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Pokaži broj blokiranih zahtjeva na ikoni", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Isključi naputke", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Koristite kontekstni izbornik gdje je prikladno", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Ugodan za daltoniste", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Izgled", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Prilagođena glavna boja", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Omogući podršku za pohranu u oblaku", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ja sam napredni korisnik", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Onemogući pretpreuzimanje (za sprečavanje bilo koje veze blokiranih mrežnih zahtjeva)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Onemogući provjeravanje hiperlinkova", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Spriječi WebRTC da propušta lokalnu IP adresu", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Zadano ponašanje", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ova zadana ponašanja mogu biti poništena na bazi web-stranice", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Onemogući estesko filtriranje", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokiraj medijske elemente veće od {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokiraj udaljene fontove", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Onemogući JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokiraj CSP izvješća", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Prikaži kanonske nazive", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Napredno", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Značajke prikladne samo za napredne korisnike.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "napredne postavke", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Posljednji povratak na prijašnje:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Posljednja sigurnosna kopija:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} mrežni/ih filter/a + {{cosmeticFilterCount}} estetski/ih filter/a iz:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} korišteno od {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatsko ažuriranje popisa filtera.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Ažuriraj odmah", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Očistiti sve cache-ove", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Raščlaniti i primijeniti estetske filtre.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Estetski filteri služe za skrivanje elementa web stranice koji se smatraju vizualnim smetanjem i koji ne mogu biti blokirani filtriranjem mrežnih zahtjeva.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignoriraj opće estetsko filtriranje.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Generički estetski filteri su takvi filteri koji su namijenjeni svim web stranicama. Omogućavanjem ove postavke eliminirati će se memorijska i procesorska dodatna upotreba na web stranicama kao rezultat korištenja generičkih estetskih filtera.\n\nPreporučeno je omogućiti ovu postavku na slabijim uređajima.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Obustavite mrežnu aktivnost dok se ne učitaju svi popisi filtera", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Popis blokiranih hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Primijeni promjene", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Ugrađeno", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklame", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privatnost", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Zaštita od zlonamjernog softvera, sigurnost", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Nametljivost", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Višenamjensko", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regije, jezici", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Prilagođeno", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Uvoz…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Jedan URL po retku. Nevaljani URL-ovi će biti tiho ignorirani.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zastarjelo.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "vidi sadržaj", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Posljednje ažuriranje: {{ago}}.\nKliknite za ažuriranje.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ažuriranje u tijeku…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Mrežna pogreška je sprječila ažuriranje resursa.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Jedan filter po retku. Filter može biti običan hostname ili filter kompatibilan sa EasyList-om. Linije sa prefiksom ! zanemarit će se.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nemojte dodavati filtere iz nepouzdanih izvora.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Uvesti i dodati...", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Izvoz...", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "moji-ublock-staticni-filteri_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Primijeni promjene", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Trajna pravila", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Privremena pravila", + "description": "header" + }, + "rulesRevert": { + "message": "Vratiti", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Izvršiti", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Uredi", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Spremi", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Odbaci", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Uvoz iz datoteke…", + "description": "" + }, + "rulesExport": { + "message": "Izvoz u datoteku...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "moja-ublock-dinamicna-pravila_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Popis dinamičkih pravila filtriranja.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Pravila sintakse: akcija tipa izvornog odredišta (sva dokumentacija).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortiraj:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Vrsta pravila", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Izvor", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinacija", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Direktiva pouzdanih stranica govori za koje bi web stranice uBlock Origin trebao biti onemogućen. Jedan zapis po retku.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Uvesti i dodati...", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Izvoz...", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "moje-ublock-pouzdane-stranice_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Primijeni promjene", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tip", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domena", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Sve", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Iza scene", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Trenutna kartica", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Ponovno učitaj sadržaj kartice", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Uključi/Isključi DOM inspektor", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Uključi/Isključi panel sa skočnim prozorima", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Zabilješke", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Očisti zabilješke", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pauziraj zabilješke (odbaci sve dolazne podatke)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Uključite zabilješke", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Uključi/Isključi filtriranje zabilješki", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrirajte zabilješke", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Postavke filtiriranja zabilješki", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ne", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "sadržajno", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokirano", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "dopušteno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "promijenjeno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Prve strane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Treće strane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalji", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista filtera", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Pravilo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Korijenski kontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Pripadnost", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tip", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dinamično URL filtriranje", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tip:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statičko filtriranje", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} mrežni zahtjev {{type}} {{br}}kojem URL adresa odgovora {{url}} {{br}}i koji dolazi od {{origin}},{{br}}{{importance}} postoji odgovarajući filter izuzetak.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokiraj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Dopusti", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tip “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "i tip", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "od “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "bilo gdje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "osim kad", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "čak i ako", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statični filter {{filter}} pronađen u:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statični filter nije pronađen u trenutno uključenim listama filtera", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Unosi zapisnika koji ne ispunjavaju sva tri uvjeta navedena ispod bit će automatski odbačeni:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Sačuvajte unose od zadnjih {{input}} minuta", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Sačuvajte najviše {{input}} osvježavanja stranice po kartici", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Sačuvajte najviše {{input}} unosa po kartici", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Koristi {{input}} linija po unosu u vertikalno proširenom načinu", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sakrij stupce:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Vrijeme", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/pravilo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Pripadnost", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Popis", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tablica", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Obično", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Otvori", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Napravi novu prijavu", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Nađi slične prijave", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacija", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Pročitajte dokumentaciju na uBlock/wiki kako bi ste saznali uBlock Origin mogućnosti.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Pitanja i podrška", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odgovori na pitanja i druge vrste podrške nalaze se na subreddit r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter problemi/website je pao", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Prijavite probleme s filtriranjem određenih web stranica uBlockOrigin/uAssets alatki za praćenje problema. Potreban je GitHub račun.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Važno: Izbjegavajte korištenje drugih blokera slične namjene u isto vrijeme s uBlock Origin-om jer to može uzrokovati probleme s filtriranjem na određenim web stranicama.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Savjeti: Provjerite jesu li vaše liste filtera ažurirane. Zapisnik je primarni alat za dijagnosticiranje problema povezanih s filterima.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Prijava greške", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Prijavite probleme sa samim uBlock Origin-om na uBlockOrigin/uBlock-problem alatki za praćenje problema. Potreban je GitHub račun.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informacije o rješavanju problema", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "U nastavku se nalaze tehničke informacije koje bi mogle biti korisne kada vam volonteri pokušavaju pomoći u rješavanju problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Važno: Potencijalno privatni ili osjetljivi podaci redigirani su prema zadanim postavkama. Redaktirane informacije mogu otežati rješavanje problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Prijavi problem sa filterom", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Kako biste izbjegli opterećivanje volontera duplim prijavama, provjerite nije li problem već prijavljen.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Popisi filtera ažuriraju se svakodnevno. Provjerite nije li vaš problem već riješen sa najnovijim popisima filtera.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Provjerite postoji li problem i dalje nakon ponovnog učitavanja problematične web stranice.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa web stranice:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Web stranica…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Odaberite unos --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Prikazuje oglase ili ostatke oglasa", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ima overlaye ili druge smetnje", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detektira uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ima problema u vezi s privatnošću", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Ruši se kad je uBlock Origin omogućen", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Otvara neželjene kartice ili prozore", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Označite web stranicu kao “NSFW” (“nije sigurno za pregledavanje na poslu“)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redigiraj", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Vratiti na prijašnje", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Pravila privatnosti", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Popis promjena", + "description": "" + }, + "aboutCode": { + "message": "Izvorni kôd (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Suradnici", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Izvorni kod", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Prijevodi", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Liste filtera", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Vanjski korišteni programi (GPLv3-kompatiblini):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Vlastiti popisi filtera uBO-a besplatno su posluženi sa sljedećih CDN-ova:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Koristit će se slučajno odabrani CDN kada treba ažurirati popis filtera", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sigurnosno kopiranje u datoteku...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "moja-ublock-sig_kopija_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Vraćanje iz datoteke…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Vraćanje izvornih zadanih postavki…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Sve vaše postavke prebrisat će se sa postavkama spremljenim {{time}}, i uBlock₀ će se ponovno pokrenuti. \n\nPrepisati sve postojeće postavke pomoću sigurnosne kopije postavki?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Podatke nije moguće učitati ili su neispravni", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Sve vaše postavke će biti obrisane i µBlock₀ će se ponovno pokrenuti. \n\nVraćanje µBlock₀ tvorničkih postavki?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Mrežna greška {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Dodajte slijedeći izvor u vaš izbor filter lista?\n\nNaslov: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Prijava", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "prije minutu", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "prije {{value}} minute/a", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "prije jedan sat", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "prije {{value}} sata/i", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "prije jedan dan", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "prije {{value}} dana", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Prikaži kontrolnu ploču", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Prikaži zapis mrežnih zahtjeva", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "isključen", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Stranica blokirana", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin je onemogućio učitavanje sljedeće stranice:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Zbog sljedećeg filtera", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametara", + "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": "Pronađeno u:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Natrag", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zatvori ovaj prozor", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ne upozoravaj me više za ovu web stranicu", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Isključi strogo blokiranje za {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Privremeno", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Trajno", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Nastavi", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Izvezi u pohranu u oblaku", + "description": "tooltip" + }, + "cloudPull": { + "message": "Uvezi iz pohrane u oblaku", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Uvezite iz spremišta u oblaku i spojite sa trenutnim postavkama", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Naziv ovog uređaja:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Upozorenje! Mijenjate ove napredne postavke na vlastitu odgovornost.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Pošalji", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Primijeni promjene", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Vratiti", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajtovi", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokiraj element u okviru…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Prijavite se na popis filtera…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Privremeno dopusti velike medijske elemente", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Pogledaj izvorni kod...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Utipkajte tipkovni prečac", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Uključi/Isključi zaključano pomicanje", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiraj u međuspremnik", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Odaberi sve", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Prekidač estetskog filtriranja", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Opušteni način blokiranja", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Korišteno prostora: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kliknite za pokretanje", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Greške: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Nije moguće pravilno filtrirati pri pokretanju \npreglednika. Ponovno učitajte stranicu \nkako biste osigurali ispravno filtriranje.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Ova stavka mora biti posljednja", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json new file mode 100644 index 0000000..f4c8e47 --- /dev/null +++ b/src/_locales/hu/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "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.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Vezérlőpult", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Figyelem! Neked még vannak nem mentett változtatásaid", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Tartózkodás", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Figyelmen kívül hagyás", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Beállítások", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Külső szűrők", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Saját szűrők", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Saját szabályok", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Kivételek", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Billentyűparancsok", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Hálózati lekérések naplója", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Névjegy", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Támogatás", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ - Eszköznézet", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Haladó beállítások", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klikk: uBlock₀ tiltása/engedélyezése ezen a webhelyen.\n\nCtrl+klikk: csak a jelenlegi oldal tiltása/engedélyezése.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kattints a uBlock₀ letiltásához ezen a webhelyen.\n\nCtrl+kattintás a uBlock₀ letiltásához csak a jelenlegi oldalon.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kattints az uBlock₀ engedélyezéséhez ezen a webhelyen.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokkolt lekérések", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ezen a lapon", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} vagy {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "telepítés óta", + "description": "English: since install" + }, + "popupOr": { + "message": "vagy", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokkolva ezen az oldalon", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokkolva a telepítés óta", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Csatlakoztatott domain-ek", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Vezérlőpult megnyitása", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Belépés az elemeltávolító módba", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Elemválasztó mód aktiválása", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Naplózott lekérések megtekintése", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Az oldalon lévő probléma bejelentése", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Oldal összes felugró ablakának blokkolása/engedélyezése", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kattints az összes előugró ablak letiltásához ezen a webhelyen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kattints, hogy ne legyen többé az összes előugró ablak blokkolva ezen a webhelyen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Nagyméretű média elemek blokkolásának ki/bekapcsolása", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kattints a nagyméretű médiaelemek blokkolásához ezen a webhelyen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kattints a nagyméretű médiaelemek blokkolásának visszavonásához ezen a webhelyen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Kozmetikai szűrés ki- és bekapcsolása ezen a weboldalon", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kattints a kozmetikai szűrés kikapcsolásához ezen a webhelyen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kattints a kozmetikai szűrés bekapcsolásához ezen a webhelyen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Távoli betűkészletek blokkolásának ki/bekapcsolása ezen az oldalon", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kattints a távoli fontok blokkolásához ezen a webhelyen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kattints a távoli betűtípusok blokkolásának visszavonásához ezen a webhelyen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kattints a JavaScript teljes letiltásához ezen az oldalon", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kattints, hogy JavaScript ne legyen teljesen letiltva ezen az oldalon", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Felugró ablakok", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Nagy média elemek", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kozmetikai szűrés", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Távoli betűtípusok", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Több", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Kevesebb", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globális szabályok: ebben az oszlopban azok a szabályok vannak, amelyek minden weboldalra vonatkoznak.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokális szabályok: ebben az oszlopban azok a szabályok vannak, amelyek csak a jelenlegi weboldalra vonatkoznak.\nA lokális szabályok felülírják a globális szabályokat.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kattintson a módosítások véglegesítéséhez.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kattintson ide a módosítások visszavonásához.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "minden", + "description": "" + }, + "popupImageRulePrompt": { + "message": "képek", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "külső féltől", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "külső féltől származó css/képek", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scriptek", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scriptek", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scriptek", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frame-ek", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domain csatlakozik", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}}, összesen: {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Verzió", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "szkript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "keret", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Létrehoz", + "description": "English: Create" + }, + "pickerPick": { + "message": "Választ", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Kilép", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Előnézet", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Hálózati szűrők", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kozmetikai szűrők", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klikk, Ctrl-klikk", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Elem blokkolása", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Blokkolt elemek helyőrzőinek elrejtése", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Jelenjen meg a blokkolt lekérések száma az ikonon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Buboréksúgó (tooltip) kikapcsolása", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Környezeti menü alkalmazása, ahol lehetséges", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Színvak-barát", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Kinézet", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Téma", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Egyedi akcentus szín", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Felhőben tárolás bekapcsolása", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Haladó felhasználó vagyok (További tudnivalók)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Előtöltés kikapcsolása (kapcsolódás megakadályozása blokkolt hálózati lekérésekhez)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Hivatkozás-vizsgálat kikapcsolása", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC helyi IP-cím szivárogtatásának megakadályozása", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Alapértelmezett viselkedés", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ezek az alapértelmezett viselkedések felülírhatóak weboldal-szinten", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Kozmetikai szűrés kikapcsolása", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Média elemek blokkolása, amelyek nagyobbak, mint {{input:number}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Távoli betűkészletek blokkolása", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript letiltása", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP jelentések blokkolása", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Kanonikus nevek felfedése", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Haladó", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkciók csak haladó felhasználóknak ", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "haladó beállítások", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Utolsó visszaállítás:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Utolsó biztonsági mentés:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} hálózati szűrők + {{cosmeticFilterCount}} kozmetikai szűrők:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} használatban a listában lévő {{total}} szűrő közül", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Szűrőlisták automatikus frissítése.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Frissítés most", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Gyorsítótárak ürítése", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Értelmezze és alkalmazza a kozmetikai szűrőket.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Ez a beállítás engedélyezi az Adblock Plus-típusú “elemelrejtő” szűrőket. Ezek kizárólag kozmetikai célokat szolgálnak; elrejtik egy webhely azon elemeit, amelyek vizuálisan zavaróak, de a hálózati lekérések alapján nem szűrhetők ki.

A beállítás engedélyezése megnöveli a uBlock₀ memóriahasználatát.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Általános kozmetikai szűrők figyelmen kívül hagyása", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Az általános kozmetikai szűrők azok a kozmetikai szűrők, amelyek minden weboldalra érvényesek.

Ugyan a uBlock₀ hatékonyan kezeli őket, az általános kozmetikai szűrők mégis mérhetően magasabb memória és CPU használatot eredményezhetnek néhány weboldalon, főleg nagy, és régóta futóak esetében.

Ennek az opciónak a bekapcsolása kiküszöböli az általános kozmetikai szűrők kezeléséből a weboldalakon adódó memória és CPU használat többletet, továbbá csökkenti a uBlock₀ által foglalt memóriát is.

Ajánlott bekapcsolni ezt az opciót a gyengébb eszközökön.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Hálózati forgalom szüneteltetése, amíg a szűrőlisták be nem töltődtek", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Blokkolt hostokat tartalmazó listák", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Módosítások alkalmazása", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Beépített", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Hirdetések", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Adatvédelem", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware domainek", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Kellemetlenségek", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Többcélú", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Régiók, nyelvek", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Saját", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importálás...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Soronként egy URL. A ‘!’ kezdetű sorok figyelmen kívül maradnak. A szabálytalan URL-ek szintén figyelmen kívül maradnak, hibajelzés nélkül.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Elavult.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "tartalom megtekintése", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Utolsó frissítés: {{ago}}.\nKattintson a frissítés kényszerítéséhez.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Frissítés...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Egy hálózati hiba megakadályozta az erőforrás frissítését.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Soronként egy szűrő. A szűrő lehet egy hostnév, vagy egy Adblock Plus kompatibilis szűrő.\nA ! kezdetű sorok figyelmen kívül maradnak.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Ne adj hozzá szűrőket megbízhatatlan forrásokból.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importál és hozzáad", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportál", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-statikus-szabalyaim_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Módosítások alkalmazása", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Állandó szabályok", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Átmeneti szabályok", + "description": "header" + }, + "rulesRevert": { + "message": "Visszaállítás", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Alkalmaz", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Szerkesztés", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Mentés", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Elvetés", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importálás fájlból…", + "description": "" + }, + "rulesExport": { + "message": "Exportálás fájlba…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-dinamikus-szabalyaim_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Saját szűrőszabályok listája.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Szabály szintaxis: forrás cél típus művelet (Teljes dokumentáció).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Rendezés:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Szabály típusa", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Forrás", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Cél", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Az alábbi listában felsorolt hostokon a kiegészítő nem fog működni. Soronként egy bejegyzés. Érvénytelen hostnevek figyelmen kívül maradnak.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importál és hozzáad", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportál", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-feherlistam_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Módosítások alkalmazása", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Típus", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Szűrő", + "description": "English: Filter" + }, + "logAll": { + "message": "Összes", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Hálózati forgalom a háttérben", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Jelenlegi lap", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Töltse újra a lap tartalmát", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM ellenőrző kapcsolása", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Felugró panel kapcsolása", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: A naplózó", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Naplózó törlése", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Naplózás szüneteltetése (az összes bejövő adat elvetése)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Naplózó folytatása", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Naplózó szűrőjének kapcsolása", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "naplóbejegyzések szűrése", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Naplózó szűrő beállítások", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nem", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokkolva", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "engedélyezve", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "módosított", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1. fél", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3. fél", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Részletek", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Szűrő", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Szűrő lista", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Szabály", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontextus", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Gyökér kontextus", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Típus", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dinamikus URL szűrő", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontextus:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Típus:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statikus szűrés", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "Hálózati kérések {{action}} amik {{type}} {{br}} és illeszkednek a(z) {{url}} URL-re {{br}} és amik innen származnak: {{origin}},{{br}}{{importance}} van illeszkedő kivétel szűrő.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "blokkolása", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "engedélyezése", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "„{{type}}” típusúak", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "bármilyen típusúak", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "{{origin}}", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "bárhonnan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "kivéve ha", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "akkor is, ha", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statikus filter, amiben {{filter}} benne van:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "A statikus szűrő {{filter}} nem található az aktuálisan engedélyezett szűrőlisták egyikében sem", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "A naplózó bejegyzések, amelyek nem felelnek meg az alábbi három feltételnek, automatikusan eldobásra kerülnek:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "A bejegyzések megőrzése az utolsó {{input}} percből", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Tartsa meg a legtöbb {{input}} lapot betöltéskor laponként", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Tartsa meg a legtöbb {{input}} bejegyzést laponként", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Használja a {{input}} sorokat egy bejegyzésre függőlegesen bővített módban", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Oszlopok elrejtése:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Idő", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Szűrő/szabály", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontextus", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tábla", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Sík", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Megnyitás", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Hiba bejelentése", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Hasonló hibák keresése", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentáció", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Az uBlock Origin további funkcióihoz látogassa meg a dokumentációt itt: uBlock/wiki.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Kérdések és támogatás", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "A felhasználói kérdésekre választ és további segítséget, támogatást az /r/uBlockOrigin subredditen nyújtunk.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Szűrőhibák/a weboldal nem működik megfelelően", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Adott weboldalra vonatkozó szűrőhibákat jelentse a uBlockOrigin/uAssets hibakövetőn. GitHub-fiók szükséges.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Fontos: Ne használjon hasonló célú reklámblokkolókat az uBlock Originnal egyszerre, mert ez szűrőhibákat okozhat bizonyos weboldalakon.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tippek: Bizonyosodjon meg arról, hogy a legfrissebb szűrőlistákat használja. A napló a legfontosabb eszköz a szűrőkkel kapcsolatos hibák diagnózisában.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Hibajelentés", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Az uBlock Origin hibáit jelentse a uBlockOrigin/uBlock-issue hibakövetőn. GitHub-fiók szükséges.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Hibakeresési információ", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Az alább található technikai információk segíthetnek önkénteseinknek megoldani a problémáját.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Fontos: Az esetlegesen személyes vagy érzékeny adatok alapértelmezésből rejtve vannak. Az elrejtett információk megnehezíthetik a probléma megoldását.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Szűrőhibák bejelentése", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "A szűrőlisták naponta frissülnek. Ügyeljen arra, hogy az Ön problémája ne szerepeljen már a legfrissebb szűrőlistákon.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Ellenőrizze, hogy a probléma a problémás weboldal újratöltése után is fennáll-e.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "A weboldal címe:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "A weboldal...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Válasszon egy opciót --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Hirdetéseket vagy hirdetés maradványokat jelenít meg", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Zavaró elemeket tartalmaz", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Érzékeli a uBlock Origin-t", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Adatvédelmi problémákat vet fel", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Hibásan működik, amikor az uBlock Origin be van kapcsolva", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Kéretlen lapokat vagy ablakokat nyit meg", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "A weboldal megjelölése felnőtt tartalomként", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Elrejtés", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Megjelenítés", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Adatvédelmi szabályzat", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Változások listája", + "description": "" + }, + "aboutCode": { + "message": "Forráskód (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Közreműködők", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Forráskód", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Fordítások", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Szűrő listák", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Külső függőségek (GPLv3-kompatibilis):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Az uBO saját szűrőlistáit a következő ingyenes CDN-ek (angol) szolgáltatják:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A szűrőlisták frissítéséhez egy véletlenszerűen kiválasztott CDN-t használ a bővítmény", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Biztonsági mentés fájlba", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-mentesem_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Visszaállítás fájlból...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Alapértelmezett beállítások visszaállítása...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "A jelenlegi beállítások felülíródnak a mentett adatokkal (mentési idő: {{time}}), utána a uBlock₀ újraindul.\n\nFelülírja a jelenlegi beállításokat a biztonsági mentéssel?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Nem olvasható vagy érvénytelen adat", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Az összes beállítás törlődik, utána a uBlock₀ újraindul.\n\nÁllítsa vissza a gyári beállításokat?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Hálózati hiba: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Hozzáadja a következő URL-t a saját szűrő listákhoz?\n\nNév: \"{{title}}\"\nURL: \"{{url}}\"", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Feliratkozás", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "egy perce", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} perce", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "egy órája", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} órája", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "egy napja", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} napja", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Vezérlőpult megnyitása", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Napló mutatása", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "kikapcsolva", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Oldal blokkolva", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin nem engedte a következő lap betöltését:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "A következő szűrő miatt", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "paraméterek nélkül", + "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": "Ezekben található:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Vissza", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Ablak bezárása", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ne figyelmeztessen újra ennél az oldalnál", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Kapcsolja ki a szigorú tiltást a(z) {{hostname}} részére", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Ideiglenesen", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Véglegesen", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Továbblépés", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportálás a felhőszolgáltatásba", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importálás a felhőszolgáltatásból", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importálás a felhőből és egybevonás a jelenlegi beállításokkal", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Ennek az eszköznek a neve:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Figyelem! Haladó beállítások, megváltoztatásuk csak saját felelősségre.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Küldés", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Módosítások alkalmazása", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Visszaállítás", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bájt", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Elem blokkolása a keretben", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Feliratkozás szűrőlistára...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Nagyméretű média elemek ideiglenes engedélyezése", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Forráskód megtekintése…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Billentyűkombináció megadása", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Zárolt görgetés kapcsolása", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Másolás a vágólapra", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Mindent kijelöl", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kozmetikai szűrés kapcsolása", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaxáló blokkolási mód", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Használt tárolás: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kattints a betöltéshez", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Hibák: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Nem sikerült megfelelően szűrni a böngésző indításakor. Töltse újra az oldalt a megfelelő szűrés biztosítása érdekében.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Ez a bejegyzés utolsó kell hogy legyen", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/hy/messages.json b/src/_locales/hy/messages.json new file mode 100644 index 0000000..291d67c --- /dev/null +++ b/src/_locales/hy/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Վերջապե՛ս, արդյունավետ արգելափակիչ։ Խնայում է մշակիչը և հիշողությունը։", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Կառավահան", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Ուշադրությո՛ւն։ Դուք ունեք չպահպանված փոփոխություններ։", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Մնալ", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Անտեսել", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Կարգավորումներ", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Զտիչների ցանկեր", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Իմ զտիչները", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Իս կանոնները", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Վստահված կայքեր", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Դյուրանցումներ", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Մատյան", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Ընդլայնման մասին", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Աջակցություն", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Ակտիվների դիտակ", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Ընդլայնված կարգավորումներ", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀֊ն միայն այս էջում անջատելու համար։", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "կտտացրեք՝ uBlock₀֊ն այս կայքի համար միացնելու համար։", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "արգելափակված հարցում", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "այս էջում", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "տեղադրման պահից", + "description": "English: since install" + }, + "popupOr": { + "message": "կամ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Արգելափակվել է այս էջում", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Արգելափակվել է տեղադրման պահից", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Միացվել է տիրույթներ", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Բացել կառավահանը", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Գործարկել տարրերի ջնջման ռեժիմը", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Գործարկել տարրերի ընտրության ռեժիմը", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Բացել մատյանը", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Հաղորդել կայքում առաջացած խնդրի մասին", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Միաց./Անջ. այս կայքի բոլոր ելնող լուսամուտների արգելափակումը", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Կտտացրեք՝ այս կայքի բոլոր ելնող լուսամուտներն արգելափակելու", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Կտտացրեք՝ այս կայքի բոլոր ելնող լուսամուտների արգելափակումն անջատելու", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Միաց./Անջ. այս կայքի խոշոր մեդիա տարրերի արգելափակումը", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Կտտացրեք՝ այս կայքի խոշոր մեդիա տարրերն արգելափակելու", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Կտտացրեք՝ այս կայքի խոշոր մեդիա տարրերի արգելափակումն անջատելու", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Միաց./Անջ. կոսմետիկ զտումն այս կայքի համար", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Կտտացրեք՝ այս կայքում կոսմետիկ զտումն անջատելու", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Կտտացրեք՝ այս կայքում կոսմետիկ զտումը միացնելու", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Միաց./Անջ. կողմնակի տառատեսակների արգելափակումն այս կայքի համար", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Կտտացրեք՝ կողմնակի տառատեսակներն այս կայքում արգելափակելու", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Կտտացրեք՝ այս կայքի համար կողմնակի տառատեսակների արգելափակումն անջատելու", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Կտտացրեք՝ JavaScript֊ն այս կայքում անջատելու", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Կտտացրեք՝ այս կայքում JavaScript֊ն այլևս չանջատելու համար", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ելնող լուսամուտներ", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Խոշոր մեդիա տարրեր", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Կոսմետիկ զտում", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Կողմնակի տառատեսակներ", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Ավել", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Պակաս", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Համընդհանուր կանոններ. այս սյունակը նախատեսված է բոլոր կայքերի վրա տարածվող կանոնների համար։", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Տեղական կանոններ. այս սյունակը նախատեսված է միայն այս կայքի վրա տարածվող կանոնների համար։\nՏեղական կանոնները վերասահմանում են համընդհանուր կանոնները։", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Կտտացրեք՝ փոփոխությունները պահպանելու համար։", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Կտտացրեք՝ փոփոխությունները հետարկելու համար։", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "բոլորը", + "description": "" + }, + "popupImageRulePrompt": { + "message": "պատկերներ", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3-րդ կողմերի ռեսուրսներ", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3-րդ կողմերի CSS/պատկերներ", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ներտող սկրիպտներ", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1-ին կողմի սկրիպտներ", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3-րդ կողմերի սկրիպտներ", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3-րդ կողմերի շրջանակներ", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "միացված տիրույթներ", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}}֊ից {{count}}֊ը", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Տարբերակ", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "սկրիպտ", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "շրջանակ", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Ստեղծել", + "description": "English: Create" + }, + "pickerPick": { + "message": "Ընտրել", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Դուրս գալ", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Նախադիտում", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Ցանցային զտիչներ", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Կոսմետիկ զտիչներ", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Կտտոց, Ctrl+կտտոց", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Արգելափակել տարրը...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Թաքցնել արգելափակված տարրերի տեղապահները", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Ցուցադրել արգելափակված հայտերի քանակը պատկերակի վրա", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Անջատել գործիքահուշերը", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Օգտվեք համատեքստային ընտրացանկից, երբ դա տեղին է", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Բարեհաճ գույներ գունակուրություն ունեցողների համար", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Արտաքին տեսք", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Թեմա", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Ընտրովի շեշտային գույն", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Միացնել ամպային պահեստի աջակցոմը", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ես հմուտ օգտվող եմ (կարդալը պարտադիր է)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Անջատել նախաբեռնումը՝ արգելափակված ցանցային հայտերի համար միացումները կանխելու", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Անջատել հիպերհղումների ստուգումը", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Կանխել տեղական IP-հասցեների արտահոսքը WebRTC-ի միջոցով", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Լռելյայն վարքագիծ", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Այս կարգավորումները կարող են նշված լինել յուրաքանչյուր կայքի համար ջոկ֊ջոկ", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Անջատել կոսմետիկ զտումը", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Արգելափակել {{input}} ԿԲ-ից մեծ մեդիա տարրերը", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Արգելափակել կողմնակի տառատեսակները", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Անջատել JavaScript֊ը", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Արգելափակել CSP հաշվետվությունները", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Բանալ կանոնական անունները", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Ընդլայնված կարգավորումներ", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Տեխնիկական օգտվողների համար նախատեսված գործառույթներ", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "ընդլայնված կարգավորումներ", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Վերջին վերականգնումը՝", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Վերջին պահուստային պատճենը՝", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} ցանցային զտիչ + {{cosmeticFilterCount}} կոսմետիկ զտիչ այստեղից՝", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}}֊ից օգտագործվում է {{used}}֊ը", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Ինքնաշխատորեն թարմացնել զտիչների ցանկերը", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Թարմացնել հիմա", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Մաքրել բոլոր հիշապահեստները", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Վերլուծել և կիրառել կոսմետիկ զտիչներ", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Կոսմետիկ զտիչները ծառայում են կայքէջի այն տարրերը թաքցնելու համար, որոնք պատճառում են տեսողական անհանգստություն և որոնք չեն կարող արգելափակվել ցանցային հայտերի հիման վրա աշխատող զտման մեխանիզմներով։", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Անտեսել ընդհանուր կոսմետիկ զտիչները", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Ընդհանուր կոսմետիկ զտիչներն այն կոսմետիկ զտիչներն են, որոնք նախատեսված են կիրառվել բոլոր կայքերում։ Այս ընտրանքը միացնելը կվերացնի հիշողության և մշակիչի բեռնվածությունը, որը կայքեջերի մոտ ավելանում է ընդհանուր կոսմետիկ զտիչների մշակման արդյունքում։\n\nԽորհուրդ է տրվում միացնել այս ընտրանքը ոչ բավականաչափ հզոր սարքերում։", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Կանգնեցնել ցանցային ակտիվությմւնը մինչև բեռնվեն զտիչների բոլոր ցուցակները", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Կիրառել փոփոխությունները", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Ներկառուցված", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Գովազդ", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Գաղտնիություն", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Վնասակար տիրույթներ", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Ջղայնացնող տարրեր", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Բազմանպատակային", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Տարածաշրջաններ, լեզուներ", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Օգտվողային", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Ներմուծել...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Մեկ URL մեկ տողում։ Անվավեր URL֊ներն անտեսվելու են առանց նախազգուշացման։", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Ժամկետանց։", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "տեսնել բովանդակությունը", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Վերջին թարմացումը՝ {{ago}}։\nԿտտացրեք՝ ստիպողական թարմացման համար։", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Թարմացվում է...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ցանցի սխալի պատճառով թարմացումը տեղի չունեցավ։", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Մեկ տողում մեկ զտիչ։ Որպես զտիչ կարող է լինել կայքի անուն կամ EasyList-համաեղելի զտիչ։ ! -ով սկսվող տողերը կանտեսվեն։", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Մի՛ ավելացրեք զտիչներ անվստահելի աղբյուրներից։", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Ներմուծել և հավելել", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Արտահանել", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Կիրառել փոփոխությունները", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Մշտական կանոններ", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Ժամանակավոր կանոններ", + "description": "header" + }, + "rulesRevert": { + "message": "Հետադարձել", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Հաստատել", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Խմբագրել", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Պահպանել", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Չեղարկել", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Ներմուծել նիշքից...", + "description": "" + }, + "rulesExport": { + "message": "Արտահանել դեպի նիշք", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Դինամիկական զտման կանոնների Ձեր ցուցակը։", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Կանոնների շարահյուսություն՝ աղբյուր նպատակակետ տեսակ գործողություն (բոլոր փաստաթղթերը)։", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Տեսակավորել՝", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Կանոնի տեսակ", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Աղբյուր", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Նպատակակետ", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Վստահված կայքերի ցուցակը սահմանում է, թե որ կայքերում uBlock Origin-ը պիտի անջատված լինի։ Մեկ տողում մեկ գրառում։ Անճիշտ կանոններն առանց նախազգուշացման անտեսվելու և մեկնաբանվելու են։", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Ներմուծել և հավելել", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Արտահանել", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Կիրառել փոփոխությունները", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Տեսակ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Տիրույթ", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Զտիչ", + "description": "English: Filter" + }, + "logAll": { + "message": "Բոլորը", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Անդրկուլիսյան հարցումներ", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Ընթացիկ ներդիր", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Վերաբեռնել ներդիրի բովանդակությունը", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Միաց./Անջատել DOM-տեսուչը", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Միաց./Անջատել ելնող վահանակը", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin վիքի. Մատյան", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Մաքրել մատյանը", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Դադարեցնել մատյանավորումը (մերժել բոլոր մուտքային տվյալները)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Վերսկսել մատյանավորումը", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Միաց./Անջ. մատյանի զտումը", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "մատյանի գրառումների զտում", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Մատյանի զտման ընտրանքներ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ոչ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "արգելափակված", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "թույլատրված", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "փոփոխված", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1-ին կողմ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3-րդ կողմ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Մանրամասներ", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Զտիչ", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Զտիչների ցանկ", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Կանոն", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Համատեքստ", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Արմատային համատեքստ", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Պատկանելություն", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Տեսակ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL-ի կանոն", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Համատեքստ՝", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Տեսակ՝", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Ստատիկ զտիչ", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} {{type}} ցանցային հարցումները,{{br}}որոնց URL-հասցեներն համընկնում են {{url}} {{br}}և որոնք ծագում են {{origin}},{{br}}{{importance}} կա համապատասխան բացառության կանոն։", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Արգելափակել", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Թույլատրել", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "«{{type}}» տեսակի", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ցանկացած տեսակի", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "«{{origin}}»-ից", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "ցանկացած տեղից", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "բացառությամբ այն դեպքերի, երբ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "նույնիսկ եթե", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "{{filter}} ստատիկ զտիչը գտնվել է՝", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Ստատիկ զտիչն անհնար է գտնել ներկայումս միացված զտիչների ցանկերից որևէ մեկում", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Մատյանի գրառումները, որոնք չեն բավարարում ցածում նշված բոլոր երեք պայմաններին, ինքնաշխատ կմերժվեն։", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Պահպանել վերջին {{input}} րոպեի գրառումները", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Պահպանել ոչ ավելի, քան {{input}} բեռնում ամեն մի ներդիրում", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Պահպանել ոչ ավելի, քան {{input}} գրառում ամեն մի ներդիրում", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Ուղղահայացորեն ընդլայնված ռեժիմում օգտագործել {{input}} տող ամեն մի գրառման համար", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Թաքցնել սյունակները՝", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Ժամանակ", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Զտիչ/կանոն", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Համատեքստ", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Պատկանելություն", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Ցանկ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Աղյուսակ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Պարզ", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Բացել", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Նոր զեկույց ստեղծել", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Գտնել նման զեկույցներ", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Փաստաթղթեր", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Կարդացեք փաստաթղթերը uBlock/wiki-ում՝ uBlock Origin-ի բոլոր հնարավորությունների մասին իմանալու։", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Հարցեր և աջակցություն", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Հարցերի պատասխանները և օգնության այլ տեսակները մատչելի են Reddit-ի /r/uBlockOrigin բաժնում։", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Զտիչի խնդիրներ/կայքը կոտրված է", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Հաղորդեք որոշակի կայքերի հետ կապված զտիչի խնդիրների մասին uBlockOrigin/uAssets-ի խնդիրների հետագծիչի բաժնում։ Պահանջվում է GitHub հաշիվ։", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Կարևոր է. Խուսափեք uBlock Origin-ի հետ մեկտեղ նման այլ արգելափակիչներ օգտագործելուց, քանի որ դա կարող է որոշակի կայքերում զտիչի հետ կապված խնդիրներ առաջացնել:", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Խորհուրդներ.Համոզվեք, որ Ձեր զտիչների ցուցակները թարմացված են: Մատյանը զտիչների հետ կապված խնդիրների ախտորոշման հիմնական գործիքն է։", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Զեկույց սխալի մասին", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Հաղորդեք uBlock Origin-ի սեփական սխալների մասին uBlockOrigin/uBlock-issue խնդիրների հետագծիչի բաժնում։ Պահանջվում է GitHub հաշիվ։", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Ախտորոշիչ տեղեկություն", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Ցածում տեխնիկական տեղեկություն է, որը կարող է օգտակար լինել, երբ կամավորները փորձում են օգնել Ձեզ լուծել խնդիրը։", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Կարևոր է. Հնարավոր անձնական կամ զգայուն տեղեկությունները խմբագրվում է լռելյայնորեն։ Վերամշակված տեղեկություները կարող է ավելի բարդացնել խնդրի լուծումը:", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Հաղորդել զտիչի խնդրի մասին", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Կամավորներին կրկնօրինակ զեկույցներով չծանրաբեռնելու համար խնդրում ենք ստուգել, որ խնդիրն արդեն հաղորդված չէ։", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Զտիչների ցուցակները թարմացվում են ամեն օր։ Համոզվեք, որ Ձեր խնդիրը չի լուծվել զտիչների թարմ ցուցակներում։", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Համոզվեք, որ խնդիրը պահպանվում է նույնիսկ խնդրահարույց էջը վերաբեռնելուց հետո։", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Վեբ էջի հասցեն՝", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Վեբ էջը...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Ընտրեք կատեգորիա --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Գովազդ է ցուցադրվում կամ դրա մնացորդներ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Վրածածկումներ կամ այլ խանգարումներ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Հայտնաբերվում է uBlock Origin-ը", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Գաղտնիության հետ կապված խնդիրներ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Անսարքություններ, երբ uBlock Origin-ը միացված է", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Բացում է անցանկալի ներդիրները կամ լուսամուտները", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Նշել վեբ էջը որպես «NSFW» («Աշխատանքի համար անվտանգ չէ»)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Խմբագրել", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Չեղարկել խմբագրումը", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Գաղտնիության քաղաքականություն", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Փոփոխությունների մատյան", + "description": "" + }, + "aboutCode": { + "message": "Աղբյուրի կոդ (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Աջակցողներ", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Աղբյուրի կոդ", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Թարգմանություններ", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Զտիչների ցանկեր", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Արտաքին կախվածություններ (GPLv3-համատեղելի)՝", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO-ի սեփական զտիչների ցանկերն ազատորեն տեղաբաշխված են հետևյալ CDN-երում.", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Զտիչների ցանկը թարմացնելիս օգտագործվում է պատահականորեն ընտրված CDN", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Պահուստավորել նիշքում...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-իմ-պահուստ_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Վերականգնել նիշքից...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Վերականգնել լռելյայն կարգավորումները...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Ընթացիկ կարգավորումները կփոխարինվեն տվյալներով {{time}}-ին ստեղծված պահուստային պատճենից, և uBlock₀-ը կվերագործարկվի։\n\nՓոխարինե՞լ առկա բոլոր կարգավորումները պահուստավորված տվյալներով։", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Տվյալները չեն կարող ընթերցվել կամ անվավեր են", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Ձեր բոլոր կարգավորումները կջնջվեն, uBlock₀֊ը կվերագործարկվի։\n\nՎերականգնե՞լ լռելյայն կարգավորումները։", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Ցանցի սխալ՝ {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Ավելացնե՞լ հետևյալ հասցեն զտիչների օգտվողային ցանկին։\n\nՎերնագիր՝ «{{title}}»\nURL՝ {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Բաժանորդագրվել", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "րոպե առաջ", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} րոպե առաջ", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ժամ առաջ", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ժամ առաջ", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "օր առաջ", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} օր առաջ", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Ցույց տալ կառավահանը", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Ցույց տալ մատյանը", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "անջատված է", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Էջն արգելաբացվեց", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin֊ը կանխել է հետևյալ էջի բեռնումը՝", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Հետևյալ զտիչի պատճառով՝", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Գտնվել է այստեղ՝", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Հետ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Փակել այս լուսամուտը", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Այլևս չզգուշացնե՛լ ինձ այս կայքի մասին", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Անջատեք խիստ արգելափակումը {{hostname}}-ի համար", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Առժամապես", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Մշտապես", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Շարունակել", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Արտահանել առ ամպային պահեստ", + "description": "tooltip" + }, + "cloudPull": { + "message": "Ներմուծել ամպային պահեստից", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Ներմուծել ամպային պահեստից և միաձուլել ընթացիկ կարգավորումների հետ", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Այս սարքի անունը՝", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Ուշադրությո՛ւն։ Փոխեք այս կարգավորումները Ձեր ռիսկով և պատասխանատվությամբ։", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Հաստատել", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Կիրառել", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Հետադարձել", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "բայթ", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Արգելափակել տարրը շրջանակում...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Բաժնեգրվել զտիչների ցանկի...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Ժամանակավորապես թույլ տալ խոշոր մեդիա տարրերը", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Դիտել աղբյուրի կոդը…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Մուտքագրեք դյուրանցում", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Միաց./Անջատել ընդհանուր ոլորումը", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Պատճենել առ սեղմատախտակ", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Ընտրել բոլորը", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Փոխանջատել կոսմետիկ զտումը", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Արգելափակման թուլացված ռեժիմ", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Պահեստի չափը՝ {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "ԿԲ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "ՄԲ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ԳԲ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Կտտացրեք՝ բեռնելու համար", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Սխալներ՝ {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Չհաջողվեց կատարել զտումը զննիչի գործարկման ժամանակ։\nՎերաբեռնեք էջը՝ պատշաճ զտումն ապահովելու համար։", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json new file mode 100644 index 0000000..21629c1 --- /dev/null +++ b/src/_locales/id/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Akhirnya, pemblokir iklan yang efisien. Ringan penggunaan CPU dan memori.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dasbor", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Peringatan! Anda memiliki ubahan yang belum disimpan", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Tinggal", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Abaikan", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Pengaturan", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Daftar Filter", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Filter Saya", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Aturan Saya", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Situs Terpercaya", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Pintasan", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Pencatat Log", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Tentang", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Dukungan", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Penampil aset", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Pengaturan lanjutan", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: nonaktif/aktifkan uBlock₀ untuk situs ini.\n\nCtrl+klik: nonaktifkan uBlock₀ hanya di laman ini.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klik untuk menonaktifkan uBlock₀ pada situs ini.\n\nCtrl+klik untuk menonaktifkan uBlock₀ hanya di laman ini.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik untuk mengaktifkan uBlock₀ pada situs ini.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "permintaan diblokir", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "di laman ini", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} atau {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "sejak dipasang", + "description": "English: since install" + }, + "popupOr": { + "message": "atau", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Diblokir di laman ini", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Diblokir sejak dipasang", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domain terhubung", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Buka dasbor", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Memasuki mode penghapus elemen", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Memasuki mode pemilihan elemen", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Buka pencatat log", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Laporkan masalah situs web ini", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alihkan pemblokiran semua popup untuk situs ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik untuk memblokir semua popup pada situs ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik untuk tidak lagi memblokir semua popup pada situs ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Aktifkan/Nonaktifkan pemblokiran elemen media besar untuk situs ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik untuk memblokir elemen media berukuran besar pada situs ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik untuk tidak lagi memblokir elemen media berukuran besar pada situs ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Aktif/Nonaktifkan filter tampilan untuk situs ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik untuk menonaktifkan filter tampilan pada situs ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik untuk mengaktifkan filter tampilan pada situs ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Aktif/Nonaktifkan pemblokiran fon eksternal untuk situs ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik untuk memblokir fon eksternal pada situs ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik untuk tidak lagi memblokir fon eksternal pada situs ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klik untuk menonaktifkan total JavaScript di situs ini", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klik untuk tidak lagi menonaktifkan total JavaScript di situs ini", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Jendela pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elemen media besar", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filter tampilan", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fon eksternal", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Lebih banyak", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Lebih sedikit", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Aturan global: kolom ini untuk aturan yang diterapkan ke semua situs.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klik untuk membuat ubahan Anda permanen.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klik untuk membatalkan ubahan Anda.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "semua", + "description": "" + }, + "popupImageRulePrompt": { + "message": "gambar", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "pihak ketiga", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/gambar pihak ke-3", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "skrip inline", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skrip pihak pertama", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skrip pihak ketiga", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frame pihak ketiga", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domain terhubung", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} dari {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versi", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skrip", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Buat", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pilih", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Keluar", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Pratinjau", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filter jaringan", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filter tampilan", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokir elemen...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Sembunyikan wadah elemen yang diblokir", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Tampilkan jumlah permintaan yang diblokir pada ikon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Nonaktifkan tip alat", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Pergunakan menu konteks jika sesuai", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Ramah buta warna", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Tampilan", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Warna aksen khusus", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktifkan dukungan penyimpanan awan", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Saya pengguna tingkat lanjut", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Nonaktifkan pra-ambil (untuk mencegah sambungan apapun untuk permintaan jaringan yang diblokir)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Nonaktifkan pengauditan pranala", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Cegah WebRTC membocorkan alamat IP lokal", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Perilaku bawaan", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Perilaku bawaan ini bisa ditimpa pada masing-masing aturan situs", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Nonaktifkan filter tampilan", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokir elemen media yang lebih besar dari {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokir fon eksternal", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Nonaktifkan JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokir laporan CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Ungkap nama kanonis", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Tingkat lanjut", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Fitur ditujukan untuk pengguna tingkat lanjut.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "pengaturan lanjutan", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Pemulihan terakhir:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Pencadangan terakhir:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filter jaringan + {{cosmeticFilterCount}} filter tampilan dari:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} digunakan dari {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Otomatis perbarui daftar filter", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Perbarui sekarang", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Bersihkan semua tembolok", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Urai dan paksa terapkan filter tampilan", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Filter tampilan berfungsi untuk menyembunyikan elemen di halaman web yang dianggap sebagai gangguan visual, dan tidak bisa diblokir oleh filter berbasis permintaan jaringan.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Abaikan filter tampilan generik", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Filter tampilan generik adalah filter tampilan yang dibuat untuk diterapkan pada semua situs web. Mengaktifkan opsi ini akan menghilangkan peningkatan overhead memori ram dan CPU pada halaman web akibat diterapkannya filter tampilan generik.\n\nDirekomendasikan untuk mengaktifkan opsi ini pada perangkat dengan performa rendah.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Tunda aktivitas jaringan sampai semua daftar filter dimuat", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Daftar host yang diblokir", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Bawaan", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Iklan", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privasi", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Perlindungan malware, keamanan", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Gangguan", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Serbaguna", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Wilayah, bahasa", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Khusus", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Impor...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Satu URL per baris. URL yang tidak valid akan diabaikan tanpa peringatan.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Sudah usang.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "lihat konten", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Pembaruan terakhir: {{ago}}.\nKlik untuk memaksa memperbarui.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Memperbarui...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Galat jaringan mencegah sumber daya diperbarui.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Satu filter per baris. Filter dapat berupa nama hos, atau filter yang kompatibel dengan EasyList. Baris yang diawali dengan ! akan diabaikan.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Jangan tambah filter dari sumber yang tidak tepercaya.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Impor dan tambahkan…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Ekspor…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Aturan permanen", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Aturan sementara", + "description": "header" + }, + "rulesRevert": { + "message": "Urungkan", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Tetapkan", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Sunting", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Simpan", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Batal", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Impor dari berkas...", + "description": "" + }, + "rulesExport": { + "message": "Ekspor ke berkas…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Daftar aturan filter dinamis Anda.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Aturan sintaksis: sumber tujuan jenis tindakan (dokumentasi lengkap).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Urutkan:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipe aturan", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Sumber", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Tujuan", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Arahan situs tepercaya menentukan halaman web mana yang uBlock Origin harus dinonaktifkan. Satu entri per baris.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Impor dan tambahkan…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Ekspor…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Jenis", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Semua", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Di balik layar", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Tab saat ini", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Muat ulang konten tab", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Aktif/Nonaktifkan inspeksi DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Aktif/Nonaktifkan panel popup", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Pencatat log", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Kosongkan pencatat log", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Jeda pencatat log (buang semua data masuk)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Lanjutkan pencatat log", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Aktif/Nonaktifkan penyaringan pencatat log", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter konten pencatat log", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opsi filter pencatat log", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Bukan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "diblokir", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "diizinkan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "diubah", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "pihak ke-1", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "pihak ke-3", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detail", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Daftar filter", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Aturan", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteks", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Konteks induk", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Hubungan", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Jenis", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Aturan URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteks:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Jenis:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filter statis", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} permintaan jaringan dari {{type}} {{br}}yang alamat URLnya cocok dengan {{url}} {{br}}dan yang berasal dari {{origin}},{{br}}{{importance}} ada pengecualian penyaring yang cocok.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokir", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Izinkan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "jenis “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "semua jenis", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "dari “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "dari manapun", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "kecuali ketika", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "meskipun", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filter statis {{filter}} ditemukan di dalam:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Filter statis tidak dapat ditemukan di semua daftar filter yang aktif saat ini", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Entri pencatat log yang tidak memenuhi ketiga kondisi di bawah akan otomatis dibuang:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Pertahankan entri sejak {{input}} menit terakhir", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Pertahankan maksimal {{input}} pemuatan laman per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Pertahankan maksimal {{input}} entri per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Gunakan {{input}} baris per entri dalam mode perluasan vertikal", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sembunyikan kolom:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Waktu", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/aturan", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteks", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Relasi", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Daftar", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Biasa", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Buka", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Buat laporan baru", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Temukan laporan serupa", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentasi", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Baca dokumentasi di uBlock/wiki untuk mempelajari semua fitur uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Pertanyaan dan dukungan", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Jawaban pertanyaan dan dukungan bantuan lainnya tersedia di subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Masalah filter/situs web rusak", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Laporkan masalah filter pada situs web ke pelacak masalah uBlockOrigin/uAssets. Membutuhkan akun GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Penting: Hindari menggunakan pemblokir sejenis bersamaan dengan uBlock Origin, karena mungkin akan mengakibatkan terjadinya masalah filter pada situs web tertentu.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: Pastikan filter Anda selalu yang terbaru. Pencatat log adalah utilitas utama untuk mendiagnosis masalah yang terkait dengan filter.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Laporan bug", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Laporkan masalah ekstensi uBlock Origin ke pelacak masalah uBlockOrigin/uBlock-issue. Membutuhkan akun GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informasi penyelesaian masalah", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Di bawah ini adalah informasi teknis yang mungkin berguna saat sukarelawan berusaha membantu memecahkan masalah Anda.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Penting: Informasi yang sifatnya privat dan sensitif disensor secara bawaan. Informasi yang disensor mungkin akan membuat proses memecahkan masalah semakin sulit.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Laporkan masalah filter", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Untuk menghindari membebani sukarelawan dengan laporan duplikat, harap verifikasi bahwa masalah tersebut belum dilaporkan.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Daftar filter diperbarui setiap hari. Pastikan masalah Anda belum teratasi dalam daftar filter terbaru.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifikasi bahwa masalah masih ada setelah memuat ulang halaman web yang bermasalah.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Alamat laman web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Laman web…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pilih entri --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Menampilkan iklan atau sejenisnya", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Memiliki overlay atau gangguan lainnya", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Mendeteksi uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Memiliki masalah terkait privasi", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Rusak saat uBlock Origin aktif", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Membuka tab atau jendela yang tidak diinginkan", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Beri label halaman web sebagai “TAUSB” (“Tidak Aman Untuk Saat Bekerja”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Sensor", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Batal sensor", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Kebijakan privasi", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Catatan perubahan", + "description": "" + }, + "aboutCode": { + "message": "Kode sumber (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Kontributor", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kode sumber", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Terjemahan", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Daftar filter", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependensi eksternal (kompatibel GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Daftar filter uBO sendiri dihosting secara gratis di CDN berikut:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN yang dipilih secara acak digunakan saat daftar filter perlu diperbarui", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Cadangkan ke berkas…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Pulihkan dari berkas...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Kembalikan ke pengaturan bawaan...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Semua pengaturan Anda akan ditimpa dengan data yang dicadangkan pada {{time}}, dan uBlock₀ akan memulai ulang.\n\nTimpa semua pengaturan yang ada dengan data cadangan?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Data tidak dapat dibaca atau tidak valid", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Semua pengaturan Anda akan dihapus, dan uBlock₀ akan memulai ulang.\n\nKembalikan uBlock₀ ke pengaturan bawaan?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Galat jaringan: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Tambah URL berikut ke ke daftar filter khusus Anda?\n\nJudul: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Berlangganan", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "semenit yang lalu", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} menit yang lalu", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "sejam yang lalu", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} jam yang lalu", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "sehari yang lalu", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} hari yang lalu", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Tampilkan Dasbor", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Tampilkan Pencatat Log", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "mati", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Halaman diblokir", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin telah mencegah halaman berikut dimuat:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Disebabkan oleh filter berikut", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "tanpa parameter", + "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": "Ditemukan di:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Kembali", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Tutup jendela ini", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Jangan ingatkan saya lagi tentang situs ini", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Nonaktifkan pemblokiran ketat untuk {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Sementara", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanen", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Lanjutkan", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Ekspor ke penyimpanan awan", + "description": "tooltip" + }, + "cloudPull": { + "message": "Impor dari penyimpanan awan", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Impor dari penyimpanan awan dan gabungkan dengan pengaturan saat ini", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nama perangkat ini:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Peringatan! Ubah pengaturan lanjutan berikut dengan risiko Anda sendiri.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Kirim", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Terapkan perubahan", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Urungkan", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokir elemen di dalam frame...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Berlangganan daftar filter...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Sementara izinkan elemen media besar", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Lihat kode sumber…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Ketik pintasan", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Aktif/Nonaktifkan bilah gulir", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Salin ke papan klip", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Pilih semua", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Aktif/Nonaktifkan filter tampilan", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Perlonggar mode pemblokiran", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Penyimpanan terpakai: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klik untuk memuat", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Galat: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Filter tidak dapat bekerja dengan baik saat peramban dimulai.\nMuat ulang halaman agar filter dapat bekerja dengan baik.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Entri ini harus menjadi yang terakhir", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/it/messages.json b/src/_locales/it/messages.json new file mode 100644 index 0000000..000b19e --- /dev/null +++ b/src/_locales/it/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finalmente, un blocker efficiente. Leggero sulla CPU e sulla memoria.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Attenzione! Ci sono delle modifiche non ancora salvate", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Attendi", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignora", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Opzioni", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtri di terze parti", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "I miei filtri", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Le mie regole", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Whitelist", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Scorciatoie", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Cronologia richieste di rete", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Info", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Supporto", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visualizzatore di risorse", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Impostazioni avanzate", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Click: disabilita/abilita uBlock₀ per questo sito.\n\nCtrl+click: disabilita uBlock₀ solo per questa pagina.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Click per disabilitare uBlock₀ per questo sito.\n\nCtrl+click per disabilitare uBlock₀ solo su questa pagina.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clicca per attivare uBlock₀ in questo sito.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "richieste bloccate", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "in questa pagina", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} o {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "dall'installazione", + "description": "English: since install" + }, + "popupOr": { + "message": "o", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloccati su questa pagina", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloccati dall'installazione", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domini connessi", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Apri la dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Accedi alla modalità elimina elemento", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Accedi alla modalità seleziona elemento", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Vai al registro delle richieste", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Segnala un problema su questo sito", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Disabilita/abilita il blocco di tutti i popup per questo sito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clicca per bloccare tutti i popup in questo sito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clicca per sbloccare tutti i popup in questo sito", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Abilita/disabilita il blocco di elementi multimediali di grandi dimensioni per questo sito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clicca per bloccare elementi multimediali di grandi dimensioni in questo sito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clicca per sbloccare elementi multimediali di grandi dimensioni in questo sito", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Disabilita/abilita filtraggio cosmetico per questo sito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Clicca per disattivare il filtraggio cosmetico in questo sito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Clicca per attivare il filtraggio cosmetico in questo sito", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Attiva o disattiva il blocco dei font remoti per questo sito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clicca per bloccare i font remoti in questo sito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clicca per sbloccare i font remoti in questo sito", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Clicca per disattivare JavaScript su questo sito", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Clicca per non disabilitare più JavaScript su questo sito", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Finestre pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elementi multimediali di grandi dimensioni", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtraggio cosmetico", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Caratteri remoti", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Altro", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Meno", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Regole globali: questa colonna è per le regole che si applicano a tutti i siti.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Regole locali: questa colonna è per le regole che si applicano solo al sito corrente.\nLe regole locali hanno la precedenza su quelle globali.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Clicca per rendere le tue scelte permanenti.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Clicca per annullare i cambiamenti.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Tutto", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Immagini", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Di terze parti", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Immagini/CSS di terze parti", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Script inline", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Script di proprietà del sito", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Script di terze parti", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Frame di terze parti", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domini connessi", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} di {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versione", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Crea", + "description": "English: Create" + }, + "pickerPick": { + "message": "Seleziona", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Esci", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Anteprima", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtri di rete", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtri cosmetici", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blocca elemento...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Nascondi lo spazio riservato agli elementi bloccati", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Visualizza il numero degli elementi bloccati sull'icona", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disabilita suggerimenti", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Usa il menu contestuale quando è possibile", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Adatto ai daltonici", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aspetto", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Colore di risalto personalizzato", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Abilita supporto salvataggio nel cloud", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Sono un utente avanzato (Lettura obbligatoria)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disattiva pre-fetching (per evitare qualsiasi connessione per le richieste di rete bloccate)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disattiva la revisione dei collegamenti ipertestuali", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Impedisci a WebRTC di rivelare l'indirizzo IP locale", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportamento predefinito", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Questi comportamenti predefiniti possono essere modificati per ogni singolo sito", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disabilita filtraggio cosmetico", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blocca elementi multimediali maggiori di {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blocca font remoti", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disattiva JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blocca i report CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Rivela i nomi canonici", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avanzate", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Caratteristiche adatte solo ad utenti tecnici.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "impostazioni avanzate", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Ultimo ripristino:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Ultimo backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtri di rete + {{cosmeticFilterCount}} filtri cosmetici da:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} usati su {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Aggiornamento automatico liste.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Aggiorna ora", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Elimina tutte le cache", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizza e applica filtri cosmetici", + "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 un fastidio visivo, e che non possono essere bloccati dai motori di filtraggio basati sulla richiesta di rete.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignora filtri cosmetici generici.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

I filtri cosmetici generici sono i filtri cosmetici intesi per essere applicati a tutti i siti Web.

Benché questi siano gestiti in modo efficiente da uBlock₀, i filtri cosmetici generici potrebbero contribuire a un carico elevato in termini di memoria e CPU su alcune pagine Web, in particolare quelle di notevoli dimensioni e a lunga scadenza.

L'attivazione di quest'opzione eliminerà il carico elevato in termini di memoria e CPU aggiunto alle pagine Web in conseguenza della gestione dei filtri cosmetici generici, e inoltre ridurrà l'impatto sulla memoria di uBlock₀ stesso.

È raccomandato abilitare quest'opzione sui dispositivi meno potenti.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Sospendi l'attività di rete finché non vengono caricate tutte le liste filtri", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista degli hosts bloccati", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Salva i cambiamenti", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Integrati", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Pubblicità", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domini con Malware", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Elementi fastidiosi", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multiuso", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regioni, lingue", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizzate", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importa...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Un URL per riga. URL non validi verranno silenziosamente ignorati.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Obsoleto.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "visualizza contenuto", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Ultimo aggiornamento: {{ago}}.\nClicca per forzare l'aggiornamento.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Aggiornamento in corso...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Un errore di rete ha impedito l'aggiornamento della risorsa.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Un filtro per riga. Un filtro può essere un semplice hostname, o un filtro compatibile con EasyList. Ogni riga che comincia con ! verrà ignorata.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Non aggiungere filtri da fonti non attendibili.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importa e aggiungi", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Esporta", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-filtri-statici-personalizzati_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Salva i cambiamenti", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Regole permanenti", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Regole temporanee", + "description": "header" + }, + "rulesRevert": { + "message": "Ripristina", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Applica", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Modifica", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Salva", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Annulla", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importa da file...", + "description": "" + }, + "rulesExport": { + "message": "Esporta in file", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-filtri-dinamici-personalizzati_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista delle regole di filtraggio dinamiche personalizzate.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintassi per le regole: sorgente destinazione tipo azione (documentazione completa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordina:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipo regola", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Fonte", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinazione", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Lista dei siti dove uBlock è disattivato. Un sito per ogni riga. Le voci non valide verranno silenziosamente ignorate.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importa e aggiungi", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Esporta", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Salva i cambiamenti", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Dominio", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtro", + "description": "English: Filter" + }, + "logAll": { + "message": "Tutte", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Dietro le quinte", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Scheda corrente", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Ricarica il contenuto della scheda", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Attiva o disattiva l'ispettore DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Attiva o disattiva il pannello popup", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin Wiki: Registro", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Pulisci il registro", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Metti in pausa il registro (scarta tutti i dati in arrivo)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Riattiva il registro", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Attiva o disattiva il filtraggio del registro", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtra il contenuto del registro", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opzioni di filtraggio del registro", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Non", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "movimentato", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloccato", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "Consentito", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificato", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Dominio attuale", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Di terze parti", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Dettagli", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtro", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Elenco dei filtri", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regola", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contesto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contesto di root", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Parte della richiesta", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Regola dell'URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contesto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtraggio statico", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} la richiesta di rete di {{type}} {{br}} il cui indirizzo URL corrisponde a {{url}} {{br}}e che proviene da {{origin}},{{br}}{{importance}} c'è una corrispondenza nel filtro delle eccezioni.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blocca", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permetti", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "qualsiasi tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "da “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "da ovunque", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "tranne quando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "anche se", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtro statico {{filter}} trovato in:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Non è stato possibile trovare il filtro statico in nessuno degli elenchi di filtri attualmente abilitati", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Le voci del registro che non soddisfano tutte e tre le condizioni seguenti verranno automaticamente scartate:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Mantieni le voci degli ultimi {{input}} minuti", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Conserva al massimo {{input}} caricamenti di pagina per scheda", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Conserva al massimo {{input}} voci per scheda", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Usa {{input}} righe per voce in modalità espansa verticale", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Nascondi colonne:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tempo", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtro/regola", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contesto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Parte della richiesta", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabella", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Semplice", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Apri", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Crea una nuova segnalazione", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Trova segnalazioni simili", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentazione", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Leggi la documentazione su uBlock/wiki per conoscere tutte le funzionalità di uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Domande e supporto", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Le risposte alle domande e ad altri tipi di supporto sono fornite sul subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemi dei filtri/siti malfunzionanti", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Segnala problemi dei filtri con siti specifici al tracciatore di bug uBlockOrigin/uAssets. Richiede un account GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Importante: Evita di utilizzare altre estensioni simili insieme a uBlock Origin, poiché ciò potrebbe causare problemi di filtro su specifici siti.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Suggerimenti: Assicurati che le tue liste di filtri siano aggiornate. Il registro è lo strumento principale per diagnosticare i problemi relativi ai filtri.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Segnalazione di errori", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Segnala problemi di uBlock Origin stesso al tracciatore di bug uBlockOrigin/uBlock-issue. Richiede un account GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informazioni sulla risoluzione dei problemi", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Di seguito sono riportate le informazioni tecniche che potrebbero essere utili quando i volontari stanno cercando di aiutarti a risolvere un problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Importante: Le informazioni potenzialmente private o sensibili vengono oscurate automaticamente. Le informazioni oscurate possono rendere più difficile risolvere un problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Segnala un problema con un filtro", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Gli elenchi dei filtri vengono aggiornati quotidianamente. Assicurati che il tuo problema non sia già stato risolto negli elenchi di filtri più recenti.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifica che il problema sussista ancora dopo aver ricaricato la pagina web problematica.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Indirizzo della pagina web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "La pagina web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "Scegli una voce", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Mostra pubblicità o avanzi di pubblicità", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ha sovrapposizioni o altri fastidi", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Rileva uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ha problemi relativi alla privacy", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Si rompe quando uBlock Origin è attivato", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Apre schede o finestre indesiderate", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Etichetta la pagina web come “NSFW” (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Oscura", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Non oscurare", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Codice di condotta sulla privacy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Codice sorgente (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Collaboratori", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Codice sorgente", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduzioni", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Liste filtri", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dipendenze esterne (GPLv3-compatibili):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Gli elenchi di filtri di uBO sono liberamente ospitati sui seguenti CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Un CDN selezionato a caso verrà utilizzato quando è necessario aggiornare un elenco di filtri", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Crea file di backup...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Ripristina configurazione", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Ripristina le impostazioni predefinite…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Tutte le impostazioni verranno sovrascritte utilizzando i dati di backup del {{time}} e uBlock sarà riavviato.\n\nSovrascrivere tutte le impostazioni esistenti con quelle del backup?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "I dati non possono essere letti o non sono validi", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Verranno cancellate tutte le impostazioni, e uBlock₀ sarà riavviato.\n\nResettare uBlock alle impostazioni di fabbrica?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Errore di rete: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Aggiungere il seguente URL alla tua lista dei filtri personalizzata?\n\nTitolo: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Sottoscrivi", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "un minuto fa", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuti fa", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "un'ora fa", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ore fa", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "un giorno fa", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} giorni fa", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Visualizza Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Visualizza registro richieste di rete", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "disattivato", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pagina bloccata", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ ha impedito alla seguente pagina di caricarsi:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "A causa del seguente filtro", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "senza parametri", + "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": "Trovato in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Torna indietro", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Chiudi questa finestra", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Non avvisarmi più per questo sito", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disabilita blocco assoluto per {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporaneamente", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentemente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Procedi", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Esporta nel cloud", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importa dal cloud", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importa da archivio cloud ed unisci con le impostazioni attuali", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nome di questo dispositivo:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Attenzione! Modifica queste impostazioni avanzate a tuo rischio e pericolo.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Invia", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Salva i cambiamenti", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Ripristina", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blocca elemento in un frame", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Iscriviti alla lista dei filtri...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Consenti temporaneamente elementi multimediali di grandi dimensioni", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Visualizza origine...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Digita una scorciatoia", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Attiva o disattiva il blocco dello scorrimento", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copia negli appunti", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Seleziona tutto", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Attiva/Disattiva filtri cosmetici", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Rilassa la modalità di blocco", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Spazio utilizzato: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clicca per caricare", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errori: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Non è stato possibile filtrare correttamente all'avvio del browser.\nRicaricare la pagina per garantire un filtraggio corretto", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json new file mode 100644 index 0000000..0293e53 --- /dev/null +++ b/src/_locales/ja/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "高効率ブロッカーついに登場。CPU とメモリーに負担をかけません。", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — ダッシュボード", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "警告! 保存していない変更があります", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "留まる", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "無視", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "設定", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "フィルターリスト", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "マイフィルター", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "マイルール", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "信頼するサイト", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "ショートカットキー", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ログ", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "uBlock₀ について", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "サポート", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — アセットビューアー", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "高度な設定", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ を無効にします。", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "クリックするとこのサイトで uBlock₀ を有効にします。", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "ブロックしたリクエスト数", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "このページ", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} 件 ({{percent}} %)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "インストールしてから", + "description": "English: since install" + }, + "popupOr": { + "message": "/", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "このページでのブロック数", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "インストールからのブロック数", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "接続したドメイン数", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ダッシュボードを開く", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "要素抹消モードに入る", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "要素選択モードに入る", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "ログを開く", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "このサイト上での問題を報告", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "このサイトに対するポップアップブロックの有効/無効をすべて切り替えます", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "クリックするとこのサイトのポップアップをすべてブロックします", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "クリックするとこのサイトのポップアップをすべてブロックしなくなります", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "このサイトに対する大きなメディア要素のブロックの有効/無効を切り替えます", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "クリックするとこのサイトの大きなメディア要素をブロックします", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "クリックするとこのサイトの大きなメディア要素をブロックしなくなります", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "このサイトに対する整形フィルタリングの有効/無効を切り替えます", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "クリックするとこのサイトでの整形フィルタリングを無効にします", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "クリックするとこのサイトでの整形フィルタリングを有効にします", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "このサイトに対するリモートフォントのブロックの有効/無効を切り替えます", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "クリックするとこのサイトのリモートフォントをブロックします", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "クリックするとこのサイトのリモートフォントをブロックしなくなります", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "クリックするとこのサイトの JavaScript を無効にします", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "クリックするとこのサイトの JavaScript は無効にならなくなります", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "ポップアップウィンドウ", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "大きなメディア要素", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "整形フィルタリング", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "リモートフォント", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "さらに表示", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "折りたたむ", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "グローバルルール: この列のルールはすべてのサイトに適用されます。", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "ローカルルール: この列のルールは現在のサイトだけに適用されます。\nローカルルールはグローバルルールを上書きします。", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "クリックすると変更を確定します。", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "クリックすると変更を元に戻します。", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "すべて", + "description": "" + }, + "popupImageRulePrompt": { + "message": "画像", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "サードパーティ", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "サードパーティ CSS/画像", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "インラインスクリプト", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "ファーストパーティスクリプト", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "サードパーティスクリプト", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "サードパーティフレーム", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "接続したドメイン数", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} 件 ({{total}} 件中)", + "description": "appears in popup" + }, + "popupVersion": { + "message": "バージョン", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "スクリプト", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "フレーム", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "作成", + "description": "English: Create" + }, + "pickerPick": { + "message": "選択", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "終了", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "プレビュー", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ネットワークフィルター", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "整形フィルター", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "クリック、Ctrl+クリック", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "要素をブロック...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ブロックした要素のプレースホルダーを非表示にする", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "ブロックしたリクエストの数をアイコンに表示する", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "ツールチップを無効にする", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "状況に合わせてコンテキストメニューを活用する", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "色覚多様性に配慮した色を使用する", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "外観", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "テーマ", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "カスタムアクセントカラー", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "クラウドストレージのサポートを有効にする", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "私は上級者です", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "先読み機能を無効にする (ブロックしているネットワークリクエストへの接続を完全に防ぐため)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "ハイパーリンクの監査を無効にする", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC によるローカル IP アドレスの漏洩を防ぐ", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "既定の動作", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "以下の既定の動作はサイトごとに上書きできます", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "整形フィルタリングを無効にする", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input}} KB より大きいメディア要素をブロックする", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "リモートフォントをブロックする", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript を無効にする", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP レポートをブロックする", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "CNAME クローキングを解除する", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "高度な設定", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "技術に詳しいユーザーのみを対象にした機能です", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "高度な設定", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "前回の復元:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "前回のバックアップ:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} 件のネットワークフィルター + {{cosmeticFilterCount}} 件の整形フィルター:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} 件中 {{used}} 件使用", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "フィルターリストを自動更新する", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "今すぐ更新", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "キャッシュをすべて削除", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "整形フィルターを解析して適用する", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "整形フィルターは、ネットワークリクエストに基づいたフィルタリングエンジンではブロックできない、邪魔とみなされる視覚的要素をウェブページ上から隠すという機能を果たします。", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "汎用整形フィルターを無視する", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "汎用整形フィルターとは、すべてのウェブサイトに適用することを目的とした整形フィルターです。このオプションを有効にすると、汎用整形フィルターを処理する結果としてウェブページに加わる、メモリーと CPU のオーバーヘッドが削減されます。\n\n性能の低い端末ではこのオプションを有効にすることをお勧めします。", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "フィルターリストをすべて読み込むまで、ネットワークアクティビティを停止する", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "ブロックしたホストの一覧", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "変更を適用", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "内製", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "広告", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "プライバシー", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "マルウェアドメイン", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "迷惑系", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "多目的", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "地域・言語", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "カスタム", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "インポート...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "1 行につき 1 つの URL です。無効な URL はそのまま無視されます。", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "期限切れです。", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "中身を表示します", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "最終更新: {{ago}}。\nクリックすると強制的に更新できます。", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "更新中...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ネットワークエラーが発生したため、リソースを更新できませんでした。", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "1 行につき 1 つのフィルターです。フィルターはただのホスト名でも EasyList と同じ形式でも構いません。! を先頭に付けた行は無視されます。", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "信頼できないソースからフィルターを追加しないでください。", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "インポートと追加", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "エクスポート", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "変更を適用", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "永続ルール", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "一時ルール", + "description": "header" + }, + "rulesRevert": { + "message": "元に戻す", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "確定", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "編集", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "保存", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "破棄", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ファイルからインポート...", + "description": "" + }, + "rulesExport": { + "message": "ファイルへエクスポート", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "動的フィルタリングルールの一覧です。", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "ルールの構文: 発信源 通信先 タイプ アクション (詳しい解説)", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "並べ替え:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "ルールの種類", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "発信源", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "通信先", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "[信頼するサイト] では uBlock Origin を無効にするウェブページを指定します。1 行につき 1 つです。", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "インポートと追加", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "エクスポート", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "変更を適用", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "タイプ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ドメイン", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "フィルター", + "description": "English: Filter" + }, + "logAll": { + "message": "すべて", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "バックグラウンド通信", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "現在のタブ", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "タブを再読み込みします", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM インスペクターの表示/非表示を切り替えます", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "ポップアップパネルの表示/非表示を切り替えます", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: ログ", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "ログを消去します", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "ログの出力を中断します (以後のデータはすべて破棄)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "ログの出力を再開します", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "ログの絞り込みの有効/無効を切り替えます", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "出力するログを絞り込む", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "ログ絞り込みオプション", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "除外", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "フィルタリングした", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "ブロックした", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "許可した", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "変更した", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "ファーストパーティ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "サードパーティ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "詳細", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "フィルター", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "フィルターリスト", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "ルール", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "コンテキスト", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "ルートコンテキスト", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "パーティ種別", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "タイプ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL ルール", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "コンテキスト:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "タイプ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "静的フィルター", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "一致する例外フィルター {{importance}}{{br}}{{url}} に URL アドレスが一致し{{br}}{{origin}} 発信された{{br}}{{type}} のネットワークリクエストを {{action}} する。", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "ブロック", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "許可", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "タイプ “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "任意のタイプ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}” から", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "任意のサイトから", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "がない場合", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "に関係なく", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "この静的フィルター {{filter}} を含むフィルターリスト:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "この静的フィルターは現在有効なフィルターリストのどれにも含まれていません", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "以下の 3 つの条件から 1 つでも外れたログは自動的に破棄されます:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "過去 {{input}} 分間のログを保持する", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "1 つのタブにつき最大 {{input}} ページの読み込みを保持する", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "1 つのタブにつき最大 {{input}} 件のログを保持する", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "展開表示モードではログ 1 件につき {{input}} 行で表示する", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "非表示にする列:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} 時刻", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} フィルター/ルール", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} コンテキスト", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} パーティ種別", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "リスト形式", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "表形式", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "テキスト形式", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown 形式", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "開く", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "新しい報告を作成", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "似た報告を探す", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "ドキュメント", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock Origin のすべての機能については uBlock/wiki のドキュメントをお読みください。", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "質問とサポート", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "質問への回答などのヘルプやサポートは /r/uBlockOrigin の subreddit で提供しています。", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "フィルターの問題 / ウェブサイトが正しく動作しない", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "特定のウェブサイトで起きるフィルターの問題は uBlockOrigin/uAssets の Issue トラッカーに報告してください。GitHub のアカウントが必要です。", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "重要: 似た機能を持つブロッカーを uBlock Origin と併用することは控えてください。特定のウェブサイトでフィルターの問題を引き起こすことがあります。", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "ヒント: フィルターリストが最新か確認しましょう。ログはフィルターに関連する問題の原因を調査するための第一のツールです。", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "バグ報告", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlock Origin 自体の問題は uBlockOrigin/uBlock-issue の Issue トラッカーに報告してください。GitHub のアカウントが必要です。", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "トラブルシューティング情報", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "以下の技術情報はボランティアが問題解決の手助けをするときに役立つことがあります。", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "重要: 個人情報や機密情報の可能性のある情報は既定で削除されます。情報が削除されたことによって問題解決が困難になることがあります。", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "フィルターの問題を報告する", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "重複した報告によってボランティアに負担をかけないように、問題がすでに報告されていないか確認してください。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "フィルターリストは毎日更新されます。まず最新のフィルターリストで問題が修正されていないか確認してください。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "問題のあるページを再読み込みしても問題がまだ残っているか確認してください。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "ウェブページのアドレス:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "ウェブページは...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- エントリーを選択する --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "広告またはその消し残りを表示します", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "オーバーレイなど邪魔なものがあります", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin を検出します", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "プライバシーに関連する問題があります", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin を有効にすると誤動作します", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "勝手にタブやウィンドウを開きます", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "ウェブページに“NSFW” (閲覧注意、“Not Safe For Work”) とラベルをつける", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "編集済にする", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "無編集にする", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "プライバシーポリシー", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "更新履歴", + "description": "" + }, + "aboutCode": { + "message": "ソースコード (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "貢献者", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "ソースコード", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "翻訳", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "フィルターリスト", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "外部依存関係 (GPLv3 と両立):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO の内製フィルターリストは以下の CDN に無料でホストしています:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "フィルターリストの更新が必要なときにはランダムに選択した CDN を使用します", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ファイルにバックアップ...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "ファイルから復元...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "初期設定にリセット...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "すべての設定を {{time}} にバックアップしたデータを使用して上書きした後、uBlock₀ が再起動します。\n\nバックアップデータを使用して既存の設定をすべて上書きしますか?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "データが無効、または読み込みができませんでした", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "すべての設定を削除した後、uBlock₀ が再起動します。\n\nuBlock₀ を初期設定にリセットしますか?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "ネットワークエラー: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "以下の URL をカスタムフィルターリストに追加しますか?\n\nフィルター名: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "購読", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 分前", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} 分前", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "1 時間前", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} 時間前", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "1 日前", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} 日前", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "ダッシュボードを表示", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "ログを表示", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "オフ", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "ブロックしたページ", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin は、 以下のサイトの読み込みを防止しました:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "以下のフィルターと一致したためです:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "このフィルターを含むフィルターリスト:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "戻る", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "このウィンドウを閉じる", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "今後このサイトに関する警告を表示しない", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}} への厳格なブロッキングを無効にする", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "一時的", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "永続的", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "続行する", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "クラウドストレージにエクスポートします", + "description": "tooltip" + }, + "cloudPull": { + "message": "クラウドストレージからインポートします", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "クラウドストレージからインポートして現在の設定に統合します", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "この端末の名前:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "警告! 以下の高度な設定の変更は自己責任で行ってください。", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "送信", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "変更を適用", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "元に戻す", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "バイト", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "フレーム内の要素をブロック...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "フィルターリストを購読...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "大きなメディア要素を一時的に許可", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "ソースを表示…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "ショートカットキーを入力", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "スクロールの同期/非同期を切り替えます", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "クリップボードにコピー", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "すべて選択", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "整形フィルタリングの有効/無効を切り替える", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "ブロッキングモードを緩和する", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "ストレージ使用量: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "クリックして読み込む", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "エラー: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "ブラウザー起動時に正しくフィルターできませんでした。\nページを再読み込みしてください。", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ka/messages.json b/src/_locales/ka/messages.json new file mode 100644 index 0000000..999553c --- /dev/null +++ b/src/_locales/ka/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "როგორც იქნა, მძლავრი და შედეგიანი რეკლამების შემზღუდავი. ზოგავს CPU-ს და მეხსიერებას.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — სამართავი დაფა", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "გაფრთხილება! ცვლილებები არ შენახულა", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "დარჩენა", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "უგულებელყოფა", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "პარამეტრები", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "სხვა ფილტრები", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "ჩემი ფილტრები", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "ჩემი წესები", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "გამონაკლისები", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "მალსახმობები", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — აღმრიცხავი", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "შესახებ", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "მხარდაჭერა", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — რესურსები", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "გაფართოებული პარამეტრები", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ მხოლოდ ამ გვერდზე გამოირთვება.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "დააწკაპეთ uBlock₀-ის ჩასართავად ამ საიტზე.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "შეზღუდული მოთხოვნები", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ამ გვერდზე", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ანუ {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "დაყენების შემდგომ", + "description": "English: since install" + }, + "popupOr": { + "message": "ანუ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "შეზღუდული ამ გვერდზე", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "შეზღუდული დაყენების შემდგომ", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "დაკავშირებული დომენები", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "სამართავის გახსნა", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "ნაწილების ამოჭრა", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "ნაწილების შერჩევა", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "აღმრიცხავის გახსნა", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "ამ საიტზე ხარვეზის მოხსენება", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "ამ საიტზე ყველა ამომხტომის შეზღუდვის ჩამრთველი", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "დააწკაპეთ ყველა ამომხტომი ფანჯრის შესაზღუდად ამ საიტზე", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "დააწკაპეთ, ამომხტომი ფანჯრების შეზღუდვის გასაუქმებლად ამ საიტზე", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "ამ საიტზე დიდი მედიაფაილების შეზღუდვის ჩამრთველი", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "დააწკაპეთ დიდი მედიაფაილების შესაზღუდად ამ საიტზე", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "დააწკაპეთ დიდი მედიაფაილების შეზღუდვის გასაუქმებლად ამ საიტზე", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "გარეგნული ნაწილების ფილტრის ჩამრთველი", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "დაწკაპეთ გარეგნული ნაწილების ფილტრის გასათიშად ამ საიტზე", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "დააწკაპეთ გარეგნული ნაწილების გასაფილტრად ამ საიტზე", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "ვებშრიფტების შეზღუდვის ჩართვა/გამორთვა ამ საიტზე", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "დააწკაპეთ ვებშრიფტების შესაზღუდად ამ საიტზე", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "დააწკაპეთ ვებშრიფტების შეზღუდვის გასაუქმებლად ამ საიტზე", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "დააწკაპეთ JavaScript-ის გასათიშად ამ საიტზე", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "დააწკაპეთ JavaScript-ზე შეზღუდვის მოსახსნელად ამ საიტზე", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "ამომხტომი ფანჯრები", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "დიდი მედიაფაილები", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "გარეგნული გაფილტვრა", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "ვებშრიფტები", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "ვრცლად", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "მოკლედ", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "გლობალური წესები: ეს სვეტი არის წესებისთვის, რომლებიც მოქმედებს ყველა საიტზე.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "ლოკალური წესები: ეს სვეტი არის წესებისთვის, რომლებიც მოქმედებს მხოლოდ მიმდინარე საიტზე.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "დაწკაპეთ ცვლილებების მუდმივად შენახვისთვის.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "დააწკაპუნეთ შეტანილი ცვლილებების გაუქმებისთვის.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "ყველა", + "description": "" + }, + "popupImageRulePrompt": { + "message": "სურათები", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "მესამე მხარე", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "მესამე მხრის css/ნახატები", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ხაზოვანი სკრიპტები", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1-ლი მხრის სკრიპტები", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "მე-3 მხრის სკრიპტები", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "მე-3 მხრის ჩარჩოები", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "დაკავშირებული დომენები", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}}-დან {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "ვერსია", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "სკრიპტი", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ჩარჩო", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "შექმნა", + "description": "English: Create" + }, + "pickerPick": { + "message": "გადარჩევა", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "გამოსვლა", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "შეთვალიერება", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ქსელის ფილტრები", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "გარეგნული ფილტრები", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl + დაწკაპუნება", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "ამ ნაწილის შეზღუდვა…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "შეზღუდული ნაწილების ადგილის შემავსებლის დამალვა", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "შეზღუდული მოთხოვნების რაოდენობის ჩვენება ხატულაზე", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "მინიშნებების გათიშვა", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "კონტექსტური მენიუს გამოყენება, როდესაც ეს ხელსაყრელია", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "ფერთა გასწორება დაქვეითებულად მხედველთათვის", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "იერსახე", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "თემა", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "სასურველი შეფერილობა", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "ღრუბლოვანი მეხსიერების მხარდაჭერის ჩართვა", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "მე ვარ გამოცდილი მომხმარებელი (აუცილებლად წასაკითხი)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "წინასწარი ჩატვირთვის გათიშვა (კავშირის არიდება ქსელის შეზღუდული მოთხოვნებისთვის)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "ბმულებით სარგებლობაზე თვალყურის დევნების არიდება", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC-სთვის ხელის შეშლა შიდა IP მისამართის გაჟონვაში", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "ნაგულისხმევი მითითებები", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "ეს ნაგულისხმევი მითითებები შესაძლებელია შეიცვალოს ცალკეული საიტისთვის", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "გარეგნული ნაწილების ფილტრის გათიშვა", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "მედიაფაილების შეზღუდვა, რომლებიც აჭარბებს {{input:number}} კბაიტს", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "ვებშრიფტების შეზღუდვა", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript-ის გათიშვა", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP-მოხსენებების აკრძალვა", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "დადგენილი სახელების გამოაშკარავება", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "გაფართოებული", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "შესაძლებლობები მხოლოდ ტექნიკური მომხმარებლებისთვის", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "გაფართოებული პარამეტრები", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "ბოლო აღდგენა:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "ბოლო მარქაფი:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} ქსელის ფილტრი + {{cosmeticFilterCount}} გარეგნული ნაწილების ფილტრი:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}}-დან გამოიყენება {{used}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "ფილტრების წესების თვითგანახლება", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "ახლავე განახლება", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "მარაგის გასუფთავება", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "გარეგნული ნაწილების ფილტრების დამუშავება და გამოყენება", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "გარეგნული ფილტრები, ძირითადად, იმ ხილული ნაწილების დასამალად გამოიყენება ვებგვერდზე, რომელთაც ქსელის მოთხოვნაზე დაფუძნებული ფილტრები ვერ ზღუდავს.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "გარეგნული საერთო ფილტრების უგულებელყოფა", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "გარეგნული საერთო ფილტრები ისეთი ფილტრებია, რომლებიც ყველა ვებსაიტზე მოქმედებს. ამ პარამეტრის ჩართვით კი თავიდან აიცილებთ გარეგნული საერთო ფილტრების შედეგად მეხსიერებისა და პროცესორის ზედმეტ დატვირთვას.\n\nამ პარამეტრის ჩართვა სასურველია სუსტ მოწყობილობებზე.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "ქსელის მოქმედებების გადავადება ყველა ფილტრის ჩატვირთვამდე", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "ცვლილებების ასახვა", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "ჩაშენებული", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "რეკლამები", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "პირადულობა", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "მავნე დომენები", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "შემაწუხებელი შიგთავსი", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "უნივერსალური", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "რეგიონები, ენები", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "საკუთარი სიები", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "შემოტანა...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "თითოეული URL ცალკეულ ხაზზე. არამართებული URL-ბმულები უგულებელყოფილი იქნება გაუფრთხილებლად.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "მოძველებული", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "შიგთავსის ნახვა", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "ბოლო განახლება: {{ago}}.\nდააწკაპეთ ახლავე გასაახლებლად.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "ახლდება...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ქსელის შეცდომის შედეგად, შიგთავსის განახლება ვერ მოხერხდა.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "თითოეული ფილტრი ცალკეულ ხაზზე. ფილტრი შეიძლება იყოს საიტის უბრალო დასახელება ან Adblock Plus-სთან თავსებადი მითითებები. ხაზები ‘!’ თავსართით უგულებელყოფილი იქნება.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "ფილტრების არიდება არასანდო წყაროებიდან.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "შემოტანა და დამატება", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "შენახვა", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ჩემი-ublock-მუდმივი-ფილტრები_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "ცვლილებების ასახვა", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "მუდმივი წესები", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "დროებითი წესები", + "description": "header" + }, + "rulesRevert": { + "message": "დაბრუნება", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "მიბარება", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "შეცვლა", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "შენახვა", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "გაუქმება", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ფაილიდან შემოტანა...", + "description": "" + }, + "rulesExport": { + "message": "ფაილში შენახვა", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ჩემი-ublock-ცვალებადი-წესები_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "თქვენი ცვალებადი ფილტრების წესები.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "წესის აგებულება: წყარო დანიშნულება მოთხოვნის სახე მოქმედება (მასალები სრულად).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "დალაგება:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "წესის სახეობა", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "წყარო", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "დანიშნულება", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "გამონაკლისებში მითითებულ ვებგვერდებზე uBlock Origin გამოირთვება. თითო ჩანაწერი ცალკეულ ხაზზე.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "შემოტანა და დამატება", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "შენახვა", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ჩემი-ublock-გამონაკლისები_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "ცვლილებების ასახვა", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "სახეობა", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "დომენი", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "ფილტრი", + "description": "English: Filter" + }, + "logAll": { + "message": "ყველა", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "ფარული მოთხოვნები", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "მიმდინარე ჩანართი", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "ჩანართის შიგთავსის ხელახლა ჩატვირთვა", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM-დამკვირვებლის ჩამრთველი", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "ამომხტომი არეს ჩამრთველი", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin-ის ვიკი: აღმრიცხავი", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "აღმრიცხავის გასუფთავება", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "აღმრიცხავის შეჩერება (მიღებული მონაცემების მოცილება)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "აღრიცხვის გაგრძელება", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "აღმრიცხავის გამორჩევის ჩამრთველი", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "აღრიცხული ჩანაწერების გამორჩევა", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "აღრიცხულის გამორჩევის პარამეტრები", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "განურჩევლად", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "საგულისხმო", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "შეზღუდული", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "დაშვებული", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "ჩასწორებული", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "მონახულებული", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "გარეშე მხარის", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "ვრცლად", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ფილტრი", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "ფილტრების სია", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "წესი", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "კონტექსტი", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "ძირეული კონტექსტი", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "მხარე", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "სახეობა", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "მისამართი", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "ცვალებადი URL ფილტრები", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "კონტექსტი:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "სახეობა:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "მუდმივი ფილტრები", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{type}} ქსელის მოთხოვნების {{action}} {{br}}რომლის URL მისამართიც შეესაბამება ბმულს {{url}} {{br}}და რომლის წყაროცაა {{origin}},{{br}}{{importance}}, როცა არსებობს შესაბამისი გამონაკლისი.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "შეზღუდვა", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "დაშვება", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "„{{type}}“ სახის", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ნებისმიერი სახის", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "„{{origin}}“", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "ნებისმიერი", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "გარდა იმ შემთხვევისა", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "იმ შემთხვევაშიც კი", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "მუდმივი ფილტრი {{filter}} ნაპოვნია სიაში:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "მუდმივი ფილტრი {{filter}} ვერ მოიძებნა ამჟამად გამოყენებულ ფილტრებს შორის", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "აღრიცხული ჩანაწერი, რომელიც არ აკმაყოფილებს ქვემოთ მოცემულ სამივე პირობას, ავტომატურად ამოიშლება:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "ბოლო {{input}} წუთის ჩანაწერების დატოვება", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "არაუმეტეს {{input}} გვერდის ჩატვირთვის დატოვება თითოეულ ჩანართზე", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "არაუმეტეს {{input}} ჩანაწერის დატოვება თითოეულ ჩანართში", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "თითოეული ჩანაწერისთვის {{input}} ხაზის გამოყენება, შვეულად ჩამოშლის რეჟიმში", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "სვეტების დამალვა:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} დრო", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} ფილტრი/წესი", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} კონტექსტი", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} მხარე", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "სია", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "ცხრილი", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "მარტივი", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "გაფორმებული", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "გახსნა", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "შექმენით ახალი მოსხენება", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "იპოვეთ მსგავსი მოხსენებები", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "მასალები", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "დამატებითი მასალებისთვის იხილეთ uBlock/wiki, რომ უკეთ გაეცნოთ uBlock Origin-ის შესაძლებლობებს.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "შეკითხვები და დახმარება", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "კითხვებზე პასუხისა და სხვა სახის მხარდაჭერის მისაღებად ეწვიეთ Reddit-განყოფილებას /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "ფილტრის ხარვეზი/საიტი დაზიანდა", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "ცალკეულ საიტზე ფილტრების ხარვეზების მოსახსენებლად გამოიყენეთ uBlockOrigin/uAssets ხარვეზების აღსარიცხავი. დაგჭირდებათ GitHub-ანგარიში.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "ყურადღება: ეცადეთ, არ გამოიყენოთ სხვა მსგავსი დანიშნულების შემზღუდავები uBlock Origin-თან ერთად, ვინაიდან წარმოშობს ფილტრების ხარვეზებს ცალკეულ საიტებზე.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "რჩევა: გადაამოწმეთ, რომ ფილტრები განახლებულია. აღმრიცხავი ხელსაწყო მთავარი საშუალებაა ფილტრების ხარვეზების გამოსავლენად.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "ხარვეზის მოხსენება", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "თავად uBlock Origin-ის ხარვეზების მოსახსენებლად, გამოიყენეთ uBlockOrigin/uBlock-issue ხარვეზების აღსარიცხავი. დაგჭირდებათ GitHub-ანგარიში.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "მონაცემები ხარვეზის მოსაგვარებლად", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "ქვემოთ მოცემულია ტექნიკური ინფორმაცია, რომელიც გამოადგებათ მოხალისეებს, უკეთ დაგეხმარონ ხარვეზის აღმოფხვრაში.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "გაითვალისწინეთ: მონაცემები, რომლებიც შესაძლოა პირადი და მნიშვნელოვანი იყოს, ნაგულისხმევად იკვეცება. ამასთანავე, შეკვეცილი ინფორმაციით სავარაუდოდ გართულდება ხარვეზის გამოსწორება.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "ფილტრის ხარვეზის მოხსენება", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "მოხალისეები რომ არ მოცდნენ ერთნაირი მოსხენებების ნახვით, გთოხვთ გადაამოწმოთ, უკვე ხომ არაა გაგზავნილი საჩივარი ამ ხარვეზზე.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "ფილტრთა სიები ახლდება ყოველდღე. გადაამოწმეთ, ხარვეზი ხომ არ გამოსწორებულა უახლეს სიებში.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "შეამოწმეთ, გაახლებით ხომ არ გამოსწორდა ხარვეზიანი ვებგვერდი. ", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "ვებგვერდის მისამართი", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "ვებგვერდი...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- შეარჩიეთ --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "აჩვენებს რეკლამებს ან მის ნარჩენებს", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "ადებს შემაწუხებელ შრეებსა და მისთანებს", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "ამჩნევს, რომ uBlock Origin ჩართულია", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": " პირადულობის დაცვის ხარვეზებითაა", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "ფუჭდება, როცა uBlock Origin ჩართულია", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "ხსნის არასასურველ ჩანართებს ან ფანჯრებს", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "გვერდი მოინიშნოს, როგორც „NSFW“ („შეუსაბამო“)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "შეკვეცილი", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "შეუკვეცელი", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "პირადულობის დებულება", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "ცვლილებათა ჟურნალი", + "description": "" + }, + "aboutCode": { + "message": "წყაროს კოდი (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "მოხალისეები", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "პირველწყარო კოდი", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "თარგმანები", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "ფილტრების სიები", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "ცალკეული დაქვემდებარებული პროექტები (GPLv3-თან თავსებადი):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO-ს კუთვნილი ფილტრები ღიადაა განთავსებული შემდეგ CDN-ებზე:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN შეირჩევა შემთხვევითობით ფილტრების განახლების დროს", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ფაილში დამარქაფება", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ჩემი-ublock-მარქაფი_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "აღდგენა ფაილიდან...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "ნაგულისხმევ პარამეტრებზე დაბრუნება...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "თქვენს ყველა პარამეტრს გადაეწერება {{time}} დროინდელი დამარქაფებული მონაცემები და uBlock₀ გაეშვება ხელახლა.\n\nნამდვილად გსურთ არსებული პარამეტრების დამარქაფებული მონაცემებით ჩანაცვლება?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "მონაცემები ვერ იკითხება, ან დაზიანებულია", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "თქვენ მიერ მითითებული ყველა პარამეტრი წაიშლება და uBlock₀ გაეშვება ხელახლა.\n\nნამდვილად გსურთ uBlock₀-ის ნაგულისხმევ პარამეტრებზე დაბრუნება?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "ქსელის შეცდომა: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: გსურთ შემდეგი URL ბმულის საკუთარ ფილტრის წესებში ჩამატება?\n\nდასახელება: „{{title}}“\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "გამოწერა", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ერთი წუთის წინ", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} წუთის წინ", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ერთი საათის წინ", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} საათის წინ", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ერთი დღის წინ", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} დღის წინ", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "ხელსაწყოების გვერდის ჩვენება", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "აღრიცხვის ჩვენება", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "გამორთული", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "გვერდი შეიზღუდა", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin-მა შეზღუდა მოცემული გვერდის ჩატვირთვა:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "მოცემული ფილტრიდან გამომდინარე", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "პოვნა:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "უკან დაბრუნება", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "ფანჯრის დახურვა", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "მომავალში გაფრთხილების გარეშე ამ საიტზე", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "მკაცრი შეზღუდვის მოხსნა საიტისთვის: {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "დროებით", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "მუდმივად", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "მაინც გადასვლა", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "ღრუბლოვან საცავში შენახვა", + "description": "tooltip" + }, + "cloudPull": { + "message": "ღრუბლოვანი საცავიდან გადმოტანა", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "ღრუბლოვანი საცავიდან გადმოტანა და არსებულ პარამეტრებთან მისადაგება", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "ამ მოწყობილობის დასახელება:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "გაფრთხილება! გაფართოებული პარამეტრების ცვლილების შედეგებზე, თავად იქნებით პასუხისმგებელი.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "მიღება", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "ცვლილებების ასახვა", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "დაბრუნება", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "ბაიტი", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "ნაწილების შეზღუდვა ჩარჩოში...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "ფილტრის სიის გამოწერა...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "დიდი მედიაფაილების დროებით დაშვება", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "პირველწყარო კოდის ნახვა…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "მალსახმობის მითითება", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "ჩაკეტილად გადაადგილების ჩამრთველი", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "ასლის აღება", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "ყველას მონიშვნა", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "გარეგნული ფილტრის ჩამრთველი", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "მსუბუქი შეზღუდვის რეჟიმი", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "გამოყენებული მოცულობა: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "კბ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "მბ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "გბ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "დაწკაპეთ ჩასატვირთად", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "შეცდომა: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "სათანადოდ ვერ გაიფილტრა ბრაუზერის ჩართვისას.\nახლიდან გახსენით გვერდი უკეთ გასაფილტრად.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/kk/messages.json b/src/_locales/kk/messages.json new file mode 100644 index 0000000..9cf48a4 --- /dev/null +++ b/src/_locales/kk/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Жарнамаларды жақсы өшіретін Addon'дардың бірі. Компьютердің қуатың аз алады.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Орнату", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Сізде сақталмаған параметрлер бар!", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Қалу", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Өшіру", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Баптаулар", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "3-ші жақты сүзгілер", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Менің сүзгілерім", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Менің ережелерім", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Рұқсат тізімі", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Жапсырм-р", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Журналшы", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Осы туралы", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Қолдау", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Активтерді қарау", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Кеңейтілген баптаулар", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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\nТек осы бетте uBlock₀ өшіру үшін Ctrl+Басу.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Осы сайт үшін uBlock₀ қосу үшін басыңыз.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "сұраным блокталды", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "бұл парақта", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} немесе {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "орнатылғаннан бастап", + "description": "English: since install" + }, + "popupOr": { + "message": "немесе", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Жарнамалар жойылды", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Орнатудан бастап құлыптаулы", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Домендар қосылды", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "uBlock₀-ты орнату", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Элементтің режимін енгізу", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Элемент таңдау режиміне өту", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Журналды ашу", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Осы вебсайттағы мәселе жайлы хабарлау", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Осы сайт үшін барлық попаптарды бұғаттау", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Мына сайттағы барлық қалқымалы терезелерді бұғаттау үшін басыңыз", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Мына сайттағы барлық қалқымалы терезелерді бұғаттамау үшін басыңыз", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Мына сайттағы үлкен медиа элементтерді бұғаттауын қосу/сөндіру", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Мына сайттағы үлкен медиа элементтерді бұғаттауын қосу үшін басыңыз", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Мына сайттағы үлкен медиа элементтерді бұғаттауын өшіру үшін басыңыз", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Осы сайт үшін косметикалық сүзуді қосу/өшіру", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Мына сайт үшін косметикалық сүзуді өшіру үшін басыңыз", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Мына сайт үшін косметикалық сүзуді қосу үшін басыңыз", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Осы сайт үшін қашықтан қосылған қаріптерді қосу/өшіру", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Мына сайттағы қашықтан қосылған қаріптерді бұғаттау үшін басыңыз", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Мына сайттағы қашықтан қосылған қаріптерді бұғаттамау үшін басыңыз", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Осы сайт үшін JavaScript-ты өшіру үшін басыңыз", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Осы сайт үшін JavaScript-ты өшірмеу үшін басыңыз", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Қалқымалы терезелер", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "барлығы", + "description": "" + }, + "popupImageRulePrompt": { + "message": "суреттер", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3-ші жақты", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3-ші жақты css/суреттер", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Жасау", + "description": "English: Create" + }, + "pickerPick": { + "message": "Таңдау", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Шығу", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Алдын-ала қарау", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Шерту, Ctrl-шерту", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Элементті блоктау", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Update now", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Өзерістерді іске асыру", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Жарнамалар", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Жекелік", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "Қайтару", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Түзету", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Сақтау", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Елемеу", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Файлдан импорттау...", + "description": "" + }, + "rulesExport": { + "message": "Файлға экспорттау", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Экспорт", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Өзерістерді іске асыру", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Түрі", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Сүзгі", + "description": "English: Filter" + }, + "logAll": { + "message": "Барлығы", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Журналды кідірту (барлық кіріс деректерін алып тастау)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Журналды тоқтата тұру", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Журнал тіркеушісі сүзгісін қосу", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "сүзгі журналының мазмұны", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Журнал тіркесімін сүзу параметрлері", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Жоқ:", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "бұғату", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "рұқсаты", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1-ші тарап", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3-і тарап", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Егжей", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Сүзгі", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Сүзгілер тізімі", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Ереже", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Түбірлік контекст", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Көңілділік", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Түрі", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL ережесі", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Түрі:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статикалық сүзгі", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} қай URL мекен-жайы {{url}} {{br}} сәйкес келетін және {{Origin}}, {{br}} {{маңыздылығы) қай URL мекен-жайы сәйкес келетін {{type}} {{br}} желілік сұраулары сәйкес ерекше жағдай сүзгісі.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Бұғату", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Рұқсат ету", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Бастапқы код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Салымшылар", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Бастапқы код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Аудармашылар", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Тізімдерді сүзу", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Сыртқы тәуелділіктер (GPLv3 үйлесімді):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Файлға сақтық көшірме жасау", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Файлдан қалпына келтіру...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Әдепкі параметрлерге қайтару...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Барлық параметрлер {{time}} күні сақтық көшірмесі жасалған деректерді пайдаланып жазылады және uBlock₀ қайта іске қосылады.\n\nСақтық көшірме жасалған деректерді пайдаланып, барлық қолданыстағы параметрлерді қайта жазу керек пе?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Дата оқуға сай емес (жарамсыз)", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Барлық параметрлер жойылып, uBlock₀ қайта қосылады.\n\nUBlock₀ зауыттық параметрлерге қайтарылсын ба?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Желілік қате: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Келесі URL-ді өзіңіздің теңшелетін сүзгілер тізіміне қосыңыз?\n\nТақырып: «{{title}}»\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Жазылу", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "бір минут бұрын", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} минут бұрын", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "бір сағат бұрын", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} сағат бұрын", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "бір күн бұрын", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} күн бұрын", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Орнату-ды көрсету", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Logger-ді көрсету", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "сөнд.", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin келесі парақтың жүктелуіне жол бермеді:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Келесі сүзгіге байланысты:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Мында табылды:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Артқа", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Терезені жабу", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{Hostname}} үшін қатаң блоктауды өшіру", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Уақытша", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Тұрақты", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Бұлтты жадқа экспорттау", + "description": "tooltip" + }, + "cloudPull": { + "message": "Бұлт қоймасынан импорттау", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Бұлтты сақтау қоймасынан импорттаңыз және ағымдағы параметрлермен біріктіру", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Девайстың аты:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Ескерту! Өзіңіздің тәуекеліңізбен осы кеңейтілген параметрлерді өзгертіңіз.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Жіберу", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Өзгерістерді қолдану", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Қайтару", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байт", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Үлкен медиа элементтеріне уақытша рұқсат беру", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Жарлық теріңіз", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Құлыпталған айналдыруды қосу", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Аралық сақтағышқа көшіру", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Бөгеу режимі", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "{{value}} {{unit}} қолданылды.", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "КБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/kn/messages.json b/src/_locales/kn/messages.json new file mode 100644 index 0000000..567a8e5 --- /dev/null +++ b/src/_locales/kn/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "ಯುಬ್ಲಾಕ್", + "description": "extension name." + }, + "extShortDesc": { + "message": "ಕೊನೆಗೂ, ಒಂದು ದಕ್ಷ ನಿರ್ಬಂಧಕ. ಮಿತವಾದ ಸಿಪಿಯೂ ಹಾಗು ಮೆಮೊರಿ ಬಳಕೆ.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ - ಡ್ಯಾಶ್ಬೋರ್ಡ", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "ಎಚ್ಚರಿಕೆ! ನೀವು ಉಳಿಸದ ಬದಲಾವಣೆಗಳನ್ನು ಹೊಂದಿದ್ದೀರಿ", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "ಸೆಟ್ಟಿಂಗ್ಸ್", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "೩ನೇ ವ್ಯಕ್ತಿ ಶೋಧಕಗಳು", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "ನನ್ನ ಶೋಧಕಗಳು", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "ನನ್ನ ನಿಯಮಗಳು", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "ವೈಟ್ ಲಿಸ್ಟ್", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ಲಾಗರ್", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "ಕುರಿತು", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "ಸುಧಾರಿತ ಆಯ್ಕೆಗಳು", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "ಕ್ಲಿಕ್: ಈ ಜಾಲತಾಣಕ್ಕೆ ನಿಷ್ಕ್ರಿಯ/ಸಕ್ರಿಯಗೊಳಿಸಲು.\nಕಂಟ್ರೋಲ್ + ಕ್ಲಿಕ್: ಈ ಜಾಲತಾಣಕ್ಕೆ ಮಾತ್ರ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "ಬೇಡಿಕೆಗಳನ್ನು ತಡೆಹಿಡಿಯಲಾಗಿದೆ", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ಈ ಪುಟದಲ್ಲಿ", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ಅಥವಾ {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "ಅನುಸ್ಥಾಪಿಸಿದ ಈಚೆಗೆ", + "description": "English: since install" + }, + "popupOr": { + "message": "ಅಥವಾ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ಡ್ಯಾಶ್ಬೋರ್ಡ ತೆರೆಯಲು ಕ್ಲಿಕಿಸಿ", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "ಅಂಶ ಆಯ್ವಿಕೆ ಕ್ರಮಕ್ಕೆ ದಾಖಲಾಗಿ", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "ಲಾಗರ್ ತೆರೆಯಿರಿ", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "ಈ ಜಾಲತಾಣದ ಎಲ್ಲಾ ಪಾಪ್ಅಪ್ ಗಳ ನಿರ್ಬಂಧವನ್ನು ಟಾಗಲ್ ಮಾಡಿ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "ಈ ಜಾಲತಾಣಕ್ಕೆ ಕಾಸ್ಮೆಟಿಕ್ ಫಿಲ್ಟರಿಂಗನ್ನು ಟಾಗಲ್ ಮಾಡಿ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "ಈ ಜಾಲತಾಣಕ್ಕೆ ದೂರಸ್ಥ ಅಕ್ಷರಶೈಲಿಯ ನಿರ್ಬಂಧವನ್ನು ಟಾಗಲ್ ಮಾಡಿ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "ಎಲ್ಲಾ", + "description": "" + }, + "popupImageRulePrompt": { + "message": "ಚಿತ್ರಗಳು", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "೩ನೇ ವ್ಯಕ್ತಿ", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "೩ನೇ ವ್ಯಕ್ತಿ ಸಿಎಸ್ಸೇಸು/ಚಿತ್ರಗಳು", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ಒಳಸಾಲಿನ ಸ್ಕ್ರಿಪ್ಟುಗಳು", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "೧ನೇ ವ್ಯಕ್ತಿ ಸ್ಕ್ರಿಪ್ಟುಗಳು", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "೩ನೇ ವ್ಯಕ್ತಿ ಸ್ಕ್ರಿಪ್ಟುಗಳು", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "೩ನೇ ವ್ಯಕ್ತಿ ಫ್ರೇಮುಗಳು", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "ಸಂಪರ್ಕ ಹೊಂದಿರುವ ಡೊಮೈನ್ಗಳು", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} ರಲ್ಲಿ {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "ರಚಿಸಿ", + "description": "English: Create" + }, + "pickerPick": { + "message": "ಆಯ್ಕೆ", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "ತ್ಯಜಿಸಿ", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ನಿವ್ವಳ ಫಿಲ್ಟರುಗಳು", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "ಕಾಸ್ಮೆಟಿಕ್ ಫಿಲ್ಟರುಗಳು", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "ಕ್ಲಿಕ್, ಕಂಟ್ರೋಲ್-ಕ್ಲಿಕ್", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "ಭಾಗ ತಡೆಹಿಡಿಯಿರಿ", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ನಿರ್ಬಂಧಿಸಿದ ಭಾಗಗಳಿರುವ ಪ್ಲೇಸ್ಹೋಲ್ಡರ್ಸ್ ಮರೆಮಾಡಿ", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "ಬಣ್ಣ ಅಂಧತೆ ಉಪಯುಕ್ತ", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "ಶೋಧಕ ಪಟ್ಟಿಗಳನ್ನು ಸ್ವಯಂ ನವೀಕರಿಸಿ.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "ಈಗ ನವೀಕರಿಸಿ", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "ಬದಲಾವಣೆಗಳನ್ನು ಅನ್ವಯಿಸಿ", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "ಜಾಹಿರಾತು", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "ಗೌಪ್ಯತೆ", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "ಬಹುಪಯೋಗಿ", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "ಪ್ರದೇಶಗಳು, ಭಾಷೆಗಳು", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "ಇಚ್ಛೆಯ", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "ಹಳೆಯದಾಗಿದೆ", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "ಆಮದಿಸಿ ಸೇರ್ಪಡಿಸು", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "ರಫ್ತು", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "ಬದಲಾವಣೆಗಳನ್ನು ಅನ್ವಯಿಸಿ", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "ಶಾಶ್ವತ ನಿಯಮಗಳು", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "ತಾತ್ಕಾಲಿಕ ನಿಯಮಗಳು", + "description": "header" + }, + "rulesRevert": { + "message": "ಹಿಂತಿರುಗಿಸಿ", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "ಕಮಿಟ್", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "ಸಂಪಾದಿಸಿ", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "ಉಳಿಸು", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "ತ್ಯಜಿಸಿ", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "ಎಲ್ಲಾ", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "ನೀಡುಗರು", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ಒಂದು ನಿಮಿಷದ ಹಿಂದೆ", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} ನಿಮಿಷದ ಹಿಂದೆ", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ಒಂದು ತಾಸಿನ ಹಿಂದೆ", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ತಾಸಿನ ಹಿಂದೆ", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ಒಂದು ದಿನದ ಹಿಂದೆ", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} ದಿನದ ಹಿಂದೆ", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "ಹಿಂದೆ ಹೋಗಿ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "ಈ ವಿಂಡೋವನ್ನು ಮುಚ್ಚಿ", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "ತಾತ್ಕಾಲಿಕವಾಗಿ", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "ಶಾಶ್ವತವಾಗಿ", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "ಸಲ್ಲಿಸಿ", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "ಹಿಂತಿರುಗಿಸಿ", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "ಬೈಟ್ಗಳು", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ko/messages.json b/src/_locales/ko/messages.json new file mode 100644 index 0000000..a43e85c --- /dev/null +++ b/src/_locales/ko/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "이 부가 기능은 효율적인 차단기입니다. CPU와 메모리에 주는 부담이 적습니다.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — 대시보드", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "경고! 저장되지 않은 변경 사항이 있습니다", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "취소", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "무시", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "설정", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "필터 목록", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "내 필터", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "내 규칙", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "제외 목록", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "단축키", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — 로그", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "정보", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "지원", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset 뷰어", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "고급 설정", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀을 끕니다.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "클릭하여 이 사이트에서 uBlock₀ 을 켭니다.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "요청 차단됨", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "이 페이지에서", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}}개 / {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "설치된 이후", + "description": "English: since install" + }, + "popupOr": { + "message": "/", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "이 페이지에서 차단됨", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "설치 후 차단됨", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "도메인 연결됨", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "클릭하여 대시보드 열기", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "구성 요소 선택기 모드로 진입", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "구성 요소 선택기 모드로 진입", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "로그로 이동", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "이 사이트의 이슈 신고", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "이 사이트에서 팝업 차단 토글", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "클릭하여 이 사이트에서 모든 팝업을 차단합니다.", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "클릭하여 이 사이트에서 모든 팝업 차단을 해제합니다.", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "이 사이트에서만 적용되는 대형 미디어 구성요소 차단 기능을 켜고 끕니다.", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "클릭하여 이 사이트에서 대용량의 미디어를 차단합니다.", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "클릭하여 이 사이트에서 대용량의 미디어 차단을 해제합니다.", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "이 사이트에서 시각적 필터링 토글", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "클릭하여 이 사이트에서 시각적 필터링을 끕니다.", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "클릭하여 이 사이트에서 시각적 필터링을 켭니다.", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "이 사이트에서 글꼴조정 차단 토글", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "클릭하여 이 사이트에서 외부 폰트를 차단합니다.", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "클릭하여 이 사이트에서 더 이상 외부 폰트를 차단하지 않습니다.", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "클릭하여 이 사이트에서 JavaScript 비활성화", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "클릭하여 이 사이트에서 JavaScript 활성화", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "팝업 창", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "큰 미디어 요소", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "표면 필터링", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "외부 폰트", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "자바스크립트", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "더보기", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "간단히", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "공용 규칙: 이 열은 모든 사이트에 적용되는 규칙 열 입니다.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "로컬 규칙: 이 열은 현재 사이트만 적용되는 규칙 열 입니다.\n로컬 규칙은 공용 규칙보다 우선권을 가지고 있습니다.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "클릭하여 변경사항을 저장합니다.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "클릭하여 변경사항 적용을 되돌립니다.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "전체", + "description": "" + }, + "popupImageRulePrompt": { + "message": "이미지", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "보조 필터", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "보조 CSS/이미지", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "인라인 스크립트", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "주 스크립트", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "보조 스크립트", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "보조 프레임", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "도메인 연결됨", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}}개 중 {{count}}개", + "description": "appears in popup" + }, + "popupVersion": { + "message": "버전", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "스크립트", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "프레임", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "생성", + "description": "English: Create" + }, + "pickerPick": { + "message": "선택", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "종료", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "미리보기", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "넷 필터", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "표면 필터", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "클릭, Ctrl-클릭", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "구성 요소 차단", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "차단된 구성 요소의 자리 감추기", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "차단된 요청 개수를 아이콘에 표시", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "툴팁 비활성화", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "컨텍스트 메뉴를 상황에 맞게 사용", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "색맹 최적화", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "표시", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "테마", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "사용자 지정 강조 색상", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "클라우드 저장소 활성화", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "고급 사용자 모드 (필수로 읽어보세요.)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "프리-페칭 비활성화 (차단된 네트워크 요청에 대해 모든 접속요청 방지)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "하이퍼링크 검사 비활성화", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC로부터 로컬 IP 주소 유출을 방지", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "기본 동작", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "이 기본 동작들은 사이트 별로 정의 할 수 있습니다.", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "표면 필터 비활성화", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input:number}} KB 보다 큰 미디어 구성요소 차단", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "글꼴 조종 차단", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript 비활성화", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP 보고서 차단", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "표준 이름 잠금 해제", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "고급", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "전문적인 사용자에게만 권장되는 설정입니다.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "고급 설정", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "최근 복원:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "최근 백업:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} 네트워크 필터 + {{cosmeticFilterCount}} 표면 필터:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}}개 중 {{used}}개 사용 중", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "필터 목록 자동 업데이트", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "지금 업데이트", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "모든 캐시 제거", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "표면 필터 분석 및 적용", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

이 옵션은 애드블록 플러스-호환 “구성 요소 감추기” 필터를 분석하고 적용하는 것을 활성화합니다. 이 필터는 기본적으로 웹 페이지에서 시각적 방해 요소들을 숨기는 역할을 하며, 네트워크 요청에 기반한 필터링 엔진에서 차단될 수 없습니다.

이 기능을 활성화하면 uBlock₀의 메모리 사용량이 증가합니다.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "전체적 표면 필터 무시", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

전체적 표면 필터들은 방문하는 모든 사이트에 적용하는 표면 필터입니다.

uBlock₀는 이를 효율적으로 적용하지만, 전체적 표면 필터들은 사이트의 크기와 유지시간에 따라 확연할 정도의 메모리 및 CPU 오버헤드를 줄 수 있습니다.

이 옵션을 활성화하면 전체적 표면 필터 적용으로 메모리 및 CPU 오버헤드를 제거하고, uBlock₀ 자체의 메모리 사용량도 줄입니다.

저전력 기기에 사용하는 것을 권장합니다.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "모든 필터 목록을 불러올 때까지 네트워크 일시 중단", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "차단된 호스트 목록", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "변경사항 적용", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Ublock₀ 제공", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "광고", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "개인정보", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "멀웨어 도메인", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "골칫거리", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "다목적", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "지역, 언어", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "사용자 지정", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "불러오기..", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "한 줄에 한 개의 URL을 입력하세요. 시작 부분이 ‘!’ 로 시작되면 무시됩니다. 존재하지 않는 URL은 자동으로 무시됩니다.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "구버전", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "내용 보기", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "마지막 업데이트: {{ago}}\n업데이트하려면 여기를 클릭하세요.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "업데이트 중...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "네트워크 오류로 인해 리소스가 업데이트되지 못했습니다.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "한 줄에 한 개의 필터를 입력하세요. 필터는 순수 호스트이름, 혹은 Adblock Plus-호환 필터가 될 수 있습니다. 시작 부분이 ‘!’ 로 시작되면 무시됩니다.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "신뢰할 수 없는 출처의 필터를 추가하지 마십시오.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "가져오기 및 추가하기", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "내보내기", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-고정필터_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "변경사항 적용", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "영구 규칙", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "임시 규칙", + "description": "header" + }, + "rulesRevert": { + "message": "되돌리기", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "제출", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "편집", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "저장", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "취소", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "파일로부터 불러오기...", + "description": "" + }, + "rulesExport": { + "message": "파일로 내보내기...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-동적규칙_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "동적 필터링 규칙 목록입니다.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "규칙 문법: 소스 페이지, 필터링 대상, 필터링할 타입, 적용할 조치 (전체 설명서).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "분류:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "규칙 유형", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "소스", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "목표", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "목록에 있는 호스트들은 uBlock₀에서 비활성화됩니다. 한 줄에 한 개씩 입력하세요. 존재하지 않는 호스트는 자동으로 무시됩니다.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "가져오기 및 추가하기", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "내보내기", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-제외목록_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "변경사항 적용", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "유형", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "도메인", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "필터", + "description": "English: Filter" + }, + "logAll": { + "message": "전체", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "숨겨진 구성 요소", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "현재 탭", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "탭 내용 새로고침", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM 속성 검사기 토글", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "팝업 패널 토글", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin 위키: 로거", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "로거 초기화", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "로거 일시중지 (들어오는 모든 데이터 무시)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "로거 일시중지 해제", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "로거 필터링 토글", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "필터 로그 항목", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "로거 필터링 옵션", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "제외", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "차단됨", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "허용됨", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "수정됨", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "퍼스트 파티", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "보조", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "상세정보", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "필터", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "필터 목록", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "규칙", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "컨텍스트", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "최상위 컨텍스트", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "파티", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "유형", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "동적 URL 필터링", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "페이지:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "유형:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "고정 필터링", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "네트워크 요청이 {{type}} 일 경우,{{br}}URL 주소가 {{url}} 와 일치하고{{br}}{{origin}} 에서 비롯 되었을 경우 {{action}} 한다.{{br}}그리고 다음 예외 필터와 일치할 경우 {{importance}} 한다.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "차단", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "허용", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "\"{{type}}\" 종류", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "모든 종류", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "전체", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "예외 처리", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "비 예외 처리", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "{{filter}} 에서 찾은 고정 필터:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "활성화된 정적 필터 목록에서 {{filter}}를 찾지 못했습니다", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "아래의 세 가지 조건을 모두 충족하지 않는 항목은 자동으로 삭제됩니다.", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "최근 {{input}} 분의 항목 유지", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "탭 당 최대 {{input}} 페이지로드 유지", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "탭 당 최대 {{input}} 항목 유지", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "수직 확장 모드에서 항목 당 {{input}} 줄 사용", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "숨긴 열:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} 시간", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} 필터/규칙", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} 컨텍스트", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} 파티", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "목록", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "테이블", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "일반", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "마크다운", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "열기", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "새 신고 생성", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "유사한 신고 탐색", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "문서", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock/wiki의 문서를 읽고 uBlock Origin의 모든 기능에 대해 알아보세요.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "질문 및 지원", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "질문에 대한 답변 및 기타 도움 지원은 /r/uBlockOrigin 서브레딧에서 제공됩니다.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "필터 문제/웹사이트가 망가짐", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "특정 웹사이트에서 발생하는 필터 이슈는 uBlockOrigin/uAssets 이슈 트래커에 보고해주세요. GitHub 계정이 필요합니다.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "중요: uBlock Origin과 유사한 목적의 다른 차단기를 함께 사용하지 마세요. 특정 웹사이트에서 필터 문제가 발생할 수 있습니다.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "팁: 필터 목록이 최신 버전인지 확인하세요. 로거는 필터 관련 문제를 진단하는 데에 사용되는 기본적인 도구입니다.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "오류 신고", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlock Origin 자체에 대한 이슈는 uBlockOrigin/uBlock-issue 이슈 트래커에 보고해주세요. GitHub 계정이 필요합니다.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "문제 해결 정보", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "다음은 자원 봉사자들이 문제를 해결하는 데에 도움을 줄 때 유용할 수 있는 기술적인 정보입니다.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "중요: 잠재적으로 개인 정보이거나 민감한 정보는 기본적으로 지워집니다. 정보가 지워지면 문제 해결이 더 어려워질 수도 있습니다.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "필터 이슈 신고", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "봉사자들이 중복 신고로 인해 부담을 겪지 않도록, 해당 이슈가 이미 신고되지는 않았는지 확인해주시기 바랍니다.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "필터 목록은 매일 갱신됩니다. 최신 필터 목록에서 문제가 이미 해결되진 않았는지 확인하세요.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "문제가 생긴 웹페이지를 새로고침해도 문제가 여전히 남아 있는지 확인하세요.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "웹 페이지의 주소:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "웹 페이지가...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- 주제 선택 --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "광고나 광고 흔적을 보여줍니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "오버레이나 기타 성가신 요소를 보여줍니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin 사용을 감지합니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "개인정보 보호 관련 이슈가 있습니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin을 켜면 깨집니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "원치 않는 탭이나 창을 엽니다", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "웹페이지를 \"NSFW\" (“Not Safe For Work”)로 분류", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "지우기", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "지우지 않기", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "개인정보취급방침", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "변경사항", + "description": "" + }, + "aboutCode": { + "message": "소스 코드 (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "기여자", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "소스 코드", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "번역", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "필터 목록", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "외부 종속성 (GPLv3 호환):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "아래 CDN에서 uBO의 필터 목록을 무료로 호스팅해 줍니다:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "필터 목록을 업데이트할 때 무작위로 선택된 CDN이 쓰입니다.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "파일로 백업하기", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-백업_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "파일로부터 복원하기...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "기본 설정으로 초기화...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "모든 설정은 {{time}}에 백업된 데이터에 덮어씌워지며, uBlock₀이 재시작됩니다.\n\n모든 존재하는 설정을 백업 데이터로 덮어씌우시겠습니까?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "데이터를 읽을 수 없거나 잘못되었습니다.", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "모든 설정이 제거되며, uBlock₀이 재시작됩니다.\n\nuBlock₀의 설정을 처음 설정으로 초기화하시겠습니까?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "네트워크 오류: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: 선택한 URL을 사용자 지정 필터 목록에 추가하시겠습니까?\n\n제목: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "구독", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 분 전", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} 분 전", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "1 시간 전", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} 시간 전", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "1 일 전", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} 일 전", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "대쉬보드 보기", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "로그 보기", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "끄기", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "페이지 차단됨", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin이 다음 페이지를 로드하는것을 방지했습니다:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "다음 필터로 인해 방지됨", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "다음 필터에서 찾음:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "돌아가기", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "이 창을 닫기", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "더 이상 이 사이트에 대해 경고 하지 않기", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}}에서 엄격 차단기능 끄기", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "이번만", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "항상", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "계속", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "클라우드 저장소로 내보내기", + "description": "tooltip" + }, + "cloudPull": { + "message": "클라우드 저장소로부터 가져오기", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "클라우드 저장소의 설정 불러오기 및 현재 설정과 통합", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "현재 기기의 이름:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "경고! 고급 옵션을 변경하여 발생하는 문제는 사용자에게 있습니다.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "제출", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "변경사항 적용", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "되돌리기", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "바이트", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "프레임 내 구성 요소 차단", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "필터 목록 구독...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "이번만 대형 미디어 구성요소 허용", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "소스 코드 보기…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "단축키를 입력하세요", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "스크롤 잠금 토글", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "클립보드에 복사", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "모두 선택", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "표면 필터 토글", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "차단 모드 완화", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "스토리지 사용량: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "불러오려면 클릭하기", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "오류: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "브라우저 시작 시 필터링을 제대로 수행할 수 없습니다.\n정확한 필터링을 위해 페이지를 새로고침해주세요.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ku/messages.json b/src/_locales/ku/messages.json new file mode 100644 index 0000000..647fec3 --- /dev/null +++ b/src/_locales/ku/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finally, an efficient blocker. Easy on CPU and memory.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warning! You have unsaved changes", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Settings", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filter lists", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "My filters", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "My rules", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trusted sites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "About", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Advanced settings", + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requests blocked", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "or", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Open the dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "all", + "description": "" + }, + "popupImageRulePrompt": { + "message": "images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Create", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pick", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quit", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Network filters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "advanced settings", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Update now", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Ads", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Export…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "All", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "a minute ago", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutes ago", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "an hour ago", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a day ago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} days ago", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Go back", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporarily", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanently", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "This device name:", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/lt/messages.json b/src/_locales/lt/messages.json new file mode 100644 index 0000000..3c2358f --- /dev/null +++ b/src/_locales/lt/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Pagaliau, efektyvus blokatorius, neapkraunantis nei procesoriaus, nei darbinės atminties.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Prietaisų skydas", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Dėmesio! Turite neišsaugotų pakeitimų", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Pasilikti", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignoruoti", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Nustatymai", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtrų sąrašai", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mano filtrai", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mano taisyklės", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Išimtys", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Nuorodos", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Žurnalas", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Apie", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Pagalba", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — resursų žiūryklė", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Sudėtingesni nustatymai", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Spustelėjimas: įjungti/išjungti uBlock₀ šiam puslapiui.\n\nVald+spustelėjimas: išjungti uBlock₀ tik šiam puslapiui.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Spustelėkite, kad išjungtumėte uBlock₀ šiai svetainei.\n\nVald+spustelėkite, kad išjungtumėte uBlock₀ tik šiam puslapiui.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Spustelėkite, kad įjungtumėte uBlock₀ šiai svetainei.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokuotos užklausos", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "šiame puslapyje", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} arba {{percent}} %", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "nuo įdiegimo", + "description": "English: since install" + }, + "popupOr": { + "message": "arba", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokuojama šiame puslapyje", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Užblokuota nuo įdiegimo", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Prijungti domenai", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Atverti prietaisų skydą", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Atverti elementų trynimo veikseną", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Atverti elementų parinkimo veikseną", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Atverti žurnalą", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Perjungti visų iškylančiųjų langų blokavimą šiame puslapyje", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Spustelėkite visų iškylančių langų blokavimui šioje svetainėje", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Spustelėkite visų iškylančių langų neblokavimui šioje svetainėje", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Perjungti didelių medijos elementų blokavimą šiame puslapyje", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Spustelėkite didelių medijos elementų blokavimui šioje svetainėje", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Spustelėkite didelių medijos elementų neblokavimui šioje svetainėje", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Perjungti kosmetinį filtravimą šiame puslapyje", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Spustelėkite kosmetinių filtrų išjungimui šioje svetainėje", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Spustelėkite kosmetinių filtrų įjungimui šioje svetainėje", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Perjungti nuotolinių šriftų blokavimą šiame puslapyje", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Spustelėkite nutolusių šriftų blokavimui šioje svetainėje", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Spustelėkite nutolusių šriftų neblokavimui šioje svetainėje", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Spustelėkite JavaScript išjungimui šioje svetainėje", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Spustelėkite JavaScript įjungimui šioje svetainėje", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Iškylantysis langas", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Dideli medijos elementai", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetinis filtravimas", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Nuotoliniai šriftai", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Daugiau", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mažiau", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globalios taisyklės: ši skiltis skirta visiems puslapiams taikomoms taisyklėms.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Spauskite pakeitimams padaryti pastoviais.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Spauskite pakeitimams atstatyti.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "visi", + "description": "" + }, + "popupImageRulePrompt": { + "message": "vaizdai", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "trečios šalies", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3-ios šalies CSS/paveikslai", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "įterptieji scenarijai", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1-os šalies scenarijai", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3-ios šalies scenarijai", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3-ios šalies rėmeliai", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "jungtasi prie sričių", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} iš {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versija", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "Skriptas", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Sukurti", + "description": "English: Create" + }, + "pickerPick": { + "message": "Parinkti", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Baigti", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Peržiūra", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Tinklo filtrai", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetiniai filtrai", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Spustelėjimas, Vald-spustelėjimas", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokuoti elementą", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Slėpti blokuotų elementų rezervuotą vietą", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Rodyti blokuotų užklausų skaičių piktogramoje", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Išjungti paaiškinimus", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Kur tinka, naudoti kontekstinį meniu", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Draugiškas neskiriantiems spalvų", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Išvaizda", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Įjungti nuotolinės saugyklos palaikymą", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Aš esu patyręs naudotojas (privaloma perskaityti)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Išjungti išankstinį gavimą (visiems blokuotų tinklo užklausų prisijungimams išvengti)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Išjungti saitų auditą", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Neleisti WebRTC atskleisti vietinio IP adreso", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Numatytoji elgsena", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Šios numatytosios elgsenos gali būti nustelbtos kiekvienam puslapiui atskirai", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Išjungti kosmetinius filtrus", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokuoti medijos elementus didesnius nei {{input}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokuoti nuotolinius šriftus", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Išjungti JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokuoti CSP ataskaitas", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Papildomi nustatymai", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "sudėtingesni nustatymai", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Paskutinis atkūrimas:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Paskutinė atsarginė kopija:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "Tinklo filtrų ({{netFilterCount}}) + kosmetinių filtrų ({{cosmeticFilterCount}}) iš:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "naudojama {{used}} iš {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatiškai atnaujinti filtrų sąrašus.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Atnaujinti dabar", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Valyti visus podėlius", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizuoti ir taikyti kosmetinius filtrus.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Ši nuostata įjungia Su Adblock Plus suderinamų „elementų slėpimo“ filtrų analizę ir taikymą. Šie filtrai iš esmės yra kosmetiniai, jie naudojami tinklalapio elementams, kurie yra laikomi vaizdiniais nepatogumais ir kurių negalima užblokuoti tinklo užklausomis paremtais filtrais, paslėpti.

Šios nuostatos įjungimas padidina uBlock₀ atminties naudojimą.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignoruoti daugybinius kosmetinius filtrus.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Daugybiniai kosmetiniai filtrai yra tokie kosmetiniai filtrai, kurie taikomi visoms svetainėms.

Nors uBlock₀ juos apdoroja efektyviai, daugybiniai kosmetiniai filtrai vis tiek gali prisidėti prie pamatuojamo atminties ir procesoriaus panaudojimo kai kuriose svetainėse, ypač didelėse ir ilgai gyvuojančiose.

Šio nustatymo įjungimas sumažins atminties ir procesoriaus naudojimą, kurį sukelia svetainės dėl daugybinių kosmetinių filtrų apdorojimo, bei sumažins bendrą uBlock₀ atminties naudojimą.

Rekomenduojama įjungti šį nustatymą mažiau galinguose įrenginiuose.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Blokuotų serverių sąrašas", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Taikyti pakeitimus", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Įtaisyti", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamos", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privatumas", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Kenksmingos sritys", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Erzinimas", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Univarsalūs", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regionai, kalbos", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Adaptuoti", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importuoti...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Vienas URL eilutėje. Neteisingi URL bus tyliai ignoruoti.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Pasenęs.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "peržiūrėti turinį", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Paskutinis atnaujinimas: {{ago}}.\nIeškoti atnaujinimo.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Atnaujinama...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Tinklo klaida sutrukdė atnaujinti resursą.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Vienas filtras eilutėje. Filtras gali būti paprastas serverio adresas, arba su Adblock Plus suderinamas filtras. Eilutės pradėtos ! bus ignoruotos.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importuoti ir papildyti", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksportuoti", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mano-ublock-statiniai-filtrai_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Taikyti pakeitimus", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Pastovios taisyklės", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Laikinos taisyklės", + "description": "header" + }, + "rulesRevert": { + "message": "Atstatyti", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Pritaikyti", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Redaguoti", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Įrašyti", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Atmesti", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importuoti iš failo...", + "description": "" + }, + "rulesExport": { + "message": "Eksportuoti į failą", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mano-ublock-dinaminės-taisyklės_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Dinaminių filtravimo taisyklių sąrašas.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Taisyklės sintaksė: šaltinis paskirtis tipas veiksmas (dokumentacija).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Rikiuoti pagal:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Taisyklės tipas", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Šaltinis", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Tikslas", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Baltojo sąrašo direktyvos nurodo, kurioms svetainėms uBlock Origin turėtų būti išjungtas. Vienas įrašas eilutėje. Neteisingos direktyvos bus tyliai ignoruotos ir užkomentuotos.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importuoti ir papildyti", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksportuoti", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mano-ublock-išimtys_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Taikyti pakeitimus", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipas", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Sritis", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtras", + "description": "English: Filter" + }, + "logAll": { + "message": "Visos", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Užkulisiai", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Dabartinė kortelė", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Įkelti kortelės turinį iš naujo", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Įjungti / išjungti DOM tyriklį", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Įjungti/išjungti iššokantį langą", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "„uBlock Origin“ viki: žurnalas", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Valyti žurnalą", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pristabdyti žurnalą (atmesti visus gaunamus duomenis)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Tęsti žurnalą", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Įjungti / išjungti žurnalo filtravimą", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtruoti žurnalo įrašus", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Žurnalo filtravimo nuostatos", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ne", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "užblokuota", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "leidžiama", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modifikuota", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1-oji šalis", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3-ioji šalis", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Išsamiau", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtras", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filtrų sąrašas", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Taisyklė", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekstas", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Šakninis kontekstas", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipas", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL taisyklė", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekstas:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipas:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statinis filtravimas", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} {{type}} tinklo užklausas, {{br}}kur URL adresas atitinka {{url}} {{br}}ir kurios kyla {{origin}},{{br}}{{importance}} yra atitinkantis išimties filtras.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokuoti", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Leisti", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "„{{type}}“ tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "bet kokio tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "iš „{{origin}}“", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "bet kur", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "išskyrus kai", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "net jei", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statinis filtras {{filter}} rastas:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statinis filtras {{filter}} nerastas jokiame dabar įjungtame filtrų sąraše", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggerio įrašai, kurie neatitinka visų trijų žemiau esančių sąlygų bus automatiškai panaikinami", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Išsaugoti įrašus ne senesnius kaip {{input}} min.", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Sąrašas", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Lentelė", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Neformatuotas", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Atidaryti", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacija", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privatumo politika", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Pakeitimų žurnalas", + "description": "" + }, + "aboutCode": { + "message": "Pirminis tekstas (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Talkininkai", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Programinis kodas", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Vertimai", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filtrų sąrašai", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Išorinės priklausomybės (suderinamos su „GPLv3“):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Padaryti atsarginę kopiją į failą", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "mano-ublock-atsarginė_kopija_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Atkurti iš failo...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Atkurti numatytuosius nustatymus...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Visi jūsų nustatymai bus perrašyti naudojant duomenis iš {{time}} atsarginės kopijos, o uBlock₀ bus perleistas.\n\nPerrašyti visus nustatymus naudojant atsarginės kopijos duomenis?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Nepavyko nuskaityti duomenų arba jie neteisingi", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Visi jūsų nustatymai bus pašalinti, o uBlock₀ bus perleistas.\n\nAtkurti uBlock₀ pradinius nustatymus?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Tinklo klaida: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Pridėti šį URL į jūsų adaptuotų filtrų sąrašą?\n\nPavadinimas: „{{title}}“\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Prenumeruoti", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "prieš minutę", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "prieš {{value}} min.", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "prieš valandą", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "prieš {{value}} val.", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "prieš dieną", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "prieš {{value}} d.", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Rodyti prietaisų skydą", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Rodyti žurnalą", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "išjungta", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Puslapis užblokuotas", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin neleido įkelti šio puslapio:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Dėl šio filtro", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "be parametrų", + "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": "Rasta:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Grįžti", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Užverti langą", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Išjungti griežtą {{hostname}} blokavimą", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Laikinai", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Negrįžtamai", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksportuoti į nuotolinę saugyklą", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importuoti iš nuotolinės saugyklos", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importuoti iš nuotolinės saugyklos ir sulieti su dabartiniais nustatymais", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Šio įrenginio vardas:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Įspėjimas! Keiskite šiuos sudėtingesnius nustatymus savo rizika.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Pateikti", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Taikyti pakeitimus", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Atstatyti", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "baitai", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Laikinai leisti didelius medijos elementus", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Įveskite nuorodą", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopijuoti į iškarpinę", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/lv/messages.json b/src/_locales/lv/messages.json new file mode 100644 index 0000000..6b62cc6 --- /dev/null +++ b/src/_locales/lv/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "Beidzot, efektīvs bloķētājs. Nepārslogo procesoru un atmiņu.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Vadības panelis", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Brīdinājums! Veiktās izmaiņas nav saglabātas", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Palikt", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorēt", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Iestatījumi", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Trešo pušu filtri", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mani filtri", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mani noteikumi", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Uzticamas vietnes", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Īsceļi", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Tīkla pieprasījumu žurnāls", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Par", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Atbalsts", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — līdzekļu skatītājs", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Papildu iestatījumi", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klikšķis: atslēgt/ieslēgt uBlock₀ šajā vietnē.\n\nCtrl+klikšķis: atslēgt uBlock₀ tikai šai lapai.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Noklikšķināt, lai atslēgtu uBlock₀ šajā vietnē.\n\nCtrl + klikšķis, lai atslēgtu uBlock₀ tikai šajā lapā.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klikšķināt, lai šai vietnei ieslēgtu uBlock₀.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "bloķētie pieprasījumi", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "šajā lapā", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} vai {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "kopš instalācijas brīža", + "description": "English: since install" + }, + "popupOr": { + "message": "vai", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Aizturētas šajā lapā", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Pavisam aizturētas", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Savienotie domēni", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Atvērt vadības paneli", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Ieiet elementa dzēšanas režīmā", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Ienākt elementa atlasītāju režīmā", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Atvērt pieprasījumu žurnālu", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Ziņot par nepilnību šajā vietnē", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Pārslēgt uznirstošo logu bloķēšanu šajā vietnē", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klikšķināt, lai šajā vietnē aizturētu uznirstošos logus", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klikšķināt, lai šajā vietnē vairs neaizturētu uznirstošos logus", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Pārslēgt lielu multivides elementu bloķēšanu šajā vietnē", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klikšķināt, lai šajā vietnē aizturētu lielas informācijas nesēju daļas", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klikšķināt, lai neaizturētu lielas informācijas nesēju daļas", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Pārslēgt kosmētisko filtrēšanu šajā vietnē", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klikšķināt, lai šajā vietnē atspējotu vizuālo aizturēšanu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klikšķināt, lai šajā vietnē iespējotu vizuālo aizturēšanu", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Pārslēgt ārējo fontu bloķēšanu šajā vietnē", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klikšķināt, lai šajā vietnē aizturētu attālos fontus", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klikšķināt, lai šajā vietnē vairs neaizturēt attālos fontus", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klikšķināt, lai šajā vietnē atspējotu JavaScript", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klikšķināt, lai šajā vietnē vairs neatspējotu JavaScript", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Uznirstošie logi", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Lielas informācijas nesēju daļas", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Vizuālā aizturēšana", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Attālinātie fonti", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Vairāk", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mazāk", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globālie ierobežojumi: šī kolonna paredzēta ierobežojumiem, kas attieksies uz visām mājaslapām.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Nokliķšķināt šeit, lai saglabātu izmaiņas.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klikšķināt, lai atceltu izmaiņas.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Visi", + "description": "" + }, + "popupImageRulePrompt": { + "message": "attēli", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "No trešajām pusēm", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "trešo pušu CSS/attēli", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline skripti", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party skripti", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party skripti", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party freimi", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "savienotie domēni", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} no {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versija", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skripts", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "rāmis", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Izveidot", + "description": "English: Create" + }, + "pickerPick": { + "message": "Izvēlēties", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Iziet", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Priekšskatījums", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Resursu filtri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Vizuālie filtri", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloķēt elementu…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Paslēpt vietu no bloķētā elementa", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Parādīt bloķēto pieprasījumu skaitu uz ikonas", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Atslēgt rīka padomus (tooltips)", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Izmantot konteksta izvēlni vajadzības gadījumā", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Daltoniķiem draudzīgs", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Izskats", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Izskats", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Pielāgota izcēluma krāsa", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktivizēt mākoņdatu glabāšanas atbalstu", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Es esmu pieredzējis lietotājs (Vēlams izlasīt)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Atslēgt pirmsielādi (lai novērstu bloķētus tīkla pieprasījumus)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Atslēgt tīmekļa saišu izsekošanu", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Novērst savas IP adreses noplūdi ar WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Noklusējuma darbība", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Šos uzstādījumus var mainīt katrai vietnei atsevišķi", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Atslēgt kosmētiskos filtrus", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Aizturēt informācijas nesēju daļas, kas ir lielākas par {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloķēt ārējos fontus", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Atspējot JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloķēt CSP atskaites", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Atslēpt kanoniskos nosaukumus", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Paplašināti", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Iespējas, kas piemērotas tikai tehniskiem lietotājiem.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "papildu iestatījumi", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Pēdējā atjaunošana veikta:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Pēdējā rezerves kopija:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} tīkla filtri + {{cosmeticFilterCount}} kosmētikas filtri no:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} izmanto no {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automātiski atjaunināt filtra sarakstus.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Atjaunināt tūlīt", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Visas kešatmiņas iztīrīšana", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Apstrādāt un izpildīt kosmētikas filtrus.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Šī opcija iespējo apstrādāt un ieviest ar Adblock Plus saderīgus “elementu paslēpšanas” filtrus. Šie filtri ir būtībā kosmētiski, tie kalpo, lai paslēptu tīmekļa lapu elementus, kas tiek uzskatīti par vizuālu traucējumu, un kas nevar būt nobloķēti ar pieprasījumu balstītu filtrēšanas programmu.

Šī līdzekļa iespējošana palielina uBlock₀ izmantojamās atmiņas daudzumu.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorēt vispārīgos kosmētiskos filtrus", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Vispārīgie kosmētikas filtri ir kosmētikas filtri, kurus paredzēts piemērot visās tīmekļvietnēs.

Lai gan uBlock ₀ darbojas efektīvi, vispārīgie kosmētikas filtri dažās tīmekļa lapās var ievērojami noslogot atmiņu un centrālo procesoru.

Šīs opcijas izmantošana samazinās vispārīgo kosmētikas filtru izmantotās atmiņas un procesora noslodzi kā arī samazinās paša uBlock₀ izmantoto atmiņu.

Ieteicams izmantot zemas veiktspējas ierīcēm.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Atlikt tīkla darbības, līdz visi aizturēšanas saraksti ir ielādēti.", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Bloķēto hostu saraksti", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Lietot izmaiņas", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Iebūvētie", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklāmas", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Konfidencialitāte", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Ļaundabīgo programmu domēni", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Traucējoši elementi", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Daudzfunkcionālie", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Reģionālie, valodas", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Lietotāja", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importēt…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Vienu URL katrā rindiņā. Rindiņas, kuras sākas ar ‘!’ tiks ignorētas. Nederīgs URL tiks ignorēts bez brīdinājuma.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Novecojis.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "skatīt saturu", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Pēdējo reizi atjaunināts: {{ago}}.\nNoklikšķiniet, lai atjauninātu.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Atjaunina…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Tīkla kļūda neļāva atjaunināt resursu.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Vienu filtru katrā rindā. Filtrs var būt vienkārši resursa adrese, vai ar Adblock Plus saderīgs filtrs. Rindiņas, kuras sākas ar ‘!’ tiks ignorētas.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nevajag pievienot filtrus no neuzticamiem avotiem.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importēt un pievienot", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksportēt", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Lietot izmaiņas", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Pastāvīgie noteikumi", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Pagaidu noteikumi", + "description": "header" + }, + "rulesRevert": { + "message": "Atgriezt", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Ieviest", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Rediģēt", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Saglabāt", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Atsacīties", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importēt no faila…", + "description": "" + }, + "rulesExport": { + "message": "Eksportēt uz failu", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Dinamisko filtrēšanas noteikumu saraksts.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Noteikumu sintakse: avots mērķis tips rīcība (pilna dokumentācija).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Kārtot:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Nosacījuma veids", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Avots", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Mērķis", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Saraksts ar interneta resursiem, kuriem tiks atslēgts uBlock Origin. Viens ieraksts katrā rindiņā. Nederīgi interneta resursu nosaukumi tiks ignorēti bez brīdinājuma.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importēt un pievienot", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksportēt", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Lietot izmaiņas", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tips", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domēns", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtrs", + "description": "English: Filter" + }, + "logAll": { + "message": "Viss", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Aizkulisēs", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Šī cilne", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Pārlādēt cilnes saturu", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Pārslēgt DOM pārlūku", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Pārslēgt uznirstošo paneli", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: žurnāls", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Iztīrīt žurnālu", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Apturēt žurnalēšanu (atmest visus ienākošos datus)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Atsākt žurnālus", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Pārslēgt žurnāla atlasi", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "žurnāla ierakstu filtrs", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Žurnāla atlases iespējas", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nav", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "aizturēts", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "atļauts", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "mainīts", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Pirmā puse", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Trešā puse", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Izklāsts", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtrs", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filtru saraksts", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Nosacījums", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteksts", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Saknes konteksts", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Ballīte", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Veids", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Vietnes URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dinamiskā URL filtrēšana", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteksts:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tips:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statiskā filtrēšana", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} tīkla pieprasījumiem {{type}} {{br}}kuru URL adrese satur {{url}} {{br}}un kas nāk no {{origin}},{{br}}{{importance}} ir atbilstošs izņēmumu filtrs.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloķēt", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Atļaut", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tips “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "jebkurš tips", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "no “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "no jebkuras vietas", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "izņemot gadījumus, kad", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "pat ja", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statiskais filtrs {{filter}} atrasts:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Nemainīgs aizturētājs netika atrasts nevienā no pašreiz iespējotajiem aizturēšanas sarakstiem", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Žurnāla ieraksti, kas neatbilsts visiem trim zemāk esošajiem nosacījumiem, tiks atmesti:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Saglabāt pēdējo {{input}} minūšu ierakstus", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Saglabāt ne vairāk kā {{input}} lapu ielādes cilnē", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Saglabāt ne vairāk kā {{input}} ierakstus cilnē", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Izmantot {{input}} rindas ierakstam stateniski izvērstā skatā", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Paslēpt kolonnas:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Laiks", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} aizturētājs/nosacījums", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteksts", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Ballīte", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Saraksts", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabula", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Vienkāršs", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Atvērt", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Izveidot jaunu ziņojumu", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Meklēt līdzīgus ziņojumus", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentācija", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Dokumentāciju var lasīt uBlock/wiki, lai uzzinātu par visām uBlock Origin iespējām.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Jautājumi un atbalsts", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Atbildes uz jautājumiem un cita veida atbalsts tiek sniegts /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Aizturēšanas nepilnības/nedarbojas vietne", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Par aizturēšanas nepilnībām noteiktās vietnēs var ziņot nepilnību uzskaitē uBlockOrigin/uAssets.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Svarīgi: ir jāizvairas no līdzīgu aizturētāju izmantošanas vienlaicīgi ar uBlock Origin, jo tas var radīt aizturēšanas kļūmes noteiktās vietnēs.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Ieteikums: jāpārliecinās, ka aizturēšanas saraksti ir atjaunināti. Žurnāls ir galvenais rīks, lai noteiktu ar aizturēšanu saistītas kļūmes.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Nepilnību ziņojums", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Par uBlock Origin nepilnībām jāziņo uBlockOrigin/uBlock-issue.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Kļūmju noteikšanas informācija", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Zemāk ir tehniskā informācija, kas var būt noderīga, kad brīvprātīgie mēģinās palīdzēt atrisināt sarežģījumus.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Svarīgi: iespējami privāta vai sensitīva informācija pēc noklusējuma tiek izņemta. Aizvākta informācija var apgrūtināt sarežģījuma atrisināšanu.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Ziņot par aizturētāja nepilnībām", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Aizturēšanas saraksti tiek atjaunināti ik dienu. Jāpārliecinās, vai nepilnība jau nav novērsta visjaunākajos aizturēšanas sarakstos.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Jāpārliecinās, vai nepilnība joprojām pastāv pēc tīmekļa vietnes ar sarežģījumiem pārlādēšanas.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Tīmekļa lapas adrese:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Tīmekļa lapa…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Atlasīt ierakstu --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Rāda reklāmas vai to paliekas", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ir pārklājumi vai citas neērtības", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Nosaka uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ir ar privātumu saistītas nebūšanas", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Salūzt, kad uBlock Origin ir iespējots", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Atver nevēlamas cilnes vai logus", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Iezīmēt tīmekļa lapu kā \"NSFW\" (\"Not Safe for Work (nav droša darbam))", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Izņemt", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Atdarīt izņemšanu", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privātuma nosacījumi", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Izmaiņu žurnāls", + "description": "" + }, + "aboutCode": { + "message": "Pirmkods (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Atbalstītāji", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Pirmkods", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tulkojumi", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filtru saraksti", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Ārējās atkarības (GPLv3 saderīgas):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO pašu aizturēšanas saraksti ir brīvi pieejami šajos SPT (satura piegādes tīklos):", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Nejauši izvēlēts SPT tiks izmantots, kad būs jāatjaunina aizturēšanas saraksts.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Saglabāt iestatījumus failā", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Atjaunot iestatījumus no faila...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Atgriezt noklusējuma iestatījumus…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Tiks pārrakstīti visi iestatījumi izmantojot datus, kas saglabāti {{time}}, un µBlock₀ tiks restartēts. Pārrakstīt visus esošos iestatījumus, izmantojot rezerves kopiju?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Datus nevar nolasīt vai tie nav derīgi", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Tiks atcelti visi Jūsu iestatījumi, un uBlock₀ tiks restartēts. \nAtjaunot rūpnīcas iestatījumus?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Tīkla kļūda: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Pievienot sekojošo URL Jūsu lietotāja filtru sarakstiem?\n\nNosaukums: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonēt", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "pirms minūtes", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "pirms {{value}} minūtēm", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "pirms stundas", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "pirms {{value}} stundām", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "vakar", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "pirms {{value}} dienām", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Parādīt Vadības paneli", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Parādīt tīkla pieprasījumu žurnālu", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "izslēgts", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Lapa aizturēta", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ novērsa šo lapu no ielādes:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Sakarā ar šādu filtru", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametriem", + "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": "Atrodas:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Doties atpakaļ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Aizvērt šo logu", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Vairs nebrīdināt par šo vietni", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Atslēgt satura bloķēšanu saitnei {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Pagaidu", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Paliekoši", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Turpināt", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksports uz mākoņdatu glabātuvi", + "description": "tooltip" + }, + "cloudPull": { + "message": "Imports no mākoņdatu glabātuves", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importēt no mākoņdatu glabātuves un apvienot ar pašreizējiem iestatījumiem", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Šīs ierīces nosaukums:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Brīdinājums! Mainiet šos iestatījumus uz savu atbildību.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Iesniegt", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Lietot izmaiņas", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Atgriezt", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "baiti", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Aizturēt elementu rāmī…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonēt filtru sarakstu…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Īslaicīgi atļaut lielos multivides elementus", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Skatīt pirmkodu…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Ievadīt saīsni", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Pārslēgt slēgto ritināšanu", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopēt starpliktuvē", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Atlasīt visu", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Pārslēgt kosmētisko atlasi", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Atslābinātais aizturēšanas režīms", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Izmantotais krātuves lielums: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klikšķināt, lai ielādētu", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Kļūdas: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Nevarēja pienācīgi aizturēt pārlūka palaišanas laikā.\nJāpārlādē lapa, lai nodrošinātu pienācīgu aizturēšanu.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Šim ierakstam ir jābūt pēdējam", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/mk/messages.json b/src/_locales/mk/messages.json new file mode 100644 index 0000000..4a38be4 --- /dev/null +++ b/src/_locales/mk/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Конечно, ефикасен блокер. Лесен на CPU и меморија.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Табла", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Предупредување! Имате неснимени промени", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Остани", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Игнорирај", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Подесувања", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Филтер листи", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Мои филтери", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Мои правила", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Верувани сајтови", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Кратенки", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Логови", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "За", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Click to enable uBlock₀ for this site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "побарувања блокирани", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на оваа страница", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} или {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "од инсталирање", + "description": "English: since install" + }, + "popupOr": { + "message": "или", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Блокирани на оваа страна", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Блокирани од инсталирање", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Домени конектирани", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Отворија ја таблата", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Влези во елемент западник мод", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Влези во елемент одбирач мод", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Отвоери го логерот", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Кликни да блокираш сите попапи на оваа страница", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Кликнете да го исклучите козметичките филтри на оваа страна", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Кликнете да го уклучите козметичките филтри на оваа страна", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Кликнете за да се блокира JavaScript на оваа страна", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Кликнете за да не се блокира JavaScript на оваа страна повеќе", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Поп-ап прозорец", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Големи медија елемнти", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Козметичко филтрирање", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Далечни фонтови", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Повеќе", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Помалку", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Глобални правила: оваа колона е за правила што се однесуваат на сите сајтови.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Локални правила: оваа колона е за правила што се однесуваат само на моменталниот сајт.\nЛокални правила надминуваат глобални правила.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Кликни да ги снимиш твоите промени трајно", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Кликни да ги повратиш твоите промени", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "сите", + "description": "" + }, + "popupImageRulePrompt": { + "message": "слики", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Трети лица", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Трети лица css/слики", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "внатрешни скрипти", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Самострани скрипти", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Други страни скрипти", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party фрејмови", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "домени конектирани", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} од {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Верзија", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Создади", + "description": "English: Create" + }, + "pickerPick": { + "message": "Одбери", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Исклучи", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Прегледај", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Мрежни филтери", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Козметичко филтрирање", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Клик, Контрол-клик", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Блокирај елемент...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Покажувај ја бројката на блокирани барања на иконата", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": " Исклучи ги советите", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Користи бои за слепоболност", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Уклучи поддршка за складирање во облак", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Јас сум напреден корисник (потребно читање)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Стандардно однесување", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Овие стандардни однесувања можат да се променат на база на сајт", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Исклучи козметичо филтрирање", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блокирај медија елементи поголеми од {{input}} КБ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блокирај далечни фонтови", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Исклучи JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "напредни подесувања", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Последно ресторирање:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Последно снимено:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} мрежни филтери + {{cosmeticFilterCount}} козметичи филтери од:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} користени од {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Авто-ажурирање филтер листи", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Апдејтирај сега", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Исчисти сите кешови", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Примени измени", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Вградено", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Реклами", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Приватност", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Домени на малвер", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Досадни", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Региони, јазици", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Custom", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Импортирај...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Еден УРЛ по линија. Неважечки УРЛи ќе бидат игнорирани во тишина.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Застарени.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ажурирање...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Внеси и додај", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Ескпортирај", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "мои-ублок-статични-филтери_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Постојани правила", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Привремени правила", + "description": "header" + }, + "rulesRevert": { + "message": "Поврати", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Изврши", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Уреди", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Сними", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Отфрли", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Внеси од фајл", + "description": "" + }, + "rulesExport": { + "message": "Изнеси во фајл", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "мои_ублок_динамични_правила_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Листа од твоите динамични филтер правила", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Подреди:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тип на правило", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Извор", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Внеси и додади", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Експортирај", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "моите_ублок_верувани_сајтови_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Примени ги измените", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тип", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "УРЛ", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Филтер", + "description": "English: Filter" + }, + "logAll": { + "message": "Сите", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Без табови", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Сегашен таб", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Исчисти логови", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Паузирај логови (отфрли влезни податоци)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Продолжи логирање", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Не", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "блокиран", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "Дозволен", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1ва-партија", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3та-партија", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Детали", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Филтер", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Филтер листа", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правило", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Партија", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тип", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "УРЛ", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "УРЛ правило", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст: ", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тип:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статичен филтер", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} мрежни барана од {{type}} {{br}} кои УРЛ адреси одговараат на {{url}} {{br}}кои доаѓаат од {{origin}},{{br}}{{importance}} има соодветен филтер за исклучоци.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блокирај", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Дозволи", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "тип \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "било кој тип", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "од \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "од било каде", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "освен кога", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "иако ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Време", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Филтер/правило", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} контекст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Партија", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Листа\n", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Табла", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Обично", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Маркдаун", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Дневник на промена", + "description": "" + }, + "aboutCode": { + "message": "Сорс Код (ГПЛв3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Соработници", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Сорс код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Преведувања", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Филтер листи", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "мој-ублок-бекап_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Мрежна грешка: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "пред една минута", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "пред {{value}} минути", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "пред саат време", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "пред {{value}} саати", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "пред еден ден", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "пред {{value}} дена", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Покажи Дешборд", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Покажи Логер", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "исклучи", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Најдено во:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Оди назад", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Затвори го прозорецот", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Повремено", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Трајно", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Примени ги измените", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Поврати", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "бајтови", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Внесете кратенка", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Копирај во табла со исечоци", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Релаксиран мод на блокирање", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Место вземеноЧ {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "КБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ml/messages.json b/src/_locales/ml/messages.json new file mode 100644 index 0000000..bd4452e --- /dev/null +++ b/src/_locales/ml/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "അവസാനം, ഒരു കാര്യക്ഷമമായ ബ്ലോക്കര്‍. ലഘുവായ CPU, memory ഉപയോഗം.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "യുബ്ലോക്ക്ഒ - ഡാഷ്ബോര്‍ഡ്", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "മുന്നറിയിപ്പ്! നിങ്ങൾക്ക് സംരക്ഷിക്കാത്ത മാറ്റങ്ങളുണ്ട്", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "താമസിക്കുക", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "അവഗണിക്കുക", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "ക്രമീകരണം", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "തേര്‍ഡ് പാര്‍ട്ടി ഫില്‍ട്ടറുകള്‍", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "എന്‍റെ ഫില്‍ട്ടറുകള്‍", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "എന്‍റെ നിയമങ്ങള്‍", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "വൈറ്റ് ലിസ്റ്റ്", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "കുറുക്കുവഴികൾ", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "യുബ്ലോക്ക്ഒ - നെറ്റ്‌വര്‍ക്ക് അപേക്ഷാ ലോഗ്", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "ഇതിനെ കുറിച്ച്", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "സഹായം ", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ - അസറ്റ് വ്യൂവർ", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "വിപുലമായ ക്രമീകരണങ്ങൾ", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "ക്ലിക്ക്: ഈ സൈറ്റില്‍ യുബ്ലോക്ക്ഒ ഡിസേബിള്‍/എനെബിള്‍ ചെയ്യാന്‍.\nCtrl + ക്ലിക്ക്: ഈ പേജില്‍ യുബ്ലോക്ക്ഒ ഡിസേബിള്‍/എനെബിള്‍ ചെയ്യാന്‍.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "ഈ സൈറ്റിനായി uBlock₀ പ്രവർത്തനരഹിതമാക്കാൻ ക്ലിക്കുചെയ്യുക.\n\nഈ പേജിൽ മാത്രം uBlock₀ പ്രവർത്തനരഹിതമാക്കാൻ Ctrl + ക്ലിക്കുചെയ്യുക.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "ഈ സൈറ്റിനായി uBlock₀ പ്രവർത്തനക്ഷമമാക്കാൻ ക്ലിക്കുചെയ്യുക.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "അപേക്ഷകള്‍ ബ്ലോക്ക്‌ ചെയ്യപ്പെട്ടു", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ഈ പേജില്‍", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} അല്ലെങ്കില്‍ {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "ഇന്‍സ്റ്റാളിനു ശേഷം", + "description": "English: since install" + }, + "popupOr": { + "message": "അല്ലെങ്കില്‍", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "ഈ പേജിൽ തടഞ്ഞു", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "ഇൻസ്റ്റാളുചെയ്‌തതിനുശേഷം തടഞ്ഞു", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "ഡൊമെയ്‌നുകൾ കണക്റ്റുചെയ്‌തു", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ഡാഷ്ബോര്‍ഡ് തുറക്കാന്‍ ക്ലിക്ക് ചെയ്യുക", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "ഘടക സപ്പർ മോഡ് നൽകുക", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "എലമെന്‍ഡ് പിക്കര്‍ മോഡില്‍ കടക്കുക", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "അപേക്ഷാ ലോഗിലേക്ക് പോകുക", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "ഈ വെബ്‌സൈറ്റിൽ ഉള്ള പ്രശ്നങ്ങൾ അറിയിക്കുക ", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "ഈ സൈറ്റിലെ എല്ലാ പോപ്‌അപ്പുകളും ബ്ലോക്ക്‌ ചെയ്യുന്നത് ടോഗ്ഗിള്‍ ചെയ്യുക", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "ഈ സൈറ്റിലെ എല്ലാ പോപ്പ്അപ്പുകളും തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "ഈ സൈറ്റിലെ എല്ലാ പോപ്പ്അപ്പുകളും മേലിൽ തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "ഈ സൈറ്റിനായി വലിയ മീഡിയ ഘടകങ്ങളുടെ തടയൽ ടോഗിൾ ചെയ്യുക", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "ഈ സൈറ്റിലെ വലിയ മീഡിയ ഘടകങ്ങൾ തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "ഈ സൈറ്റിലെ വലിയ മീഡിയ ഘടകങ്ങളെ മേലിൽ തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "ഈ സൈറ്റില്‍ സൗന്ദര്യ ഫില്‍ട്ടറുകള്‍ ടോഗ്ഗിള്‍ ചെയ്യുക", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "ഈ സൈറ്റിൽ കോസ്മെറ്റിക് ഫിൽ‌ട്ടറിംഗ് അപ്രാപ്‌തമാക്കാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "ഈ സൈറ്റിൽ കോസ്മെറ്റിക് ഫിൽ‌ട്ടറിംഗ് പ്രാപ്തമാക്കുന്നതിന് ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "ഈ സൈറ്റില്‍ റിമോട്ട് ഫോണ്ടുകള്‍ ബ്ലോക്ക് ചെയ്യുന്നത് ടോഗ്ഗിള്‍ ചെയ്യുക", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "ഈ സൈറ്റിലെ വിദൂര ഫോണ്ടുകൾ തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "ഈ സൈറ്റിൽ വിദൂര ഫോണ്ടുകൾ മേലിൽ തടയാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "ഈ സൈറ്റിൽ JavaScript അപ്രാപ്തമാക്കാൻ ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "ഈ സൈറ്റിൽ‌ ഇനിമുതൽ‌ JavaScript അപ്രാപ്‌തമാക്കുന്നതിന് ക്ലിക്കുചെയ്യുക", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "പോപ്പ്-അപ്പ് വിൻഡോകൾ", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "വലിയ മീഡിയ ഘടകങ്ങൾ", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "കോസ്മെറ്റിക് ഫിൽട്ടറിംഗ്", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "വിദൂര ഫോണ്ടുകൾ", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "ജാവാസ്ക്രിപ്റ്റ്", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "കൂടുതൽ", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "കുറവ്", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "ആഗോള നിയമങ്ങൾ: ഈ കോളത്തിലെ നിയമങ്ങൾ എല്ലാ സൈറ്റുകളിലും പ്രയോഗിക്കുന്ന നിയമങ്ങള് ആണ്.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "പ്രാദേശിക നിയമങ്ങൾ: ഈ കോളത്തിലെ നിയമങ്ങൾ നിലവിലെ സൈറ്റിലെ മാത്രം പ്രയോഗിക്കുന്ന.\nപ്രാദേശിക നിയമങ്ങൾ ആഗോള നിയമങ്ങൾ അതിലംഘിച്ച് പ്രവർത്തിക്കുന്നതായിരിക്കും.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "നിങ്ങളുടെ മാറ്റങ്ങൾ സ്ഥിരപെടുത്താന്‍ ക്ലിക്കുചെയ്യുക.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "നിങ്ങളുടെ മാറ്റങ്ങൾ പഴയപടി ആകാന്‍ ക്ലിക്കുചെയ്യുക.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "എല്ലാം", + "description": "" + }, + "popupImageRulePrompt": { + "message": "ചിത്രങ്ങള്‍", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "തേര്‍ഡ് പാര്‍ട്ടി", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "മൂന്നാം പാര്‍ട്ടി സിഎസ്എസ്/ ചിത്രങ്ങള്‍", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ഇന്‍ലൈന്‍ സ്ക്രിപ്റ്റുകള്‍", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "ഫസ്റ്റ് പാര്‍ട്ടി സ്ക്രിപ്റ്റുകള്‍", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "തേര്‍ഡ് പാര്‍ട്ടി സ്ക്രിപ്റ്റുകള്‍", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "തേര്‍ഡ് പാര്‍ട്ടി ഫ്രെയിമുകള്‍", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "കണക്റ്റ് ചെയ്യപ്പെട്ട ഡൊമൈനുകള്‍", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} ല്‍ നിന്നും {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "പതിപ്പ്", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "ക്രിയേറ്റ് ചെയ്യുക", + "description": "English: Create" + }, + "pickerPick": { + "message": "പിക്ക് ചെയ്യുക", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "പുറത്ത് കടക്കുക", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "പ്രിവ്യൂ", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "നെറ്റ് ഫില്‍ട്ടറുകള്‍", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "സൗന്ദര്യ ഫില്‍ട്ടറുകള്‍", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "ക്ലിക്ക്, Ctrl - ക്ലിക്ക്", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "എലമെന്‍ഡ് ബ്ലോക്ക് ചെയ്യുക", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ബ്ലോക്ക് ചെയ്യപ്പെട്ട എലമെന്‍ഡുകള്‍ക്ക് പകരമായുള്ള പ്ലയ്സ്ഹോള്‍ഡറുകള്‍ മറയ്ക്കുക", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "ഐക്കണില്‍ ബ്ലോക്ക് ചെയ്യപ്പെട്ട അപേക്ഷകളുടെ എണ്ണം കാണിക്കുക", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "ടൂള്ടിപ്പ് പ്രവർത്തനരഹിതമാക്കുക", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "ആവശ്യമായ ഇടങ്ങളില്‍ കോണ്‍ടെക്സ്റ്റ്‌ മെനു ഉപയോഗിക്കുക", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "വർണ്ണാന്ധതാ സൗഹാര്‍ദ്ദപരമായത്", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "ക്ലൌഡ് സ്റ്റോറെജ് സപ്പോര്‍ട്ട് എനേബിള്‍ ചെയ്യുക", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "ഞാന്‍ ഒരു അഡ്വാന്‍സ്ഡ് യൂസര്‍ ആണ് ( വായിക്കേണ്ടത്)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "പ്രീ-ഫെച്ചിംഗ് ഡിസേബിള്‍ ചെയ്യുക (ബ്ലോക്ക് ചെയ്ത നെറ്റ്‌വര്‍ക്ക് അപേക്ഷകള്‍ക്ക് കണക്ഷന്‍ ലഭിക്കുന്നത് തടയുന്നതിന്)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "ഹൈപര്‍ ലിങ്ക് ഓഡിറ്റിങ്ങ്/ബീക്കന്‍ ഡിസേബിള്‍ ചെയ്യുക", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "വെബ്‌ആര്‍ടിസി ലോക്കല്‍ ഐ പി അഡ്രസുകള്‍ ലീക്ക് ചെയ്യുന്നത് തടയുക", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "സ്ഥിര രീതി", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "ഓരോ സ്ഥിരസ്ഥിതി അടിസ്ഥാനത്തിലും ഈ സ്ഥിരസ്ഥിതി പെരുമാറ്റങ്ങൾ അസാധുവാക്കാനാകും", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "കോസ്മെറ്റിക് ഫിൽട്ടറിംഗ് പ്രവർത്തനരഹിതമാക്കുക", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "മീഡിയ ഘടകങ്ങളെക്കാൾ വലുത് തടയുക {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "വിദൂര ഫോണ്ടുകൾ തടയുക", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "ജാവാസ്ക്രിപ്റ്റ് അപ്രാപ്തമാക്കുക", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "സി‌എസ്‌പി റിപ്പോർട്ടുകൾ തടയുക", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "കാനോനിക്കൽ പേരുകൾ അൺലോക്ക് ചെയ്യുക", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "വിപുലമായ ക്രമീകരണങ്ങൾ", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "അവസാന റീസ്റ്റോര്‍:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "അവസാന ബാക്ക്അപ്:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} നെറ്റ്‌വര്‍ക്ക് ഫില്‍ട്ടറുകള്‍ + {{cosmeticFilterCount}} സൗന്ദര്യ ഫില്‍ട്ടറുകള്‍ ഇവിടെ നിന്നും:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} ല്‍ നിന്നും {{used}} ഉപയോഗിക്കുന്നു", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "ഫില്‍ട്ടര്‍ ലിസ്റ്റുകള്‍ ഓട്ടോ-അപ്ഡേറ്റ് ചെയ്യുക.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "ഇപ്പോള്‍ അപ്ഡേറ്റ് ചെയ്യുക", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "ക്യാഷ് ശുദ്ധീകരിക്കുക", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "ശുദ്ധീകരിച്ച് സൗന്ദര്യ ഫില്‍ട്ടറുകള്‍ എന്‍ഫോര്‍സ് ചെയ്യുക.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "ഒരു വിഷ്വൽ ശല്യമെന്ന് കരുതപ്പെടുന്നതും നെറ്റ്‌വർക്ക് അഭ്യർത്ഥന അടിസ്ഥാനമാക്കിയുള്ള ഫിൽട്ടറിംഗ് എഞ്ചിനുകൾക്ക് തടയാൻ കഴിയാത്തതുമായ ഒരു വെബ് പേജിലെ ഘടകങ്ങൾ മറയ്ക്കാൻ കോസ്മെറ്റിക് ഫിൽട്ടറുകൾ സഹായിക്കുന്നു.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "ജനറിക് കോസ്മെറ്റിക് ഫിൽട്ടറുകൾ അവഗണിക്കുക", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "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", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "മാറ്റങ്ങള്‍ അപ്ലേ ചെയ്യുക", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "അന്തർനിർമ്മിതം", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "പരസ്യങ്ങള്‍", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "സ്വകാര്യത", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "മാല്‍വെയര്‍ ഡൊമൈനുകള്‍", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "ശല്യപ്പെടുത്തലുകൾ", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "മള്‍ട്ടിപര്‍പ്പസ്", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "പ്രാദേശികം, ഭാഷകള്‍", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "കസ്റ്റം", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "ഇറക്കുമതി ചെയ്യുക ...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "ഒരു വരിയില്‍ ഒരു യുആര്‍എല്‍ എന്ന രീതിയില്‍. ‘!’ എന്നിവയില്‍ തുടങ്ങുന്ന വരികള്‍ ഇഗ്നോര്‍ ചെയ്യപ്പെടും. ഇന്‍വാലിഡ്‌ ആയ യുആര്‍എല്ലുകള്‍ നിശബ്ദമായി ഇഗ്നോര്‍ ചെയ്യപ്പെടും.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "കാലഹരണപ്പെട്ടത്", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ഉള്ളടക്കം കാണുക", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "അവസാന അപ്ഡേറ്റ്:{{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "അപ്‌ഡേറ്റുചെയ്യുന്നു ...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ഒരു നെറ്റ്‌വർക്ക് പിശക് ഉറവിടം അപ്‌ഡേറ്റുചെയ്യുന്നതിൽ നിന്ന് തടഞ്ഞു.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "ഒരു വരിയില്‍ ഒരു ഫില്‍റ്റര്‍ എന്ന രീതിയില്‍. ഒരു ഫില്‍റ്റര്‍ എന്നത്, ഹോസ്റ്റ് നെയിം, അല്ലെങ്കില്‍ ആഡ് ബ്ലോക്ക് പ്ലസ്‌-നോട്‌ കംപാറ്റബിള്‍ ആയ ഫില്‍റ്റര്‍ എന്നിവ ആകാം. ‘!’ എന്നിവയില്‍ ആരംഭിക്കുന്ന വരികള്‍ ഇഗ്നോര്‍ ചെയ്യപ്പെടും.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "ഇമ്പോര്‍ട്ടും കൂട്ടിചേര്‍ക്കലും ചെയ്യുക", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "എക്സ്പോര്‍ട്ട്‌", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "എന്‍റെ-യുബ്ലോക്ക്-സ്റ്റാറ്റിക്ക്-ഫില്‍ട്ടറുകള്‍_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "മാറ്റങ്ങള്‍ അപ്ലേ ചെയ്യുക", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "സ്ഥിര നിയമങ്ങള്‍", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "താല്‍ക്കാലിക നിയമങ്ങള്‍", + "description": "header" + }, + "rulesRevert": { + "message": "റിവേര്‍ട്ട്", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "കമ്മിറ്റ്", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "എഡിറ്റ്‌", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "സേവ്", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "കളയുക", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ഫയലില്‍ നിന്നും ഇമ്പോര്‍ട്ട് ചെയ്യുക...", + "description": "" + }, + "rulesExport": { + "message": "ഫയലിലേക്ക് എക്സ്പോര്‍ട്ട്‌ ചെയ്യുക", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "എന്‍റെ-യുബ്ലോക്ക്-ഡൈനാമിക്-നിയമങ്ങള്‍_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "താങ്കളുടെ ഡൈനാമിക് ഫില്‍റ്റര്‍ നിയമങ്ങളുടെ ലിസ്റ്റ്.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "നിയമത്തിന്‍റെ സിന്‍റ്റാക്സ്‌: സോര്‍സ് ഡെസ്റ്റിനേഷന്‍ ടൈപ്പ് ആക്ഷന്‍ ( മുഴുനീള പ്രമാണം).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "അടുക്കുക:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "റൂൾ തരം", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "ഉറവിടം", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "ലക്ഷ്യസ്ഥാനം", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "യുബ്ലോക്ക്ഒ ഡിസേബിള്‍ ചെയ്യപ്പെടേണ്ട ഹോസ്റ്റ് നെയിമുകള്‍. ഒരു വരിയില്‍ ഒരു എന്‍ട്രി എന്ന രീതിയില്‍ ചേര്‍ക്കുക. ഇന്‍വാലിഡ്‌ ഹോസ്റ്റ് നെയിമുകള്‍ നിശബ്ദമായി ഇഗ്നോര്‍ ചെയ്യപെടും.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "ഇമ്പോര്‍ട്ടും കൂട്ടിചേര്‍ക്കലും ചെയ്യുക", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "എക്സ്പോര്‍ട്ട്‌", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "എന്‍റെ-യുബ്ലോക്ക്-വൈറ്റ്ലിസ്റ്റ്_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "മാറ്റങ്ങള്‍ അപ്ലേ ചെയ്യുക", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "ടൈപ്പ്", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ഡൊമൈന്‍", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "യുആര്‍എല്‍", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "ഫില്‍ട്ടര്‍", + "description": "English: Filter" + }, + "logAll": { + "message": "എല്ലാം", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "സീനിനു പിന്നില്‍", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "നിലവിലെ ടാബ്", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "ടാബ് ഉള്ളടക്കം വീണ്ടും ലോഡുചെയ്യുക", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM ഇൻസ്പെക്ടർ ടോഗിൾ ചെയ്യുക", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "പോപ്പ്അപ്പ് പാനൽ ടോഗിൾ ചെയ്യുക", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock ഉറവിട വിക്കി: ലോഗർ", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "ലോഗർ മായ്‌ക്കുക", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "ലോഗർ താൽക്കാലികമായി നിർത്തുക (ഇൻകമിംഗ് ഡാറ്റയെല്ലാം ഉപേക്ഷിക്കുക)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "ലോഗർ അൺപോസ് ചെയ്യുക", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "ലോഗർ ഫിൽട്ടറിംഗ് ടോഗിൾ ചെയ്യുക", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "ലോഗ് എന്‍ട്രി ഫില്‍ട്ടര്‍ ചെയ്യുക", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "ലോഗർ ഫിൽട്ടറിംഗ് ഓപ്ഷനുകൾ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "അല്ല", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "തടഞ്ഞു", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "അനുവദനീയമാണ്", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "തിരുത്തപ്പെട്ടത്", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "ഒന്നാം കക്ഷി", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "തേര്‍ഡ് പാര്‍ട്ടി", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "വിശദാംശങ്ങൾ", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ഫിൽട്ടർ ചെയ്യുക", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "ലിസ്റ്റ് ഫിൽട്ടർ ചെയ്യുക", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "ഭരണം", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "സന്ദർഭം", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "റൂട്ട് സന്ദർഭം", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "പാർട്ടിത്വം", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "തരം", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL\n", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "ഡൈനാമിക് യുആര്‍എല്‍ ഫില്‍ട്ടറിങ്ങ്", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "കോണ്‍ടെക്സ്റ്റ്:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "ടൈപ്പ്:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "സ്റ്റാറ്റിക് ഫില്‍ട്ടറിങ്ങ്", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "URL {{action}} നെറ്റ്വർക്ക് അഭ്യർത്ഥനകൾ {{type}} {{br}} ഏത് URL വിലാസം പൊരുത്തപ്പെടുന്നു {{url}} {{br}}, ഒപ്പം {{origin}}, {{br}} {{importance}} an പൊരുത്തപ്പെടുന്ന ഒഴിവാക്കൽ ഫിൽട്ടർ ഉണ്ട്.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "ബ്ലോക്ക്‌ ചെയ്യുക", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "അനുവദിക്കുക", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "ടൈപ്പ് \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ഏതു ടൈപ്പും", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\"ല്‍ നിന്നും", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "എവിടെ നിന്നും", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "അങ്ങിനെ അല്ലെങ്കില്‍", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "എന്നിരുന്നാലും", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "സ്റ്റാറ്റിക് ഫില്‍ട്ടര്‍ {{filter}} ഇതില്‍ കണ്ടെത്തി:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "നിലവിൽ പ്രവർത്തനക്ഷമമാക്കിയ ഏതെങ്കിലും ഫിൽട്ടർ ലിസ്റ്റുകളിൽ സ്റ്റാറ്റിക് ഫിൽട്ടർ കണ്ടെത്താൻ കഴിഞ്ഞില്ല", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "ചുവടെയുള്ള മൂന്ന് നിബന്ധനകളും പാലിക്കാത്ത ലോഗർ എൻ‌ട്രികൾ സ്വപ്രേരിതമായി നിരസിക്കപ്പെടും:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "അവസാന {{input}} മിനിറ്റുകളിൽ നിന്ന് എൻട്രികൾ സംരക്ഷിക്കുക", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "ഒരു ടാബിന് പരമാവധി {{input}} പേജ് ലോഡുകൾ സംരക്ഷിക്കുക", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "ഒരു ടാബിന് പരമാവധി {{input}} എൻ‌ട്രികൾ സംരക്ഷിക്കുക", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "ലംബമായി വികസിപ്പിച്ച മോഡിൽ ഓരോ എൻട്രിക്കും {{input}} വരികൾ ഉപയോഗിക്കുക", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "നിരകൾ മറയ്‌ക്കുക:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} സമയം", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} ഫിൽട്ടർ / റൂൾ", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}}സന്ദർഭം", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} പാർട്ടിത്വം", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "പട്ടിക", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "മേശ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "പ്ലെയിൻ", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "മാർക്ക്ഡ .ൺ", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "പുതിയ റിപ്പോർട്ട് നിർമ്മിക്കുക", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "സമാനമായ റിപോർട്ടുകൾ കാണുക", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "സ്വകാര്യതാ നയം", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "മാറ്റങ്ങളുടെ ലോഗ്", + "description": "" + }, + "aboutCode": { + "message": "സോര്‍സ് കോഡ് (ജിപിഎല്‍വി3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "കോണ്‍ട്രിബ്യൂട്ടര്‍മാര്‍", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "സോഴ്സ് കോഡ്", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "വിവർത്തനങ്ങൾ", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "ലിസ്റ്റുകൾ ഫിൽട്ടർ ചെയ്യുക", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "ബാഹ്യ ഡിപൻഡൻസികൾ (GPLv3- അനുയോജ്യമാണ്):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO- യുടെ സ്വന്തം ഫിൽട്ടർ ലിസ്റ്റുകൾ ഇനിപ്പറയുന്നവയിൽ സ്വതന്ത്രമായി ഹോസ്റ്റുചെയ്യുന്നു CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "ഒരു ഫിൽട്ടർ ലിസ്റ്റ് അപ്ഡേറ്റ് ചെയ്യേണ്ടിവരുമ്പോൾ ക്രമരഹിതമായി തിരഞ്ഞെടുത്ത CDN ഉപയോഗിക്കുന്നു", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ഫയലിലേക്ക് ബാക്അപ്", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "എന്‍റെ-യുബ്ലോക്ക്-ബാക്ക്അപ്_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "ഫയലില്‍ നിന്നും റീസ്റ്റോര്‍ ചെയ്യുക...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "ഡീഫാള്‍ട്ട് സെറ്റിംഗ്സിലേക്ക് റീസ്റ്റോര്‍ ചെയ്യുക...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "{{time}}ല്‍ ബാക്ക്അപ് ചെയ്യപ്പെട്ട ഡേറ്റ ഉപയോഗിച്ച് താങ്കളുടെ എല്ലാ സെറ്റിംഗ്സും ഓവര്‍ റൈറ്റ് ചെയ്യപ്പെടും. അതിനു ശേഷം യുബ്ലോക്ക്‌ഒ റീസ്റ്റാര്‍ട്ട്‌ ചെയ്യപ്പെടും.\n\nനിലവിലുള്ള എല്ലാ സെറ്റിങ്ങുകളും ഓവര്‍റൈറ്റ് ചെയ്യട്ടെയോ?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "ഡേറ്റ വായിക്കാന്‍ ഒക്കുന്നില്ല അല്ലെങ്കില്‍ അത് ഇന്‍വാലിഡ്‌ ആണ്", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "എല്ലാ സെറ്റിങ്ങുകളും റിമൂവ് ചെയ്യപ്പെടും. അതിനു ശേഷം യുബ്ലോക്ക്ഒ റീസ്റ്റാര്‍ട്ട്‌ ചെയ്യപ്പെടും.\n\nയുബ്ലോക്ക്ഒ-യെ ഫാക്ടറി സെറ്റിങ്ങുകളിലേക്ക് റീസെറ്റ് ചെയ്യട്ടെയോ?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "{{url}} എന്നതിലേക്ക് കണക്റ്റ് ചെയ്യാനാകുന്നില്ല", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "യുബ്ലോക്ക്ഒ: താഴെ പറയുന്ന യുആര്‍എല്‍ താങ്കളുടെ കസ്റ്റം ഫില്‍റ്ററില്‍ ചേര്‍ക്കട്ടേയോ?\n\nടൈറ്റില്‍: \"{{title}}\"\nയുആര്‍എല്‍: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "സബ്‌സ്‌ക്രൈബുചെയ്യുക", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ഒരു മിനിറ്റ് മുന്‍പ്", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} മിനിറ്റുകള്‍ മുന്‍പ്", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ഒരു മണിക്കൂര്‍ മുന്‍പ്", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} മണിക്കൂറുകള്‍ മുന്‍പ്", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ഒരു ദിവസം മുന്‍പ്", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} ദിവസങ്ങള്‍ക്ക്മുന്‍പ്", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "ഡാഷ്ബോര്‍ഡ് കാണിക്കുക", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "ലോഗ്ഗര്‍ കാണിക്കുക", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "ഓഫ്", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "താഴെ പറയുന്ന പേജ് ലോഡ് ചെയ്യുന്നത് യുബ്ലോക്ക് ഒറിജിന്‍ തടഞ്ഞിരിക്കുന്നു:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "ഈ ഫില്‍റ്റര്‍ കാരണം", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "ഇതില്‍ കണ്ടെത്തി:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "പിന്നിലേക്ക്‌ പോകുക", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "ഈ വിന്‍ഡോ ക്ലോസ് ചെയ്യുക", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}}ലേക്ക് കര്‍ശന ബ്ലോക്കിംഗ് ഡിസേബിള്‍ ചെയ്യുക", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "താല്‍ക്കാലികമായി", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "സ്ഥിരമായി", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "ക്ലൌഡ് സ്റ്റോറേജിലേക്ക് എക്സ്പോര്‍ട്ട്‌ ചെയ്യുക", + "description": "tooltip" + }, + "cloudPull": { + "message": "ക്ലൌഡ് സ്റ്റോറേജില്‍ നിന്ന് ഇമ്പോര്‍ട്ട് ചെയ്യുക", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "ക്ലൗഡ് സംഭരനിയില്‍ നിന്ന് ഇറക്കുമതി ചെയ്ത് നിലവിലെ ക്രമീകരണത്തില്‍ ലയിപ്പിക്കും", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "ഈ ഉപകരണത്തിന്‍റെ പേര്:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "മുന്നറിയിപ്പ്! നിങ്ങളുടെ സ്വന്തം ഉത്തരവാദിത്തത്തിൽ ഈ നൂതന ക്രമീകരണങ്ങൾ മാറ്റുക.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "സബ്മിറ്റ്", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "മാറ്റങ്ങൾ വരുത്തു", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "റിവേര്‍ട്ട്", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "ബൈറ്റുകള്‍", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "ഫ്രെയിമിലെ ഘടകം തടയുക ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "ഫിൽട്ടർ ലിസ്റ്റിലേക്ക് സബ്സ്ക്രൈബ് ചെയ്യുക ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "താൽക്കാലികമായി വലിയ മീഡിയ അനുവദിക്കുക", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "ഒരു കുറുക്കുവഴി ടൈപ്പുചെയ്യുക", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "ലോക്കുചെയ്‌ത സ്ക്രോളിംഗ് ടോഗിൾ ചെയ്യുക", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "ക്ലിപ്പ്ബോർഡിലേയ്ക്ക് പകർത്തുക", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "തടയൽ മോഡ് വിശ്രമിക്കുക", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "ഉപയോഗിച്ച സംഭരണം: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "കെ.ബി.", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "എം.ബി.", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ജി.ബി.", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "ലോഡുചെയ്യാൻ ക്ലിക്കുചെയ്യുക", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/mr/messages.json b/src/_locales/mr/messages.json new file mode 100644 index 0000000..9a60cc8 --- /dev/null +++ b/src/_locales/mr/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "शेवटी, एक कार्यक्षम ब्लॉकर क्रोमियम आधारित ब्राउझरांसाठी. सीपीयू आणि मेमरी वर सोपे जातो.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "म्यूब्लॉक — डैशबोर्ड", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warning! You have unsaved changes", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "सेटिंग्ज", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "तृतीय-पक्ष फिल्टर", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "आपले फिल्टर", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "माझे नियम", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "श्वेतसूची", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — लॉगर", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "माहिती", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "प्रगत सेटिंग्ज", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "क्लिक करा : या साइटसाठी म्यूब्लॉक अक्षम/सक्षम.\n\nCtrl+क्लिक करा: फक्त या पृष्ठावर म्यूब्लॉक अक्षम.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Ctrl क्लिक करा फक्त या साइटवर म्यूब्लॉक बंद करण्यासाठी.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Ctrl क्लिक करा फक्त या साइटवर म्यूब्लॉक चालू करण्यासाठी.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "विनंत्या अवरोधित", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "या पृष्ठावर", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} किंवा {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "स्थापने पासून", + "description": "English: since install" + }, + "popupOr": { + "message": "किंवा", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "डॅशबोर्ड उघडण्यासाठी क्लिक करा", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "घटक निवडक मोड प्रविष्ट करा", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "विनंती लॉग ला जा", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "या साइटसाठी सर्व पॉपअप अवरोधित करणे टॉगल करा", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "या साइटसाठी मोठ्या माध्यम घटक अवरोधित करणे टॉगल करा", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "या साइटसाठी कॉस्मेटिक फिल्टरिंग टॉगल करा", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "More", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "सर्व", + "description": "" + }, + "popupImageRulePrompt": { + "message": "चित्रे", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "तृतीय पक्ष", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "तृतीय पक्षी css/चित्रे", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} पैकी {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "निर्माण करा", + "description": "English: Create" + }, + "pickerPick": { + "message": "निवडा", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "बाहेर पडा", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "नेट फिल्टर", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "उटणे फिल्टर", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Ctrl - क्लिक करा", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "घटक अवरोधित करा", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "अवरोधित घटकाचे प्लेसहोल्डर लपवा", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "अवरोधित विनंत्यांची संख्या चिन्हावर दाखवा", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "जेथे योग्य तेथे संदर्भ मेनू याचा वापर करा", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "प्रगत सेटिंग्ज", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "अखेरचे पुनर्संचयित:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "अंतिम बॅकअप:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} नेटवर्क फिल्टर + {{cosmeticFilterCount}} उटणे फिल्टर :", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} वापरले {{total}} पैकी", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "स्वयं-अद्यतन फिल्टर यादी.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "आता अद्यतनित करा", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "सर्व कॅशे साफ करा", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "उटणे फिल्टरना विश्लेषित करा आणि त्यांची अंमलबजावणी करा.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

हा पर्याय अद्ब्लोक प्लस सुसंगत “घटक लपवणारे” फिल्टरचे विश्लेषण आणि अंमलबजावणी सक्षम करतो. हे फिल्टर मूलत: उटणे आहेत, ते वेब पृष्ठावर घटक लपवतात जें व्हिज्युअल उपद्रव असल्याचे मानण्यात येतात आणि जे निव्वळ विनंती-आधारित फिल्टरिंग इंजिनद्वारे अवरोधित करणे शक्य नाही.

हे वैशिष्ट्य सक्षम केले तरम्यूब्लॉकचे मेमरी पावलाचा ठसा वाढतो.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "उअवरोधित होस्ट यांची सूची", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "बदल लागू करा", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "जाहिराती", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "गोपनीयता", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "मालवेअर डोमेन", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "चिडवणाऱ्या गोष्टी", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "बहुउद्देशीय", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "विभाग , भाषा", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "सानुकूल", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "प्रति ओळ एक युआरएल. ओळी सह प्रिफिक्स ‘!’ कढे दुर्लक्ष केले जाईल. अवैध युआरएल शांतपणे दुर्लक्ष केले जाईल.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "कालबाह्य", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Updating…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "प्रति ओळ एक फिल्टर. फिल्टर एक साधे होस्ट नावाचा असू शकतो, किंवा एक अद्ब्लोक प्लस सुसंगत फिल्टर असू शकतो. ओळी सह प्रिफिक्स ‘!’ कढे दुर्लक्ष केले जाईल.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "आयात आणि समावेश करा", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "निर्यात करा", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "बदल लागू करा", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "स्थायी नियम", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "अस्थायी नियम", + "description": "header" + }, + "rulesRevert": { + "message": "मागे जा", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "संपादित करा", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Save", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "आपली होस्ट नावांची यादी ज्याचासाठी म्यूब्लॉक अक्षम केले जाईल. प्रति ओळ एक प्रविष्टी. अवैध होस्ट नावांकडे शांतपणे दुर्लक्ष केले जाईल.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "आयात आणि समावेश करा", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "निर्यात करा", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "बदल लागू करा", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "प्रकार", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "डोमेन", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "यूआरएल", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "फिल्टर", + "description": "English: Filter" + }, + "logAll": { + "message": "All", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rule", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Block", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Allow", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "बदल नोंदी", + "description": "" + }, + "aboutCode": { + "message": "स्त्रोत कोड (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "सहभागी", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "फाइल वर बॅकअप करा...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "फाइल पासून पुनर्संचयित करा...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "मुळापासून सुरू करा...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "आपले सर्व सेटिंग्ज ना खोडून {{time}} चा बॅकअप डेटा वापरला जाईल, आणि म्यूब्लॉक रीस्टार्ट होईल.\n\nसर्व विद्यमान सेटिंग्ज ना खोडून बॅकअप डेटा वापरावे का?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "आपले सर्व सेटिंग्ज पुसले जातील, आणि म्यूब्लॉक रीस्टार्ट होईल .\n\nम्यूब्लॉक ला फॉक्टोरी सेटिंग्ज ला रीसेट करावे का?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "{{url}} ला कनेक्ट करण्यात अक्षम", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "a minute ago", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutes ago", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "an hour ago", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a day ago", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} days ago", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Go back", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporarily", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanently", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "This device name:", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ms/messages.json b/src/_locales/ms/messages.json new file mode 100644 index 0000000..263303d --- /dev/null +++ b/src/_locales/ms/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Akhirnya, penyekat yang cekap. Tidak membebankan CPU dan memori.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Papanmuka", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Amaran! Anda mempunyai perubahan yang tidak disimpan", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Kekal", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Abaikan", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Tetapan", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Senarai penapis", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Penapis saya", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Peraturan saya", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Senarai putih", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Pintasan", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Catatan", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Mengenai", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Sokongan", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Pertonton aset", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Tetapan lanjut", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: tutup/aktifkan uBlock₀ untuk laman web ini.\n\nCtrl+klik: tutupkan uBlock₀ pada halaman ini sahaja.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kilk untuk nyahdayakan uBlock₀ untuk laman web ini.\n\nCtrl+klik untuk nyahdayakan uBlock₀ hanya di halaman ini.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik untuk mendayakan uBlock₀ untuk laman web ini.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "permintaan dihalang", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "pada halaman ini", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} atau {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "sejak dipasang", + "description": "English: since install" + }, + "popupOr": { + "message": "atau", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Disekat di halaman ini", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Disekat sejak dipasang", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domain telah dihubungkan", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Klik untuk membuka dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Masuk mod pilihan elemen", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Memasuki mod pemetik elemen", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Membuka catatan", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Laporkan masalah tentang laman web ini", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Togol penghalang untuk segala pop timbul laman ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik untuk menyekat semua pop timbul di laman ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik untuk berhenti menyekat semua pop timbul di laman ini", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Togol penghalang semua elemen media besar untuk laman ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik untuk menyekat elemen media yang besar di laman ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik untuk berhenti menyekat elemen media yang besar di laman ini", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Togol penapis kosmetik untuk laman ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik untuk mematikan penapisan kosmetik di laman ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik untuk mengaktifkan penapisan kosmetik di laman ini", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Togol menyekat fon terpencil untuk laman web ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik untuk menyekat fon jauh di laman ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik untuk berhenti menyekat fon jauh di laman ini", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klik untuk hilangkan keupayaan JavaScript di halaman ini", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klik untuk berhenti hilangkan keupayaan JavaScript di halaman ini", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Tetingkap pop timbul", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Unsur-unsur media besar", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Tapisan kosmetik", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fon terpencil", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Lagi", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Kurangkan", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Peraturan global: lajur ini adalah untuk peraturan yang dikuatkuasakan untuk semua laman.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klik untuk membuat perubahan anda kekal.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klik untuk memungkiri perubahan anda.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "semua", + "description": "" + }, + "popupImageRulePrompt": { + "message": "gambar", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "pihak ketiga", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/imej pihak ketiga", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Skrip dalam ayat", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Skrip parti pertama", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Skrip parti ke-3", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Kerangka parti ke-3", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "Domain telah dihubungkan", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} daripada {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versi", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Cipta", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pilih", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Keluar", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Preview", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Penapis network", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Penapis Kosmetik", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Halang elemen", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Sembunyikan simbol unsur-unsur yang disekat", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Tunjukkan nombor permintaan yang disekat di atas ikon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Menutupkan mesej bantuan", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Gunakan menu konteks yang sesuai", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Mesra buta warna", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Membolehkan sokongan storan awangan", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Saya adalah pengguna mahir (memerlukan pembacaan)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Lumpuhkan pra-ambilan (untuk mengelakkan apa-apa sambungan untuk permintaan rangkaian yang disekat)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Nyahaktifkan pengauditan hiperpautan", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Mencegah WebRTC dari membocorkan alamat IP tempatan", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Kelakuan lalai", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Tingkah laku lalai ini boleh diatasi secara per-halaman", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Lumpuhkan tapisan kosmetik", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Sekat unsur-unsur media yang lebih besar dari {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Sekat fon terpencil", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Lumpuhkan JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Sekat laporan CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Mendedahkan nama kanonik", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Lanjutan", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "tetapan lanjutan", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Pemulihan lalu:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Sandaran lalu:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} penapis rangkaian + {{cosmeticFilterCount}} penapis kosmetik dari:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} digunakan dari {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Kemas kini auto senarai tapisan", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Kemas kini sekarang", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Bersihkan semua cache", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Hurai dan kuatkuasakan tapisan kosmetik", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Penapis kosmetik berkhidmat untuk menyembunyikan unsur-unsur dalam laman web yang disifatkan sebagai suatu gangguan visual, dan yang tidak mampu disekat oleh enjin tapisan berasaskan permintaan rangkaian.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Abaikan penapis kosmetik generik", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Penapis kosmetik generik adalah penapis kosmetik itu mengubah kesemua laman web. Mendayakan tetapan ini akan mengurangkan penggunaan memori dan overhed CPU dari laman web sebagai hasil pengendalian penapis kosmetik generik.\n\nIa disyorkan untuk mengaktifkan tetapan ini untuk peranti yang lemah.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Gantung aktiviti rangkaian sehingga semua senarai penapis dimuatkan", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Terbina dalam", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Iklan", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privasi", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domain perisian hasad", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Kejengkelan", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Pelbagai guna", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Wilayah, bahasa", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Tersuai", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Import...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Satu URL per garisan. URL yang tidak sah akan diabaikan secara senyap.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Usang.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "melihat kandungan", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Kemaskini terakhir: {{ago}}.\nKlik untuk memaksa kemas kini.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Sedang mengemaskini...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ralat rangkaian menghalang sumber dikemas kini..", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Satu penapis setiap baris. Penapis boleh menjadi nama hos biasa, atau penapis yang sesuai dengan Daftar Mudah. Garis yang diawali dengan ! akan diabaikan.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import dan melampirkan", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksport", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filter _ {{datetime}}. txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Peraturan kekal", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Peraturan sementara", + "description": "header" + }, + "rulesRevert": { + "message": "Bebalik", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Keterikatan", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edit", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Simpan", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Batal", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import dari fail...", + "description": "" + }, + "rulesExport": { + "message": "Eksport ke fail", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt\n", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Senaraikan peraturan penapisan dinamik anda.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaks peraturan: tindakan jenis tujuan sumber ( dokumentasi lengkap ).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Susun:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Jenis peraturan", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Sumber", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinasi", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Arahan laman web yang dipercayai menentukan halaman web mana uBlock Origin harus dilumpuhkan. Satu penyertaan setiap baris. Arahan tidak sah akan diam-diam diabaikan dan dikomentari.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import dan melampirkan", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksport", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt\n", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Terapkan perubahan", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Jenis", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Penapis", + "description": "English: Filter" + }, + "logAll": { + "message": "Semua", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tanpa tab", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Tab semasa", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Muat semula kandungan tab", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Togol pemeriksa DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Togol panel pop timbul", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Catatan", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Kosongkan catatan", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Jedakan catatan (singkirkan semua data masuk)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Nyahjeda catatan", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Togol penapis catatan", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "tapis kandungan catatan", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Pilihan tapisan catatan", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Bukan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "disekat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "dibenarkan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "diubah suai", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "pihak pertama", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "pihak ketiga", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Butiran", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Penapis", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Senarai tapisan", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Peraturan", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteks", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Konteks akar", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Jenis", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Aturan URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteks:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Jenis:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Penapis statik", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} permintaan rangkaian {{type}} {{br}} alamat URL yang sesuai dengan {{url}} {{br}} dan mana yang berasal {{origin}}, {{br}} {{kepentingan} } ada penapis pengecualian yang sepadan.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Sekat", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Benarkan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "jenis “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "pelbagai jenis", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "dari “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "dari mana-mana ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "kecuali bila", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "walaupun", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Penapis statik {{filter}} terdapat di:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Penapis statik tidak dapat dijumpai dalam daftar penapis yang diaktifkan sekarang", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Entri logger yang tidak memenuhi ketiga-tiga syarat di bawah akan dibuang secara automatik:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Simpan entri dari {{input}} minit terakhir", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Simpan paling banyak {{input}} pemuatan halaman setiap tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Simpan paling banyak {{input}} entri setiap tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Gunakan baris {{input}} setiap entri dalam mod yang diluaskan secara menegak", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sembunyikan lajur:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Masa", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Tapis / peraturan", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteks", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Kesopanan", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Senarai", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Jadual", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Kosong", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Penurunan harga", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Buka", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Cipta laporan baru", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Cari laporan yang serupa", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Pendokumenan", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Baca pendokumenan di uBlock/wiki untuk belajar tentang kesemua ciri-ciri uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Soalan dan sokongan", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Menjawab soalan dan pelbagai sokongan disediakan di subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Masalah penapisan/laman web rosak", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Laporkan masalah penapisan di laman web tertentu di uBlockOrigin/uAssets pengesan masalah. Memerlukan akaun GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Penting: Elakkan menggunakan penyekat-penyekat lain yang serupa dengan uBlock Origin, kerana ia menimbulkan masalah penapis di laman web tertentu.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tip: Pastikan senarai penapis kamu dikemaskinikan \tPencatat adalah peralatan utama untuk memeriksa masalah yang berkaitan penapis.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Laporan pepijat", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Laporkan masalah dengan uBlock Origin sendiri ke uBlockOrigin/uBlock-issue pengesan masalah. Memerlukan akaun GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informasi Pencarisilapan", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Berikut adalah maklumat teknikal yang mungkin berguna ketika sukarelawan berusaha membantu anda menyelesaikan masalah.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Penting:Maklumat yang bersifat sensitif dan peribadi dihitamkan secara lalai. Maklumat yang dihitamkan berkemungkinan sukar untuk menyelesaikan masalah. ", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Laporkan masalah berkaitan penapis", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Untuk menggelakkan bebanan penyumbang dengan laporan pendua, sila mengesahkan bahawa isu itu belum dilaporkan.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Alamat laman web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Laman web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pilih entri --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Tunjuk iklan dan baki iklan tertinggal", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Mempunyai panel dan gangguan lain", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Mengesan uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Mempunyai masalah berkaitan privasi", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Rosak pabila uBlock Origin didayakan", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Membuka tab atau tetingkap yang tidak diingini", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Labelkan laman web itu sebagai \"NSFW\" (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Hitamkan", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Nyahhitamkan", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Dasar privasi", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Catatan perubahan", + "description": "" + }, + "aboutCode": { + "message": "Kod sumber (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Penyumbang", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kod sumber", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Terjemahan", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Senarai penapis", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Pergantungan luaran (serasi dengan GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Senarai penapis uBO sendiri dihoskan secara bebas di CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN yang dipilih secara rawak digunakan apabila senarai penapis perlu dikemas kini", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sandarkan ke fail", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt\n", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Pulihkan dari fail ...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Tetapkan semula ke tetapan lalai ...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Semua tetapan anda akan ditimpa menggunakan data yang disandarkan pada {{time}}, dan uBlock₀ akan dimulakan semula.\n\nMenimpa semua tetapan yang ada menggunakan data yang disandarkan?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Data tidak dapat dibaca atau tidak sah", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Semua tetapan anda akan dikeluarkan, dan uBlock₀ akan dimulakan semula.\n\nTetapkan semula uBlock₀ ke tetapan kilang?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Ralat rangkaian: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Tambahkan URL berikut ke senarai penapis tersuai anda?\n\nTajuk: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Langgan", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "seminit yang lalu", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minit yang lalu", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "satu jam yang lalu", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} jam yang lalu", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "sehari yang lalu", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} hari yang lalu", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Tunjukkan Papan Pemuka", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Tunjukkan Pencatat", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "mati", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Halaman disekat", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin menghalang halaman berikut memuatkan:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Kerana penapis berikut:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "tanpa parameter", + "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": "Dijumpai di:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Kembali", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Tutup tetingkap ini", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Jangan beri amaran kepada saya lagi tentang laman web ini", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Lumpuhkan sekatan ketat untuk {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Sementara", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Kekal", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Teruskan", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksport ke storan awan", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import dari storan awan", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import dari storan awan dan gabungkan dengan tetapan semasa", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nama peranti ini:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Amaran! Ubah tetapan lanjutan ini dengan risiko anda sendiri.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Hantar", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Terapkan perubahan", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Membalikkan", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bait", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blok elemen dalam bingkai ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Langgan ke senarai tapisan...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Biarkan sementara elemen media besar", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Taipkan jalan pintas", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Togol tatal terkunci", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Salin ke papan keratan", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Pilih semua", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Togol penapis kosmetik", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Tenang mod menyekat", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storan yang digunakan: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klik untuk memuatkan", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json new file mode 100644 index 0000000..811ab77 --- /dev/null +++ b/src/_locales/nb/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Endelig en effektiv blokkeringsutvidelse. Lavt CPU- og minnebruk.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashbord", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Advarsel! Du har ulagrede endringer", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Bli her", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorer", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Innstillinger", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlister", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mine filtre", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mine regler", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Betrodde sider", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Snarveier", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logg", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Om", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Brukerstøtte", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Ressursviser", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Avanserte innstillinger", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klikk: Deaktiver/aktiver uBlock₀ for dette nettstedet.\n\nCtrl+klikk: Deaktiver uBlock₀ bare på denne siden.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klikk for å deaktivere uBlock₀ for dette nettstedet.\n\nCtrl+klikk for å deaktivere uBlock₀ bare på denne siden.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klikk for å aktivere uBlock₀ for dette nettstedet.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "forespørsler blokkert", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "på denne siden", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "siden installering", + "description": "English: since install" + }, + "popupOr": { + "message": "eller", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokkert på denne siden", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokkert siden installering", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domener tilkoblet", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Åpne dashbordet", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Gå til element­fjernings­modus", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Gå til element­velger­modus", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Åpne loggen", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Rapporter om problem på dette nettstedet", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Slå av/på blokkering av alle oppspretts-vinduer for dette nettstedet", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klikk for å blokkere alle oppspretts-vinduer på dette nettstedet", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klikk for å ikke lenger blokkere alle oppspretts-vinduer på dette nettstedet", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Slå av/på blokkering av store mediaelementer for dette nettstedet", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klikk for å blokkere store mediaelementer på dette nettstedet", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klikk for å ikke lenger blokkere store mediaelementer på dette nettstedet", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Slå av/på kosmetisk filtrering for dette nettstedet", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klikk for å slå av kosmetisk filtrering på dette nettstedet", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klikk for å slå på kosmetisk filtrering på dette nettstedet", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Slå av/på blokkering av eksterne skrifttyper for dette nettstedet", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klikk for å blokkere eksterne skrifttyper på dette nettstedet", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klikk for å ikke lenger blokkere eksterne skrifttyper på dette nettstedet", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klikk for å slå av JavaScript på dette nettstedet", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klikk for å ikke lenger slå av JavaScript på dette nettstedet", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Oppspretts-vinduer", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Store media­elementer", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetisk filtrering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Eksterne skrifttyper", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mer", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mindre", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globale regler: Denne kolonnen er for regler som gjelder alle nettsteder.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klikk for å gjøre endringer permanente.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klikk for å tilbakestille endringer.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "alle", + "description": "" + }, + "popupImageRulePrompt": { + "message": "bilder", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "tredjepart", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "tredjeparts CSS/bilder", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "integrerte skript", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "førsteparts skript", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "tredjeparts skript", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "tredjeparts rammer", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domener tilkoblet", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} av {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versjon", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ramme", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Opprett", + "description": "English: Create" + }, + "pickerPick": { + "message": "Velg", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Avslutt", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Forhåndsvis", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Nettfiltre", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetiske filtre", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klikk, Ctrl-klikk", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokker element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Skjul blokkerte elementers plassholdere", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Vis antall blokkerte forespørsler på ikonet", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Deaktiver hjelpetekst (verktøytips)", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Gjør bruk av høyreklikkmeny der det er hensiktsmessig", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Fargeblind-vennlig", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Utseende", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Tilpasset aksentfarge", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktiver støtte for nettlagring", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Jeg er en avansert bruker", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Deaktiver forhåndshenting (for å hindre enhver tilkobling for blokkerte nettverksforespørsler)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Deaktiver lenkesporing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Hindre WebRTC i å lekke lokale IP-adresser", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standard virkemåte", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Disse standard virkemåtene kan overstyres for hvert enkelt nettsted", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Deaktiver kosmetisk filtrering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokker mediaelementer større enn {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokker eksterne skrifttyper", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Deaktiver JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokker CSP-rapporter", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "CNAME-avdekking", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avansert", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funksjoner kun egnet for tekniske brukere", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Avanserte innstillinger", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Siste gjenoppretting:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Siste sikkerhetskopi:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} nettverksfiltre + {{cosmeticFilterCount}} kosmetiske filtre fra:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} brukt av {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatisk oppdatering av filterlister", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Oppdater nå", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Tøm alle hurtigbuffere", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analyser og bruk kosmetiske filtre", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetiske filtre tjener den hensikt å skjule elementer i en nettside som anses for å være en visuell ulempe, og som ikke blokkeres av de nettverkforespørselsbaserte filtreringsmotorene.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorer generelle kosmetiske filtre", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Generelle kosmetiske filtre er de kosmetiske filtrene som er ment å brukes på alle nettsteder. Aktivering av dette alternativet vil eliminere ekstra minne- og prosessorbruk på nettsider grunnet håndteringen av generelle kosmetiske filtre.\n\nDet anbefales å aktivere dette alternativet på mindre kraftige enheter.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Stans nettverksaktivitet inntil alle filterlister er lastet", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Bruk endringer", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Innebygd", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklame", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Personvern", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Beskyttelse mot skadelig programvare, sikkerhet", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Irritasjonsmomenter", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multi-formål", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regioner, språk", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Egendefinert", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importer…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "En nettadresse per linje. Ugyldige nettadresser ignoreres stille.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Utgått på dato", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Vis innhold", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Siste oppdatering: {{ago}}.\nKlikk for å framtvinge en oppdatering.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Oppdaterer…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "En nettverksfeil forhindret ressursen i å bli oppdatert.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ett filter per linje. Et filter kan være et vanlig vertsnavn eller et EasyList-kompatibelt filter. Linjer med prefikset ! blir ignorert.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Ikke legg til filtre fra ikke-betrodde kilder.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importer og legg til…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksporter…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mine-ublock-statiske-filtre_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Bruk endringer", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanente regler", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Midlertidige regler", + "description": "header" + }, + "rulesRevert": { + "message": "Tilbakestill", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Send", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Rediger", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Lagre", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Forkast", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importer fra fil…", + "description": "" + }, + "rulesExport": { + "message": "Eksporter til fil…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mine-ublock-dynamiske-regler_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Liste over dine dynamiske filtreringsregler.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regelsyntaks: kilde destinasjon type handling (full dokumentasjon).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sorter:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Regeltype", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Kilde", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinasjon", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Direktivene for betrodde sider bestemmer hvilke nettsider uBlock Origin ikke skal være aktiv på. Én oppføring per linje.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importer og legg til…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksporter…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mine-ublock-betrodde-sider_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Bruk endringer", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domene", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Nettadresse", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alle", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Faneløs", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Gjeldende fane", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Last faneinnholdet på nytt", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Slå av/på DOM-inspektør", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Slå av/på oppsprettspanelet", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Loggen", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Tøm loggen", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Sett loggen i pausemodus (forkast alle innkommende data)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Gjenoppta logging", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Slå av/på loggfiltrering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrer logginnhold", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Alternativer for loggfiltrering", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ikke", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "hendelsesrik", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokkert", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "tillatt", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "endret", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "førstepart", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "tredjepart", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detaljer", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterliste", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Rotkontekst", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partsrelasjon", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Nettadresse", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Nettadresseregel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statisk filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} nettverksforespørsler av {{type}} {{br}}som matcher nettadressen {{url}} {{br}}og som stammer {{origin}},{{br}}{{importance}} det er et matchende unntaksfilter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokker", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Tillat", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "enhver type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "fra “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "fra hvor som helst", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "unntatt når", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "selv om", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statisk filter {{filter}} funnet i:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statisk filter ble ikke funnet i noen av filterlistene som er aktiverte nå", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggoppføringer som ikke oppfyller alle tre betingelser nedenfor blir automatisk forkastet:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Bevar oppføringer fra de siste {{input}} minuttene", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Bevar maksimalt {{input}} sideinnlastinger per fane", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Bevar maksimalt {{input}} oppføringer per fane", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Bruk {{input}} linjer per oppføring i vertikalt utvidet modus", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Skjul kolonner:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tid", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/regel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partsrelasjon", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Liste", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabell", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Uformatert", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Åpne", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Opprett ny rapport", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Finn lignende rapporter", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentasjon", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Les dokumentasjonen på uBlock/wiki for å lære om alle uBlock Origins funksjoner.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Spørsmål og brukerstøtte", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Svar på spørsmål og andre typer hjelp er gitt på subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterproblemer/nettside defekt", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Rapporter filterproblemer med bestemte nettsteder til uBlockOrigin/uAssets problemsporing. Krever en GitHub-konto.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Viktig: Unngå å bruke andre blokkerere med lignende formål sammen med uBlock Origin, da dette kan forårsake filterproblemer på bestemte nettsteder.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: Sørg for at filterlistene dine er oppdaterte. Loggen er primærverktøyet for å diagnostisere filterrelaterte problemer.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Feilrapport", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Rapporter problemer med selve uBlock Origin til uBlockOrigin/uBlock-issue problemsporing. Krever en GitHub-konto.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Problemløsingsinformasjon", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Nedenfor er teknisk informasjon som kan være nyttig når frivillige prøver å hjelpe deg med å løse et problem.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Viktig: Potensielt privat eller sensitiv informasjon blir redigert som standard. Redigert informasjon kan gjøre det vanskeligere å løse et problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Rapporter om filterproblem", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "For å unngå å belaste frivillige med duplikate rapporter, kontroller at problemet ikke allerede er rapportert.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlister oppdateres daglig. Forsikre deg om at problemet ikke har blitt løst allerede i de nyeste filterlistene.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifiser at problemet fremdeles eksisterer etter å ha lastet den problematiske nettsiden på nytt.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Nettsidens adresse:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Nettsiden…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Velg en type --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Viser reklame eller reklamerester", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Har overlegg eller andre ulemper", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detekterer uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Har personvernrelaterte problemer", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Fungerer ikke riktig når uBlock Origin er aktivert", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Åpner uønskede faner eller vinduer", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Merk nettsiden som “NSFW” (“Not Safe For Work”) (advarsel mot sider med upassende innhold)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Rediger", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Ikke rediger", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Personvernpraksis", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Endringslogg", + "description": "" + }, + "aboutCode": { + "message": "Kildekode (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Bidragsytere", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kildekode", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Oversettelser", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlister", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Eksterne avhengigheter (GPLv3-kompatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBlock Origins egne filterlister finnes fritt tilgjengelig hos følgende CDN-er:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "En tilfeldig valgt CDN blir brukt når en filterliste trenger å bli oppdatert.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sikkerhetskopier til fil…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "min-ublock-sikkerhetskopi_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Gjenopprett fra fil…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Tilbakestill til standardinnstillinger…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Alle dine innstillinger vil bli overskrevet med data sikkerhetskopiert {{time}}, og uBlock₀ vil starte på nytt.\n\nOverskrive alle eksisterende innstillinger med sikkerhetskopierte data?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Dataene kunne ikke leses eller er ugyldige", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Alle dine innstillinger blir fjernet, og uBlock₀ vil starte på nytt.\n\nTilbakestille uBlock₀ til opprinnelige innstillinger?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Nettverksfeil: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Legge til følgende nettadresse i din egendefinerte filterliste?\n\nTittel: \"{{title}}\"\nNettadresse: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonner", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "et minutt siden", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutter siden", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "en time siden", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} timer siden", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "en dag siden", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dager siden", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Vis dashbord", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Vis logg", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "av", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Side blokkert", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin har forhindret lasting av følgende side:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "På grunn av følgende filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "uten parametere", + "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": "Funnet i:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Gå tilbake", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Lukk dette vinduet", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Ikke varsle igjen om dette nettstedet", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Slå av streng (fullstendig) blokkering for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Midlertidig", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanent", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Fortsett", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksporter til nettlagring", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importer fra nettlagring", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importer fra nettlagring og slå sammen med gjeldende innstillinger", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Denne enhets navn:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Advarsel! Endringer av de avanserte innstillingene skjer på eget ansvar.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Send", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Bruk endringer", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Tilbakestill", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokker element i ramme…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonner på filterliste…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Tillat store mediaelementer midlertidig", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Vis kildekode…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Oppfør en snarvei", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Slå av/på låst rulling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopier til utklippstavle", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Merk alt", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Slå av/på kosmetisk filtrering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Lemp på blokkeringsmodus", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Brukt lagringsplass: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klikk for å laste", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Feil: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Kan ikke filtrere riktig ved nettleseroppstart. Last siden på nytt for å sikre riktig filtrering.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json new file mode 100644 index 0000000..8c50f79 --- /dev/null +++ b/src/_locales/nl/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Eindelijk, een efficiënte adblocker. Gebruikt weinig processorkracht en geheugen.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ – Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Waarschuwing! Niet-opgeslagen wijzigingen", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Hier blijven", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Negeren", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Instellingen", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlijsten", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mijn filters", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mijn regels", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Vertrouwde websites", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Sneltoetsen", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ – Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Over", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Ondersteuning", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ – Middelenviewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Geavanceerde instellingen", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klikken: uBlock₀ voor deze website in- of uitschakelen.\n\nCtrl+klikken: uBlock₀ alleen voor deze pagina uitschakelen.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klik om uBlock₀ voor deze website uit te schakelen.\n\nCtrl+klik om uBlock₀ alleen op deze pagina uit te schakelen.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klik om uBlock₀ voor deze website in te schakelen.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "geblokkeerde aanvragen", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "op deze pagina", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "sinds installatie", + "description": "English: since install" + }, + "popupOr": { + "message": "of", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Geblokkeerd op deze pagina", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Geblokkeerd sinds installatie", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Verbonden domeinen", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Dashboard openen", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Element­wisser­modus openen", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Element­kiezer­modus openen", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Logger openen", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Een probleem op deze website melden", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alle pop-ups voor deze website in-/uitschakelen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klik om alle pop-ups op deze website te blokkeren", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klik om alle pop-ups op deze website niet meer te blokkeren", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Grote media-elementen voor deze website in-/uitschakelen", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klik om grote media-elementen op deze website te blokkeren", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klik om grote media-elementen op deze website niet meer te blokkeren", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Cosmetische filters voor deze website in-/uitschakelen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klik om cosmetische filters op deze website uit te schakelen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klik om cosmetische filters op deze website in te schakelen", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Blokkeren van externe lettertypen voor deze website in-/uitschakelen", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klik om externe lettertypen op deze website te blokkeren", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klik om externe lettertypen op deze website niet meer te blokkeren", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klik om JavaScript op deze website uit te schakelen", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klik om JavaScript op deze website niet meer uit te schakelen", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-upvensters", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Grote media-elementen", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetische filters", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Externe lettertypen", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Meer", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Minder", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Algemene regels: deze kolom is voor regels die op alle websites van toepassing zijn.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokale regels: deze kolom is voor regels die alleen op de huidige website van toepassing zijn.\nLokale regels hebben voorrang op algemene regels.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klik om uw wijzigingen permanent te maken.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klik om uw wijzigingen ongedaan te maken.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "alles", + "description": "" + }, + "popupImageRulePrompt": { + "message": "afbeeldingen", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "van derden", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/afbeeldingen van derden", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts van de webpagina", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts van derden", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames van derden", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "verbonden domeinen", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} van {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versie", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Aanmaken", + "description": "English: Create" + }, + "pickerPick": { + "message": "Kiezen", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Afsluiten", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Voorbeeld", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Netwerkfilters", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetische filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Element blokkeren…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Aanduidingen van geblokkeerde elementen verbergen", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Het aantal geblokkeerde aanvragen op het pictogram tonen", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Tooltips uitschakelen", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Contextmenu gebruiken waar mogelijk", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Vriendelijk voor kleurenblinden", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Vormgeving", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Thema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Aangepaste accentkleur", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Ondersteuning voor cloudopslag inschakelen", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ik ben een ervaren gebruiker", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Vooraf ophalen uitschakelen (om verbindingen voor geblokkeerde netwerkaanvragen te voorkomen)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Hyperlink auditing uitschakelen", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Het lekken van lokale IP-adressen via WebRTC voorkomen", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standaardgedrag", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Van deze standaardgedragingen kan per website worden afgeweken", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Cosmetische filters uitschakelen", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Media-elementen groter dan {{input}} KB blokkeren", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Externe lettertypen blokkeren", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript uitschakelen", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP-rapporten blokkeren", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Canonieke namen onthullen", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Geavanceerd", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Alleen voor technische gebruikers geschikte functies", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "geavanceerde instellingen", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Laatste terugzetactie:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Laatste back-up:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} netwerkfilters + {{cosmeticFilterCount}} cosmetische filters van:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} van de {{total}} gebruikt", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Filterlijsten automatisch bijwerken", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Nu bijwerken", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Alle caches legen", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Cosmetische filters inlezen en toepassen", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Cosmetische filters dienen voor het verbergen van elementen in een webpagina die visueel storend kunnen zijn en niet door de op netwerkaanvragen gebaseerde filter-engines kunnen worden geblokkeerd.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Algemene cosmetische filters negeren", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Algemene cosmetische filters zijn die cosmetische filters die zijn bedoeld om op alle websites te worden toegepast. Het inschakelen van deze optie elimineert de aan webpagina’s toegevoegde geheugen- en cpu-overhead als gevolg van het verwerken van algemene cosmetische filters.\n\nHet wordt aanbevolen deze optie op minder krachtige apparaten in te schakelen.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Netwerkactiviteit onderbreken totdat alle filterlijsten zijn geladen", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lijst van geblokkeerde hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Wijzigingen toepassen", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Ingebouwd", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Advertenties", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacy", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Bescherming tegen malware, beveiliging", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Storende elementen", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multifunctioneel", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Gebieden, talen", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Aangepast", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importeren…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Eén URL per regel. Ongeldige URL’s worden zonder mededeling genegeerd.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Verouderd.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "inhoud weergeven", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Laatst bijgewerkt: {{ago}}.\nKlik om een update af te dwingen.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Bijwerken…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Een netwerkfout heeft voorkomen dat de bron werd bijgewerkt.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Eén filter per regel. Een filter kan een gewone hostnaam of een EasyList-compatibel filter zijn. Regels beginnend met ! worden genegeerd.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Voeg geen filters van niet-vertrouwde bronnen toe.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importeren en toevoegen…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exporteren…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mijn-ublock-statische-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Wijzigingen toepassen", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanente regels", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Tijdelijke regels", + "description": "header" + }, + "rulesRevert": { + "message": "Terugzetten", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Vastleggen", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Bewerken", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Opslaan", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Annuleren", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importeren uit bestand…", + "description": "" + }, + "rulesExport": { + "message": "Exporteren naar bestand…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mijn-ublock-dynamische-regels_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lijst van uw dynamische filterregels.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regelsyntaxis: bron bestemming type actie (volledige documentatie).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sorteren:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Regeltype", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Bron", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Bestemming", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "De vertrouwde-website-instructies schrijven voor op welke webpagina’s uBlock Origin dient te worden uitgeschakeld. Eén vermelding per regel.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importeren en toevoegen…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exporteren…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mijn-ublock-vertrouwde-websites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Wijzigingen toepassen", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Type", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domein", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alles", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Achter de schermen", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Huidige tabblad", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "De tabbladinhoud vernieuwen", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "De DOM-inspector in-/uitschakelen", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Het pop-uppaneel in-/uitschakelen", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin-wiki: de logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Logger wissen", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Logger pauzeren (alle inkomende gegevens negeren)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Logger hervatten", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Loggerfiltering in-/uitschakelen", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "loggerinhoud filteren", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opties voor loggerfiltering", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Niet", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "afwisselend", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "geblokkeerd", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "toegestaan", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "aangepast", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "huidige domein", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "van derden", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Details", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterlijst", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Hoofdcontext", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "1e/3e partij", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL-regel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Type:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statisch filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "Netwerkaanvragen van {{type}} {{action}}{{br}}waarvan de URL overeenkomt met {{url}} {{br}}en die {{origin}} afkomstig zijn,{{br}}{{importance}} er een overeenkomstig uitzonderingsfilter bestaat.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "blokkeren", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "toestaan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type ‘{{type}}’", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "alle typen", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "van ‘{{origin}}’", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "van overal", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "behalve wanneer", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "zelfs als", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statisch filter {{filter}} gevonden in:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statisch filter kon niet in een van de momenteel ingeschakelde filterlijsten worden gevonden", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggervermeldingen die niet aan alle drie de onderstaande voorwaarden voldoen, worden automatisch genegeerd:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Vermeldingen van de laatste {{input}} minuten behouden", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Maximaal {{input}} paginalaadacties per tabblad behouden", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Maximaal {{input}} vermeldingen per tabblad behouden", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "{{input}} regels per vermelding in verticaal uitgevouwen modus gebruiken", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Kolommen verbergen:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tijd", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/regel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} 1e/3e partij", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lijst", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plat", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Openen", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Nieuwe melding maken", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Soortgelijke meldingen zoeken", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentatie", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lees de documentatie op uBlock/wiki voor meer info over alle functies van uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Vragen en ondersteuning", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Antwoorden op vragen en andere soorten ondersteuning worden geleverd op de subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterproblemen/website werkt niet", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Meld filterproblemen met specifieke websites in de uBlockOrigin/uAssets-probleemtracker. Vereist een GitHub-account.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Belangrijk: vermijd het gebruik van andere adblockers voor dezelfde doeleinden in combinatie met uBlock Origin, omdat dit op bepaalde websites problemen kan geven.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: zorg ervoor dat uw filterlijsten up-to-date zijn. De logger is het primaire hulpmiddel voor het analyseren van filtergerelateerde problemen.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bugmelding", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Meld problemen met uBlock Origin zelf in de uBlockOrigin/uBlock-issue-probleemtracker. Vereist een GitHub-account.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Probleemoplossingsinformatie", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Hieronder bevindt zich technische informatie die handig kan zijn wanneer vrijwilligers u proberen te helpen bij het oplossen van een probleem.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Belangrijk: mogelijk gevoelige of privégegevens worden standaard geredigeerd. Geredigeerde gegevens kunnen het oplossen van een probleem bemoeilijken.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Een filterprobleem melden", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Controleer of het probleem niet eerder is gemeld om te voorkomen dat vrijwilligers met dubbele meldingen worden belast.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlijsten worden dagelijks bijgewerkt. Controleer of uw probleem niet al in de meest recente filterlijsten is verholpen.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Controleer of het probleem nog steeds bestaat na vernieuwen van de problematische webpagina.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adres van de webpagina:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "De webpagina…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Maak een keuze --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Toont advertenties of restanten", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Heeft overlappingen of andere ongemakken", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detecteert uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Heeft privacy-gerelateerde problemen", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Werkt niet als uBlock Origin is ingeschakeld", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opent ongewenste tabbladen of vensters", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "De webpagina labelen als ‘NSFW’ (‘Not Safe For Work’)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redigeren", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Redigeren ongedaan maken", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacybeleid", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Wijzigingenlogboek", + "description": "" + }, + "aboutCode": { + "message": "Broncode (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Medewerkers", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Broncode", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Vertalingen", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlijsten", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Externe afhankelijkheden (GPLv3-compatibel):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO’s eigen filterlijsten zijn gratis beschikbaar op de volgende CDN’s:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Als een filterlijst moet worden bijgewerkt, wordt een willekeurig gekozen CDN gebruikt.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back-up maken naar bestand…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "mijn-ublock-back-up_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Terugzetten uit bestand…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Standaardinstellingen terugzetten…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Al uw instellingen zullen met back-upgegevens van {{time}} worden overschreven, en uBlock₀ zal worden herstart.\n\nWilt u alle bestaande instellingen met back-upgegevens overschrijven?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "De gegevens konden niet worden gelezen of zijn ongeldig", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Al uw instellingen zullen worden verwijderd, waarna uBlock₀ wordt herstart.\n\nStandaardinstellingen van uBlock₀ terugzetten?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Netwerkfout: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "De volgende URL aan uw lijsten met aangepaste filters toevoegen?\n\nTitel: ‘{{title}}’\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonneren", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "een minuut geleden", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuten geleden", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "een uur geleden", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} uur geleden", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "een dag geleden", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dagen geleden", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Dashboard tonen", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Logger tonen", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "uitgeschakeld", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pagina geblokkeerd", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin heeft het laden van de volgende pagina voorkomen:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "vanwege het volgende filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "zonder parameters", + "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:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Teruggaan", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Dit venster sluiten", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Mij niet meer waarschuwen over deze website", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Strenge blokkering voor {{hostname}} uitschakelen", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Tijdelijk", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanent", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Doorgaan", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exporteren naar cloudopslag", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importeren uit cloudopslag", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importeren uit cloudopslag en samenvoegen met huidige instellingen", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Naam van dit apparaat:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Waarschuwing! Wijzig deze geavanceerde instellingen op eigen risico.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Verzenden", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Wijzigingen toepassen", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Ongedaan maken", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Element in frame blokkeren…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonneren op filterlijst…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Grote media-elementen tijdelijk toestaan", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Broncode weergeven…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Typ een sneltoets", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Vergrendeld scrollen in-/uitschakelen", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiëren naar klembord", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Alles selecteren", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Cosmetische filters in-/uitschakelen", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Blokkeringsmodus beperken", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Gebruikte opslagruimte: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klik om te laden", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Fouten: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Kon niet goed filteren bij het starten van de browser. Vernieuw de pagina voor een juiste filtering.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/oc/messages.json b/src/_locales/oc/messages.json new file mode 100644 index 0000000..2c4b085 --- /dev/null +++ b/src/_locales/oc/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Enfin un blocador eficaç. Sollicita pauc lo CPU e la memòria", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Tablèu de bòrd", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Atencion ! Avètz de modificacions pas enregistradas", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Demorar", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorar", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Paramètres", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listas de filtre", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mos filtres", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mas règlas", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Lista blanca", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Acorchis", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Jornals d’eveniments", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "A prepaus", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Assisténcia", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visualizaira d’elements", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Paramètres avançats", + "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.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Clicatz per desactivar uBlock₀ per aqueste site\n\nCtrl+Clic per desactivar uBlock₀ sonque per aquesta pagina", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clicatz per activar uBlock₀ per aqueste site", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requèstas blocadas", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "sus aquesta pagina", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} o {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "dempuèi l’installacion", + "description": "English: since install" + }, + "popupOr": { + "message": "o", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocats sus aquesta pagina", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocats dempuèi l’installacion", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domenis connectats", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Dobrir lo tablèu de bòrd", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Passar en mòde Eliminador", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Passar en mòde Selector", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Dobrir la visualizaira d’eveniments", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Senhalar un problèma amb aqueste site web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clicatz per blocar las fenèstras sorgissentas d’aqueste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clicatz per blocar pas mai las fenèstras sorgissentas d’aqueste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clicatz per blocar los mèdias de granda talha d’aqueste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clicatz per blocar pas mai los mèdias de granda talha d’aqueste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clicatz per blocar las poliças distantas d’aqueste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clicatz per blocar pas mai las poliças distantas d’aqueste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Clicatz per desactivar JavaScript sus aqueste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Clicatz per quitar de desactivar JavaScript sus aqueste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Fenèstras sorgissentas", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Mèdias de granda talha", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtres cosmetics", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Poliças distantas", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mai", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mens", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Global rules: this column is for rules which apply to all 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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "totes", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imatges", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Tèrça partida", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripts en una linha", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domenis connectats", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Crear", + "description": "English: Create" + }, + "pickerPick": { + "message": "Causir", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Quitar", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Apercebut", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtres ret", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtres cosmetics", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blocar un element...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "De bon usar pels daltonians", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aparéncia", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tèmas", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Personalizar la color afortida", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Soi un-a utilizaire-a avandat-ada", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Compòrtament per defaut", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blocar las poliças distantas", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Desactivar JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avançat", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "paramètres avançats", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Darrièra restauracion :", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Darrièra salvagarda :", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Mesa a jorn auto de las listas", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Metre a jorn ara", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purgar totes los caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar las modificacions", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Integrats", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Publicitats", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Confidencialitat", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domenis malfasents", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, lengas", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizat", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importar...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "One URL per line. Invalid URLs will be silently ignored.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Obsolèt.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "veire contengut", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Darrièra actualizacion : {{ago}}.\nClicar per forçar la mesa a jorn.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Mesa a jorn...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importar e apondre", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportar", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mos-filtres-estatics-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar las modificacions", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Règlas permanentas", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Règlas temporàrias", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Modificar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Enregistrar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Anullar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Triar :", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipe de règla", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Font", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinacion", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar las modificacions", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipe", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domeni", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtre", + "description": "English: Filter" + }, + "logAll": { + "message": "Totes", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Onglet actual", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "autorizat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalhs", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtre", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista de filtre", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Règla", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contèxte", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipe", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Règla d’URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contèxte :", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipe :", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blocar", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Autorizar", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Hide columns:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tablèu", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Brut", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Dobrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentacion", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Senhalament d’avarias", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Politica de confidencialitat", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Jornal de modificacions", + "description": "" + }, + "aboutCode": { + "message": "Còdi font (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Còdi font", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduccions", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listas de filtres", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "S'abonar", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "fa una minuta", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "fa {{value}} minutas", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "fa una ora", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "fa {{value}} oras", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "a un jorn", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "fa {{value}} jorns", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pagina blocada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin a empachat lo cargament de la pagina seguenta :", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "A causa del filtre seguent :", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Trobat dins :", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Tornar", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Tampar aquesta fenèstra", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "M’assabentar pas mai per aqueste site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Desactivar lo blocatge estric del domeni {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporàriament", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentament", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Contunhar", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nom d’aqueste periferic :", + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Mandar", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplicar las modificacions", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Restablir", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "octets", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permetre temporàriament los elements mèdias larges", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Picar un acorchi", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiar al quichapapièrs", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Tot seleccionar", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Espaci emmagazinatge : {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "Ko", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "Mo", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "Go", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clicatz per cargar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/pa/messages.json b/src/_locales/pa/messages.json new file mode 100644 index 0000000..10438ef --- /dev/null +++ b/src/_locales/pa/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "ਆਖਰਕਾਰ ਪ੍ਰਭਾਵੀ ਬਲੌਕਰ ਹੈ। CPU ਅਤੇ ਮੈਮੋਰੀ ਲਈ ਸੌਖਾ।", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — ਡੈਸ਼ਬੋਰਡ", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "ਸਾਵਧਾਨ! ਤੁਹਾਡੇ ਕੋਲ ਨਾ-ਸੰਭਾਲੀਆਂ ਤਬਦੀਲੀਆਂ ਹਨ", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "ਰਹੋ", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "ਅਣਡਿੱਠਾ", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "ਸੈਟਿੰਗਾਂ", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "ਫਿਲਟਰ ਸੂਚੀਆਂ", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "ਮੇਰੇ ਫਿਲਟਰ", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "ਮੇਰੇ ਨਿਯਮ", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "ਭਰੋਸੇਯੋਗ ਸਾਈਟਾਂ", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "ਸ਼ਾਰਟਕੱਟ", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ਲੌਗਰ", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "ਇਸ ਬਾਰੇ", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "ਸਹਿਯੋਗ", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — ਸੰਪੱਤੀ ਦਰਸ਼ਕ", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "ਤਕਨੀਕੀ ਸੈਟਿੰਗਾਂ", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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\nਸਿਰਫ਼ ਇਸ ਸਫ਼ੇ ਲਈ uBlock₀ ਨੂੰ ਅਸਮਰੱਥ/ਸਮਰੱਥ ਕਰਨ ਲਈ Ctrl+ਕਲਿੱਕ ਕਰੋ।", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "ਇਸ ਸਾਈਟ ਲਈ uBlock₀ ਸਮਰੱਥ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ।", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "ਪਾਬੰਦੀ ਲਾਈਆਂ ਬੇਨਤੀਆਂ", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ਇਸ ਸਫ਼ੇ ਉੱਤੇ", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "ਇੰਸਟਾਲ ਕਰਨ ਤੋਂ ਬਾਅਦ", + "description": "English: since install" + }, + "popupOr": { + "message": "ਜਾਂ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "ਇਸ ਸਫ਼ੇ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਏ", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "ਇੰਸਟਾਲ ਹੋਣ ਤੋਂ ਬਾਅਦ ਪਾਬੰਦੀ ਲਾਏ", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "ਕਨੈਕਟ ਹੋਈਆਂ ਡੋਮੇਨਾਂ", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ਡੈਸ਼ਬੋਰਡ ਨੂੰ ਖੋਲ੍ਹੋ", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "ਲੌਗਰ ਖੋਲ੍ਹੋ", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "ਇਸ ਵੈੱਬਸਾਈਟ ਉੱਤੇ ਮਸਲੇ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਸਾਰੇ ਪੌਪ-ਅੱਪ ਉੱਤੇ ਪਾਬੰਦੀਆਂ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਸਾਰੇ ਪੌਪ-ਅੱਪ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਸਾਰੇ ਪੌਪ-ਅੱਪ ਉੱਤੇ ਪਾਬੰਦੀ ਨਾ ਲਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਵੱਡੇ ਮੀਡਿਆ ਭਾਗਾਂ ਉੱਤੇ ਪਾਬੰਦੀਆਂ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਵੱਡੇ ਮੀਡੀਆ ਭਾਗਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਵੱਡੇ ਮੀਡੀਆ ਭਾਗਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਹਟਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਦਿੱਖ ਫਿਲਟਰ ਕਰਨ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "ਇਸ ਸਾਈਟ ਉੱਤੇ ਦਿੱਖ ਫਿਲਟਰ ਕਰਨ ਨੂੰ ਅਸਮਰੱਥ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "ਇਸ ਸਾਈਟ ਉੱਤੇ ਦਿੱਖ ਫਿਲਟਰ ਕਰਨ ਨੂੰ ਸਮਰੱਥ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਰਿਮੋਟ ਫ਼ੌਂਟਾਂ ਉੱਤੇ ਪਾਬੰਦੀਆਂ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਰਿਮੋਟ ਫ਼ੌਂਟਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "ਇਸ ਸਾਈਟ ਲਈ ਰਿਮੋਟ ਫ਼ੌਂਟਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਹਟਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "ਇਸ ਸਾਈਟ ਉੱਤੇ JavaScript ਅਸਮਰੱਥ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "ਇਸ ਸਾਈਟ ਉੱਤੇ JavaScript ਅਸਮਰੱਥ ਕਰਨ ਨੂੰ ਹਟਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "ਪੌਪ-ਅੱਪ ਵਿੰਡੋ", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "ਵੱਡੇ ਮੀਡੀਆ ਭਾਗ", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "ਦਿੱਖ ਫਿਲਟਰ ਕਰਨਾ", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "ਰਿਮੋਟ ਫ਼ੌਂਟ", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "ਹੋਰ", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "ਘੱਟ", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "ਗਲੋਬਲ ਨਿਯਮ: ਇਹ ਕਾਲਮ ਸਾਰੀਆਂ ਸਾਈਟਾਂ ਉੱਤੇ ਲਾਗੂ ਹੋਣ ਵਾਲੇ ਨਿਯਮਾਂ ਲਈ ਹੈ।", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "ਲੋਕਲ ਨਿਯਮ: ਇਹ ਕਾਲਮ ਨਿਯਮਾਂ ਲਈ ਹੈ, ਜੋ ਕਿ ਸਿਰਫ਼ ਲੋਕਲ ਸਾਈਟਾਂ ਉੱਤੇ ਹੀ ਲਾਗੂ ਹੁੰਦੇ ਹਨ।\nਲੋਕਲ ਨਿਯਮ ਗਲੋਬਲ ਨਿਯਮਾਂ ਨੂੰ ਅਣਡਿੱਠਾ ਕਰਦੇ ਹਨ।", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "ਆਪਣੀਆਂ ਤਬਦੀਲੀਆਂ ਨੂੰ ਪੱਕਾ ਬਣਾਉਣ ਲਈ ਕਲਿੱਕ ਕਰੋ।", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "ਆਪਣੀਆਂ ਤਬਦੀਲੀਆਂ ਨੂੰ ਵਾਪਸ ਲੈਣ ਲਈ ਕਲਿੱਕ ਕਰੋ।", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "ਸਭ", + "description": "" + }, + "popupImageRulePrompt": { + "message": "ਚਿੱਤਰ", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "ਤੀਜੀ-ਧਿਰ", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "ਤੀਜੀ-ਧਿਰ CSS/ਚਿੱਤਰ", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ਇਨ-ਲਾਈਨ ਸਕ੍ਰਿਪਟਾਂ", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1ਲੀ-ਧਿਰ ਸਕ੍ਰਿਪਟਾਂ", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "ਤੀਜੀ-ਧਿਰ ਸਕ੍ਰਿਪਟਾਂ", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "ਤੀਜੀ-ਧਿਰ ਫਰੇਮ", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "ਕਨੈਕਟ ਹੋਈਆਂ ਡੋਮੇਨਾਂ", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} ਵਿੱਚੋਂ {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "ਵਰਜ਼ਨ", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "ਸਕ੍ਰਿਪਟ", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ਫਰੇਮ", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "ਬਣਾਓ", + "description": "English: Create" + }, + "pickerPick": { + "message": "ਚੁਣੋ", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "ਬਾਹਰ", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "ਝਲਕ", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ਨੈੱਟਵਰਕ ਫਿਲਟਰ", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "ਦਿੱਖ ਫਿਲਟਰ ਕਰਨਾ", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "ਕਲਿੱਕ, Ctrl-ਕਲਿੱਕ", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "ਭਾਗ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਓ…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ਪਾਬੰਦੀ ਲਾਏ ਭਾਗਾਂ ਲਈ ਸਥਾਨ ਨੂੰ ਓਹਲੇ ਕਰੋ", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "ਆਈਕਾਨ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਈਆਂ ਬੇਨਤੀਆਂ ਦੀ ਗਿਣਤੀ ਦਿਖਾਓ", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "ਟੂਲ-ਟਿੱਪ ਅਸਮਰੱਥ ਕਰੋ", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "ਜਦੋਂ ਵੀ ਵਾਜਬ ਹੋਵੇ ਤਾਂ ਪ੍ਰਸੰਗ ਮੇਨੂ ਨੂੰ ਵਰਤੋਂ", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "ਰੰਗ-ਅੰਨ੍ਹੇਪਣ ਲਈ ਸਰਲ", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "ਦਿੱਖ", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "ਥੀਮ", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "ਕਲਾਉਡ ਸਟੋਰੇਜ਼ ਸਹਾਇਤਾ ਸਮਰੱਥ ਕਰੋ", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "ਮੈਂ ਮਾਹਰ ਵਰਤੋਂਕਾਰ ਹਾਂ", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "ਪਹਿਲਾਂ-ਪ੍ਰਾਪਤ ਕਰਨਾ ਅਸਮਰੱਥ (ਪਾਬੰਦੀ ਲਾਈਆਂ ਨੈੱਟਵਰਕ ਬੇਨਤੀਆਂ ਲਈ ਕਿਸੇ ਵੀ ਕਨੈਕਸ਼ਨ ਨੂੰ ਰੋਕਣ ਲਈ)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "ਹਾਈਪਰ-ਲਿੰਕ ਪੜਤਾਲ ਨੂੰ ਅਸਮਰੱਥ ਕਰੋ", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC ਨੂੰ ਲੋਕਲ IP ਐਡਰੈਸ ਲੀਕ ਕਰਨ ਤੋਂ ਰੋਕੋ", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "ਮੂਲ ਰਵੱਈਆ", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "ਇਹ ਮੂਲ ਰਵੱਈਏ ਨੂੰ ਹਰ-ਸਟਾਈ ਮੁਤਾਬਕ ਅਣਡਿੱਠਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "ਦਿੱਖ ਫਿਲਟਰ ਕਰਨ ਨੂੰ ਅਸਮਰੱਥ ਕਰੋ", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input}} KB ਤੋਂ ਵੱਡੇ ਮੀਡੀਆ ਭਾਗਾਂ ਉੱਤੇ ਪਾਬੰਦੀ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "ਰਿਮੋਟ ਫ਼ੌਂਟਾਂ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਓ", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript ਅਸਮਰੱਥ ਕਰੋ", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP ਰਿਪੋਰਟਾਂ ਉੱਤੇ ਪਾਬੰਦੀ", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "ਤਕਨੀਕੀ", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "ਫ਼ੀਚਰ ਸਿਰਫ਼ ਤਕਨੀਕੀ ਮਾਹਰ ਵਰਤੋਂਕਾਰਾਂ ਲਈ ਢੁੱਕਵੇਂ ਹਨ", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "ਤਕਨੀਕੀ ਸੈਟਿੰਗਾਂ", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "ਪਿਛਲਾ ਰੀ-ਸਟੋਰ:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "ਪਿਛਲਾ ਬੈਕਅੱਪ:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} ਨੈੱਟਵਰਕ ਫਿਲਟਰ + {{cosmeticFilterCount}} ਦਿੱਖ ਫਿਲਟਰ, ਇੱਥੋਂ:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} ਵਿੱਚੋਂ {{used}} ਵਰਤੇ", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "ਫਿਲਟਰ ਸੂਚੀਆਂ ਆਪੇ ਅੱਪਡੇਟ ਕਰੋ", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "ਹੁਣੇ ਅੱਪਡੇਟ ਕਰੋ", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "ਸਭ ਕੈਸ਼ ਮਿਟਾਓ", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "ਦਿੱਖ ਫਿਲਟਰ ਨੂੰ ਪਾਰਸ ਅਤੇ ਲਾਗੂ ਕਰੋ", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "ਦਿੱਖ (cosmetic) ਫਿਲਟਰ ਵੈੱਬ ਸਫ਼ੇ ਉੱਤੇ ਅਜਿਹਾ ਭਾਗਾਂ ਨੂੰ ਲੁਕਾਉਂਦੇ ਹਨ, ਜੋ ਕਿ ਦਿੱਖ ਵਿੱਚ ਰੁਕਾਵਟ ਬਣਦੇ ਹਨ ਅਤੇ ਜਿਹਨਾਂ ਉੱਤੇ ਨੈੱਟਵਰਕ ਅਧਾਰਿਤ ਫਿਲਟਰ ਇੰਜਣਾਂ ਰਾਹੀਂ ਪਾਬੰਦੀ ਨਹੀਂ ਲਾਈ ਜਾ ਸਕਦੀ ਹੈ।", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "ਸਭ ਫਿਲਟਰ ਸੂਚੀਆਂ ਲੋਡ ਹੋਣ ਤੱਕ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਨੂੰ ਸਸਪੈਂਡ ਰੱਖੋ", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "ਤਬਦੀਲੀਆਂ ਲਾਗੂ ਕਰੋ", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "ਬਿਲਟ-ਇਨ", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "ਇਸ਼ਤਿਹਾਰ", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "ਪਰਦੇਦਾਰੀ", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "ਮਾਲਵੇਅਰਾਂ ਤੋਂ ਬਚਾਅ, ਸੁਰੱਖਿਆ", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "ਅਣਚਾਹੇ", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "ਬਹੁ-ਮਕਸਦੀ", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "ਖੇਤਰ, ਭਾਸ਼ਾਵਾਂ", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "ਕਸਟਮ", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "ਇੰਪੋਰਟ…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "ਹਰ ਲਾਈਨ ਵਿੱਚ ਇੱਕ URL। ਗਲਤ URL ਨੂੰ ਬਿਨਾਂ ਰੁਕੇ ਅਣਡਿੱਠਾ ਕੀਤਾ ਜਾਵੇਗਾ।", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "ਪੁਰਾਣਾ।", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ਸਮੱਗਰੀ ਵੇਖੋ", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "ਆਖਰੀ ਅੱਪਡੇਟ: {{ago}}।\nਅੱਪਡੇਟ ਲਈ ਮਜ਼ਬੂਰ ਕਰਨ ਵਾਸਤੇ ਕਲਿੱਕ ਕਰੋ।", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "…ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ਨੈੱਟਵਰਕ ਗਲਤੀ ਸਰੋਤ ਨੂੰ ਅੱਪਡੇਟ ਹੋਣ ਤੋਂ ਰੋਕਦੀ ਹੈ।", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "ਗ਼ੈਰ-ਭਰੋਸੇਯੋਗ ਸਰੋਤਾਂ ਤੋਂ ਫਿਲਟਰ ਨਾ ਜੋੜੋ।", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "ਇੰਪੋਰਟ ਕਰੋ ਤੇ ਜੋੜੋ…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "ਐਕਸਪੋਰਟ…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "ਤਬਦੀਲੀਆਂ ਲਾਗੂ ਕਰੋ", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "ਪੱਕੇ ਨਿਯਮ", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "ਆਰਜ਼ੀ ਨਿਯਮ", + "description": "header" + }, + "rulesRevert": { + "message": "ਵਾਪਸ ਲਵੋ", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "ਕਮਿਟ", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "ਸੋਧੋ", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "ਸੰਭਾਲੋ", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "ਖ਼ਾਰਜ", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "…ਫ਼ਾਈਲ ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ", + "description": "" + }, + "rulesExport": { + "message": "…ਫ਼ਾਈਲ ਉੱਤੇ ਐਕਸਪੋਰਟ ਕਰੋ", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "ਤੁਹਾਡੇ ਚਾਲੂ ਫਿਲਟਰ ਕਰਨ ਦੇ ਨਿਯਮਾਂ ਦੀ ਸੂਚੀ ਹੈ।", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "ਲੜੀਬੱਧ:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "ਨਿਯਮ ਦੀ ਕਿਸਮ", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "ਸਰੋਤ", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "ਇੰਪੋਰਟ ਕਰੋ ਤੇ ਜੋੜੋ…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "ਐਕਸਪੋਰਟ…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "ਤਬਦੀਲੀਆਂ ਲਾਗੂ ਕਰੋ", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "ਕਿਸਮ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ਡੋਮੇਨ", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "ਫਿਲਟਰ", + "description": "English: Filter" + }, + "logAll": { + "message": "ਸਭ", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "ਬਿਨ-ਟੈਬ", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "ਮੌਜੂਦਾ ਟੈਬ", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "ਟੈਬ ਸਮੱਗਰੀ ਮੁੜ-ਲੋਡ ਕਰੋ", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM ਇੰਸਪੈਕਟਰ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "ਪੌਪ-ਅੱਪ ਪੈਨਲ ਬਦਲੋ", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin ਵਿਕੀ: ਲੌਗਰ", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "ਲੌਗਰ ਮਿਟਾਓ", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "ਲੌਗਰ ਨੂੰ ਰੋਕੋ (ਸਭ ਆਉਣ ਵਾਲੇ ਡਾਟੇ ਨੂੰ ਅਣਡਿੱਠਾ ਕਰੋ)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "ਲੌਗਰ ਨੂੰ ਚਾਲੂ ਕਰੋ", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "ਲੌਗਰ ਫਿਲਟਰਾਂ ਨੂੰ ਬਦਲੋ", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "ਲੌਗਰ ਸਮੱਗਰੀ ਨੂੰ ਫਿਲਟਰ ਕਰੋ", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "ਲੌਗਰ ਫਿਲਟਰ ਕਰਨ ਲਈ ਚੋਣਾਂ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "ਨਹੀਂ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "ਪਾਬੰਦੀ ਲਾਏ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "ਮਨਜ਼ੂਰ ਕੀਤੇ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "ਸੋਧ ਕੀਤੇ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1ਲੀ-ਧਿਰ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3ਜੀ-ਧਿਰ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "ਵੇਰਵੇ", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ਫਿਲਟਰ", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "ਫਿਲਟਰ ਸੂਚੀ", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "ਨਿਯਮ", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "ਪਰਸੰਗ", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "ਰੂਟ ਪਰਸੰਗ", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "ਬਿਨ-ਧਿਰ", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "ਕਿਸਮ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL ਨਿਯਮ", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "ਪਰਸੰਗ:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "ਕਿਸਮ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "ਪਾਬੰਦੀ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "ਮਨਜ਼ੂਰ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "ਕਿਸਮ “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ਕੋਈ ਵੀ ਕਿਸਮ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}” ਤੋਂ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "ਕਿਸੇ ਵੀ ਥਾਂ ਤੋਂ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "ਛੋਟ ਜਦੋਂ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "ਭਾਵੇਂ ਜੇ", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "ਪਿਛਲੇ {{input}} ਮਿੰਟਾਂ ਤੋਂ ਐਂਟਰੀਆਂ ਰੱਖੋ", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "ਕਾਲਮ ਲੁਕਾਓ:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} ਸਮਾਂ", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} ਫਿਲਟਰ/ਨਿਯਮ", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} ਪਰਸੰਗ", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} ਬਿਨ-ਧਿਰ", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "ਸੂਚੀ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "ਸਾਰਣੀ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "ਸਰਲ", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "ਮਾਰਕਡਾਊਨ", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "ਖੋਲ੍ਹੋ", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "ਨਵੀਂ ਰਿਪੋਰਟ ਬਣਾਓ", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "ਰਲਦੀਆਂ ਰਿਪੋਰਟਾਂ ਲੱਭੋ", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "ਦਸਤਾਵੇਜ਼", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock Origin ਦੇ ਸਾਰੇ ਫੀਚਰਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਲੈਣ ਲਈ uBlock/wiki ਤੋਂ ਦਸਤਾਵੇਜ਼ ਪੜ੍ਹੋ।", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "ਸਮੱਸਿਆ ਹੱਲ ਕਰਨ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "ਹੇਠਾਂ ਤਕਨੀਕੀ ਜਾਣਕਾਰੀ ਦਿੱਤੀ ਹੈ, ਜੋ ਕਿ ਵਲੰਟੀਅਰਾਂ ਲਈ ਮਦਦਗਾਰ ਹੋ ਸਕਦੀ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਸਮੱਸਿਆ ਹੱਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ ਕਰਦੇ ਹਨ।", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "ਖਾਸ: ਸੰਭਾਵਿਤ ਤੌਰ ਉੱਤੇ ਪ੍ਰਾਈਵੇਟ ਜਾਂ ਸੰਵੇਦਨਸ਼ੀਲ ਜਾਣਕਾਰੀ ਨੂੰ ਮੂਲ ਰੂਪ ਵਿੱਚ ਛਾਂਟ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਛਾਂਂਟੀ ਕੀਤੀ ਜਾਣਕਾਰੀ ਸਮੱਸਿਆ ਨੂੰ ਹੱਲ ਕਰਨਾ ਵੱਧ ਔਖਾ ਬਣਾ ਸਕਦੀ ਹੈ।", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "ਫਿਲਟਰ ਮਸਲੇ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "ਵਲੰਟੀਅਰਾਂ ਕੋਲ ਡੁਪਲੀਕੇਟ ਰਿਪੋਰਟਾਂ ਦਾ ਕੰਮ ਵਧਾਉਣ ਤੋਂ ਬਚਣ ਲਈ ਕਿਰਪਾ ਕਰਕੇ ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਮਸਲਾ ਕਿਤੇ ਪਹਿਲਾਂ ਰਿਪੋਰਟ ਤਾਂ ਨਹੀ ਕੀਤਾ ਹੋਇਆ ਹੈ।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "ਫਿਲਟਰ ਸੂਚੀਆਂ ਰੋਜ਼ ਅੱਪਡੇਟ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਕਿਤੇ ਤੁਹਾਡਾ ਮਸਲਾ ਪਹਿਲਾਂ ਹੀ ਸਭ ਤੋਂ ਤਾਜ਼ਾ ਫਿਲਟਰ ਸੂਚੀਆਂ ਰਾਹੀਂ ਹੱਲ ਤਾਂ ਨਹੀਂ ਹੋ ਚੁੱਕਿਆ ਹੈ।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "ਸਮੱਸਿਆ ਵਾਲੇ ਵੈੱਬ-ਸਫ਼ੇ ਨੂੰ ਮੁੜ-ਲੋਡ ਕਰਨ ਦੇ ਬਾਅਦ ਜਾਂਚ ਕਰੋ ਕਿ ਕੀ ਮਸਲਾ ਹਾਲੇ ਵੀ ਮੌਜੂਦ ਹੈ।", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "ਵੈੱਬ ਸਾਈਟ ਦਾ ਸਿਰਨਾਵਾਂ:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "ਵੈੱਬ ਸਫ਼ਾ…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- ਐਂਟਰੀ ਚੁਣੋ --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "ਇਸ਼ਤਿਹਾਰ ਜਾਂ ਇਸ਼ਤਿਹਾਰ ਦੀ ਰਹਿੰਦ-ਖੂੰਦ ਦਿਖਾਉਂਦਾ ਹੈ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin ਖੋਜਦਾ ਹੈ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "ਪਰਦੇਦਾਰੀ ਸੰਬੰਧੀ ਮਸਲੇ ਹਨ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin ਸਮਰੱਥ ਕਰਨ ਦੇ ਬਾਅਦ ਗੜਬੜ ਹੁੰਦੀ ਹੈ", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "ਪਰਦੇਦਾਰੀ ਨੀਤੀ", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "ਤਬਦੀਲੀ-ਸੂਚੀ", + "description": "" + }, + "aboutCode": { + "message": "ਸਰੋਤ ਕੋਡ (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "ਯੋਗਦਾਨੀ", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "ਸਰੋਤ ਕੋਡ", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "ਅਨੁਵਾਦ", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "ਫਿਲਟਰ ਸੂਚੀਆਂ", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "ਬਾਹਰੀ ਨਿਰਭਰਤਾਵਾਂ (GPLv3-ਅਨੁਕੂਲ):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ਫ਼ਾਈਲ ਤੋਂ ਬੈਕਅੱਪ ਲਵੋ…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "…ਫ਼ਾਈਲ ਤੋਂ ਬਹਾਲ ਕਰੋ", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "ਡਾਟਾ ਪੜ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ ਜਾਂ ਗ਼ੈਰ-ਵਾਜਬ ਹੈ", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "ਤੁਹਾਡੀਆਂ ਸਾਰੀਆਂ ਸੈਟਿੰਗਾਂ ਨੂੰ ਹਟਾਇਆ ਜਾਵੇਗਾ ਅਤੇ uBlock₀ ਮੁੜ-ਚਾਲੂ ਹੋਵੇਗਾ।\n\nਕੀ uBlock₀ ਨੂੰ ਫੈਕਟਰੀ ਸੈਟਿੰਗਾਂ ਲਈ ਮੁੜ-ਸੈੱਟ ਕਰਨਾ ਹੈ?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "ਨੈੱਟਵਰਕ ਗਲਤੀ: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "ਕੀ ਅੱਗੇ ਦਿੱਤੇ URL ਨੂੰ ਤੁਹਾਡੀਆਂ ਕਸਟਮ ਫਿਲਟਰ ਸੂਚੀਆਂ ਵਿੱਚ ਜੋੜਨਾ ਹੈ?\n\nਨਾਂ: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "ਮੈਂਬਰ ਬਣੋ", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ਮਿੰਟ ਪਹਿਲਾਂ", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} ਮਿੰਟ ਪਹਿਲਾਂ", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ਘੰਟਾ ਪਹਿਲਾਂ", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ਘੰਟੇ ਪਹਿਲਾਂ", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ਇੱਕ ਦਿਨ ਪਹਿਲਾਂ", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} ਦਿਨ ਪਹਿਲਾਂ", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "ਡੈਸ਼ਬੋਰਡ ਵੇਖਾਓ", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "ਲੌਗਰ ਵੇਖਾਓ", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "ਬੰਦ", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "ਸਫ਼ੇ ਉੱਤੇ ਪਾਬੰਦੀ ਹੈ", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin ਨੇ ਅੱਗੇ ਦਿੱਤੇ ਸਫ਼ੇ ਨੂੰ ਲੋਡ ਹੋਣ ਤੋਂ ਰੋਕਿਆ ਹੈ:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "ਅੱਗੇ ਦਿੱਤੇ ਫਿਲਟਰ ਕਰਕੇ:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "ਲੱਭੋ:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "ਪਿੱਛੇ ਜਾਓ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "ਇਹ ਵਿੰਡੋ ਬੰਦ ਕਰੋ", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "ਇਸ ਸਾਈਟ ਬਾਰੇ ਮੈਨੂੰ ਮੁੜ ਚੇਤਾਵਨੀ ਨਾ ਦਿਓ", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}} ਲਈ ਸਖ਼ਤ ਪਾਬੰਦੀਆਂ ਲਾਉਣਾ ਅਸਮਰੱਥ ਕਰੋ", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "ਆਰਜ਼ੀ", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "ਪੱਕੇ ਤੌਰ ਉੱਤੇ", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "ਜਾਰੀ ਰੱਖੋ", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "ਕਲਾਉਡ ਸਟੋਰੇਜ਼ ਉੱਤੇ ਐਕਸਪੋਰਟ ਕਰੋ", + "description": "tooltip" + }, + "cloudPull": { + "message": "ਕਲਾਉਡ ਸਟੋਰੇਜ਼ ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "ਕਲਾਉਡ ਸਟੋਰੇਜ਼ ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ ਅਤੇ ਮੌਜੂਦਾ ਸੈਟਿੰਗਾਂ ਨਾਲ ਮਿਲਾਓ", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "ਇਸ ਡਿਵਾਈਸ ਦਾ ਨਾਂ:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "ਸਾਵਧਾਨ! ਇਹ ਤਕਨੀਕੀ ਸੈਟਿੰਗਾਂ ਨੂੰ ਆਪਣੇ ਖ਼ਤਰੇ ਮੁਤਾਬਕ ਬਦਲੋ।", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "ਭੇਜੋ", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "ਤਬਦੀਲੀਆਂ ਲਾਗੂ ਕਰੋ", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "ਵਾਪਸ ਲਵੋ", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "ਬਾਈਟ", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "ਫਰੇਮ ਵਿੱਚ ਭਾਗ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਈ…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "ਫਿਲਟਰ ਸੂਚੀ ਲਈ ਮੈਂਬਰ ਬਣੋ…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "ਆਰਜ਼ੀ ਤੌਰ ਉੱਤੇ ਵੱਡੇ ਮੀਡੀਆ ਭਾਗਾਂ ਨੂੰ ਮਨਜ਼ੂਰੀ ਦਿਓ", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "ਸਰੋਤ ਕੋਡ ਵੇਖੋ…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "ਸ਼ਾਰਟਕੱਟ ਲਿਖੋ", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "ਕਲਿੱਪਬੋਰਡ ਵਿੱਚ ਕਾਪੀ ਕਰੋ", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "ਸਭ ਚੁਣੋ", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "ਵਰਤੀ ਗਈ ਸਟੋਰੇਜ਼: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "ਲੋਡ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/pl/messages.json b/src/_locales/pl/messages.json new file mode 100644 index 0000000..3b2d7cf --- /dev/null +++ b/src/_locales/pl/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Nareszcie skuteczny bloker charakteryzujący się niskim użyciem procesora i pamięci.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ – Panel sterowania", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Uwaga! Masz niezapisane zmiany", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Zostań", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignoruj", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ustawienia", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listy filtrów", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Moje filtry", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Moje reguły", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Zaufane witryny", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Skróty", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ – Rejestrator", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O rozszerzeniu", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Pomoc techniczna", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ – Podgląd zasobu", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Ustawienia zaawansowane", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Kliknij, aby wyłączyć uBlock₀ dla tej witryny.\n\nKliknij z wciśniętym klawiszem Ctrl,\naby wyłączyć uBlock₀ tylko dla tej strony.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknij, aby wyłączyć uBlock₀ dla tej witryny.\n\nKliknij z wciśniętym klawiszem Ctrl, aby wyłączyć uBlock₀ tylko dla tej strony.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknij, aby włączyć uBlock₀ dla tej witryny.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "zablokowane żądania", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na tej stronie", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od instalacji", + "description": "English: since install" + }, + "popupOr": { + "message": "lub", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Zablokowane na tej stronie", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Zablokowane od instalacji", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domeny podłączone", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Otwórz panel sterowania", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Przejdź do trybu usuwania elementów", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Przejdź do trybu zaznaczania elementów", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Otwórz rejestrator", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Zgłoś problem z tą stroną", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Włącz/wyłącz blokowanie wyskakujących okien na tej witrynie", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknij, aby zablokować wszystkie wyskakujące okna na tej witrynie", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknij, aby nie blokować wyskakujących okien na tej witrynie", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Włącz/wyłącz blokowanie dużych elementów multimedialnych na tej witrynie", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknij, aby zablokować duże elementy multimedialne na tej witrynie", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknij, aby nie blokować dużych elementów multimedialnych na tej witrynie", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Włącz/wyłącz kosmetyczne filtrowanie na tej witrynie", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknij, aby wyłączyć filtrowanie kosmetyczne na tej witrynie", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknij, aby włączyć filtrowanie kosmetyczne na tej witrynie", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Włącz/wyłącz blokowanie zdalnych czcionek na tej witrynie", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknij, aby zablokować zdalne czcionki na tej witrynie", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknij, aby nie blokować zdalnych czcionek na tej witrynie", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kliknij, aby wyłączyć JavaScript na tej witrynie", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kliknij, aby JavaScript nie był już wyłączony na tej witrynie", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Wyskakujące okna", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Duże elementy multimedialne", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtrowanie kosmetyczne", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Zdalne czcionki", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Więcej", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mniej", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Reguły globalne:\nW tej kolumnie znajdują się reguły stosowane na wszystkich witrynach.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Reguły lokalne:\nW tej kolumnie znajdują się reguły stosowane tylko na bieżącej witrynie.\nReguły lokalne zastępują reguły globalne.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknij, aby zastosować zmiany na stałe.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknij, aby odrzucić zmiany.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "wszystko", + "description": "" + }, + "popupImageRulePrompt": { + "message": "obrazki", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "domeny zewnętrzne", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "zewnętrzne CSS/obrazki", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "zagnieżdżone skrypty", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skrypty własne", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skrypty z domen zewnętrznych", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "ramki z domen zewnętrznych", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "podłączone domeny", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} z {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Wersja", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skrypt", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ramka", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Utwórz", + "description": "English: Create" + }, + "pickerPick": { + "message": "Wybierz", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Zamknij", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Podgląd", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtry sieciowe", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtry kosmetyczne", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl + klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Zablokuj element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ukrywaj symbole zastępcze zablokowanych elementów", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Wyświetlaj liczbę zablokowanych żądań na ikonie rozszerzenia", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Nie wyświetlaj dymków podpowiedzi", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Używaj menu kontekstowego, gdzie to możliwe", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Interfejs przyjazny osobom z zaburzeniami widzenia kolorów", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Wygląd", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Motyw", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Własny kolor akcentujący", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Włącz obsługę zapisu ustawień w chmurze", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Jestem zaawansowanym użytkownikiem", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Wyłącz wstępne pobieranie (by uniknąć połączeń z zablokowanymi zapytaniami sieciowymi)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Wyłącz śledzenie kliknięć odnośników", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Zapobiegaj ujawnianiu lokalnego adresu IP poprzez interfejs WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Działanie domyślne", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Te ustawienia mogą być zastąpione przez ustawienia danej witryny", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Wyłącz filtrowanie kosmetyczne", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokuj elementy multimedialne większe niż {{input}} KiB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokuj zdalne czcionki", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Wyłącz JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokuj raporty CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Pokaż rzeczywistą nazwę domeny (CNAME)", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Zaawansowane", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkcje odpowiednie tylko dla użytkowników z przygotowaniem technicznym", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Ustawienia zaawansowane", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Ostatnie przywrócenie wykonano:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Ostatnią kopię zapasową wykonano:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "Filtry sieciowe: {{netFilterCount}} + filtry kosmetyczne: {{cosmeticFilterCount}} z:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "użytych {{used}} z {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automatycznie aktualizuj listy filtrów", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Zaktualizuj teraz", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Wyczyść całą pamięć podręczną", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Przetwarzaj i stosuj filtry kosmetyczne", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Filtry kosmetyczne służą do ukrywania elementów stron internetowych uważanych za wizualne uciążliwe, które to nie mogą zostać zablokowane za pomocą filtrów żądań sieciowych.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignoruj ogólne filtry kosmetyczne", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Ogólne filtry kosmetyczne, to filtry które mają być zastosowane na wszystkich stronach internetowych. Włącznie tej funkcji zmniejszy obciążenie procesora i pamięci.\n\nZaleca się włączenie tej funkcji na mniej wydajnych urządzeniach.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Zawieś aktywność sieciową do czasu załadowania wszystkich list filtrów", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listy zablokowanych hostów", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Zastosuj zmiany", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Wbudowane", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamy", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Prywatność", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Ochrona przed malware, bezpieczeństwo", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Elementy irytujące", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Wielofunkcyjne", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regiony, języki", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Własne", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importuj…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Jeden adres URL listy na linię. Błędne adresy URL będą pomijane.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Nieaktualna.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "zobacz zawartość", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Zaktualizowano: {{ago}}.\nKliknij, aby wymusić aktualizację.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Aktualizowanie…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Błąd sieci uniemożliwił aktualizację zasobów.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "W wierszu może być tylko jeden filtr. Filtrem może być nazwa hosta lub filtr kompatybilny z EasyList. Wiersze poprzedzone znakiem ! będą pomijane.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nie dodawaj filtrów z niezaufanych źródeł.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importuj i dołącz…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksportuj…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-statyczne-filtry_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Zastosuj zmiany", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Stałe reguły", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Tymczasowe reguły", + "description": "header" + }, + "rulesRevert": { + "message": "Przywróć", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Zatwierdź", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Edytuj", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Zapisz", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Odrzuć", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importuj z pliku…", + "description": "" + }, + "rulesExport": { + "message": "Eksportuj do pliku…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-dynamiczne-reguly_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista reguł dynamicznego filtrowania.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Składnia reguły: źródło cel typ akcja (pełna dokumentacja).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortowanie:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Typ reguły", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Źródło", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Miejsce docelowe", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Wytyczne zaufanych witryn nakazują, na których stronach uBlock Origin powinien zostać wyłączony. Jeden wpis na linię.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importuj i dołącz…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksportuj…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-zaufane-witryny_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Zastosuj zmiany", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Typ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domena", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Adres URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtr", + "description": "English: Filter" + }, + "logAll": { + "message": "Wszystkie", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Bez kart", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktywna karta", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Przeładuj zawartość karty", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Przełącz inspektor DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Przełącz panel popup", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Rejestrator (ang.)", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Wyczyść rejestr", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pauzuj rejestrowanie (porzuć wszystkie przychodzące dane)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Wznów rejestrowanie", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Przełącz filtrowanie rejestru", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtruj zawartość rejestru", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opcje filtrowania rejestru", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nie", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "akcje", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "zablokowane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "dozwolone", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "zmodyfikowane", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "własna domena", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "domeny zewnętrzne", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Szczegóły", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtr", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista filtrów", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Reguła", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontekst", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Kontekst główny", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Lokalność", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Typ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Adres URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Reguła URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontekst:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Typ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtr statyczny", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} żądania sieciowe {{type}}, których adres URL jest zgodny z: {{url}} {{br}}i pochodzi {{origin}}, {{importance}} filtr znajduje się na liście wyjątków.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokuj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Zezwalaj na", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "typu „{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "każdego typu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "z „{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "z dowolnego miejsca", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "z wyjątkiem, gdy", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "nawet, jeśli", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtr statyczny {{filter}} znajdujący się w:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Filtr statyczny nie został znaleziony w aktualnie włączonych listach filtrów", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Wpisy rejestru niespełniające wszystkich trzech warunków będą automatycznie porzucane:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Zachowuj wpisy z ostatnich {{input}} minut", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Zachowuj nie więcej niż {{input}} przeładowań strony na kartę", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Zachowuj nie więcej niż {{input}} wpisów na kartę", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Użyj {{input}} linie na wpis w widoku poszerzonym", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ukryj kolumny:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Czas", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtr/reguła", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontekst", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Lokalność", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabela", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Bez formatowania", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Otwórz", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Utwórz nowy raport", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Znajdź podobne raporty", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacja", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Przeczytaj dokumentację na uBlock/wiki, by nauczyć się obsługi uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Pytania oraz pomoc", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odpowiedzi na pytania oraz inne rodzaje pomocy są udzielane na subreddicie /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemy z filtrami/błędy w wyświetlaniu stron", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Zgłoś problemy z filtrami na poszczególnych stronach na trackerze błędów uBlockOrigin/uAssets. Wymaga konta GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Ważne: Unikaj innych podobnie działających dodatków razem z uBlock Origin, ponieważ może to powodować problemy z filtrami na poszczególnych stronach.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Porada: Upewnij się, że listy filtrów są aktualne. Rejestrator jest głównym narzędziem do diagnozowania problemów związanych z filtrami.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Zgłaszanie błędów", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Zgłoś problemy związane bezpośrednio z uBlock Origin na trackerze błędów uBlockOrigin/uBlock-issue. Wymaga konta GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informacje pomocne w rozwiązywaniu problemów", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Poniżej znajdują się informacje techniczne które mogą być użyteczne gdy wolontariusze próbują pomóc ci w rozwiązaniu problemu.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Ważne: Potencjalnie prywatne lub wrażliwe informacje są domyślnie ocenzurowane. Ocenzurowanie może utrudnić rozwiązanie problemu.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Zgłoś problem z filtrem", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Listy filtrów są aktualizowane codziennie. Sprawdź, czy twój problem nie został już rozwiązany w najnowszych listach filtrów.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Sprawdź, czy problem nadal występuje po odświeżeniu problematycznej strony internetowej.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adres strony internetowej:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Strona internetowa…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "— Wybierz pozycję —", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Wyświetla reklamy lub ich pozostałości", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ma nakładki lub inne niedogodności", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Wykrywa uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ma problemy związane z prywatnością", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Działa nieprawidłowo, gdy włączony jest uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Otwiera niepożądane karty lub okna", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Oznacz stronę internetową jako „NSFW” („Not Safe For Work (nieodpowiednią w pracy)”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Ocenzuruj", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Nie cenzuruj", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Polityka prywatności", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Informacje o wydaniu", + "description": "" + }, + "aboutCode": { + "message": "Kod źródłowy (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Współtwórcy", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kod źródłowy", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tłumaczenia", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listy filtrów", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Zewnętrzne zależności (kompatybilne z GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Własne listy filtrów uBO są dobrowolnie hostowane w następujących sieciach CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Losowo wybrana sieć CDN zostanie użyta, gdy lista filtrów będzie wymagała aktualizacji.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Utwórz kopię zapasową…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-kopia-zapasowa_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Przywróć kopię z pliku…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Przywróć ustawienia domyślne…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Wszystkie twoje ustawienia zostaną zastąpione ustawieniami z kopii stworzonej {{time}}. Po zakończeniu uBlock₀ zostanie uruchomiony ponownie.\n\nPrzywrócić ustawienia z kopii zapasowej?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Danych nie można odczytać lub są nieprawidłowe", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Wszystkie twoje ustawienia zostaną usunięte i uBlock₀ zostanie ponownie uruchomiony.\n\nCzy chcesz przywrócić ustawienia domyślne?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Błąd sieci: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Dodać następujący URL do twoich list filtrów?\n\nTytuł: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subskrybuj", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "minutę temu", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} min. temu", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "godzinę temu", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} godz. temu", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "wczoraj", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dni temu", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Panel sterowania", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Pokaż rejestrator", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "wyłączony", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Strona zablokowana", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin zablokował wczytywanie następującej strony:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Powodem zablokowania jest filtr", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametrów", + "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": "Filtr znajduje się na liście:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Wstecz", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zamknij to okno", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Nie ostrzegaj mnie ponownie o tej stronie", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Wyłącz rygorystyczne blokowanie dla {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Tymczasowo", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Na stałe", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Kontynuuj", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksportuj do chmury", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importuj z chmury", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importuj z chmury i połącz z aktualnymi ustawieniami", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nazwa urządzenia:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Uwaga! Te ustawienia zmieniasz na własne ryzyko.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Wyślij", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Zastosuj zmiany", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Przywróć", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajty", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Zablokuj element w ramce…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subskrybuj listę filtrów…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Tymczasowo zezwalaj na wyświetlanie dużych elementów multimedialnych", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Pokaż źródło…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Wprowadź skrót", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Przełącz przewijanie synchroniczne", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiuj do schowka", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Zaznacz wszystko", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Włącz/wyłącz filtrowanie kosmetyczne", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Rozluźnij tryb blokowania", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Użycie pamięci dyskowej: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kliknij, aby załadować", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Błędy: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Podczas uruchamiania przeglądarki nie można prawidłowo filtrować.\nAby zapewnić prawidłowe filtrowanie, wczytaj ponownie stronę.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Ten wpis musi być ostatni", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json new file mode 100644 index 0000000..e644a4d --- /dev/null +++ b/src/_locales/pt_BR/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finalmente, um bloqueador eficiente. Com baixo uso de memória e CPU.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Painel", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Aviso! Você tem mudanças não salvas", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Ficar", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorar", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Configurações", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listas de filtros", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Meus filtros", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Minhas regras", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Sites confiáveis", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Atalhos", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Coletor", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Sobre", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Suporte", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visualizador de recursos", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Configurações avançadas", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clique: desativa/ativa o uBlock₀ neste site.\n\nCtrl+clique: desativa o uBlock₀ só nesta página.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Clique pra desativar o uBlock₀ neste site.\n\nCtrl+clique pra desativar o uBlock₀ só nesta página.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clique pra ativar o uBlock₀ neste site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "requisições bloqueadas", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "nesta página", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "desde a instalação", + "description": "English: since install" + }, + "popupOr": { + "message": "ou", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloqueado(s) nesta página", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloqueado(s) desde a instalação", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domínios conectados", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Abrir painel", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Entrar no modo do elemento zapper", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Entrar no modo de seleção de elemento", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Abrir o coletor", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Reportar um problema com este site da web", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alternar o bloqueio de todos os pop-ups neste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clique pra bloquear todos os pop-ups neste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clique pra não mais bloquear todos os pop-ups neste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Alternar o bloqueio de grandes elementos de mídia neste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clique pra bloquear grandes elementos de mídia neste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clique pra não mais bloquear grandes elementos de mídia neste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Alternar a filtragem cosmética neste site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Clique pra desativar a filtragem cosmética neste site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Clique pra ativar a filtragem cosmética neste site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Alternar o bloqueio de fontes remotas neste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clique pra bloquear fontes remotas neste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clique pra não mais bloquear fontes remotas neste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Clique pra desativar o JavaScript neste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Clique pra não mais desativar o JavaScript neste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Janelas pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Grandes elementos de mídia", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtragem cosmética", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fontes remotas", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mais", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menos", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Regras globais: esta coluna é para as regras as quais se aplicam a todos os sites.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Regras locais: esta coluna é para regras as quais se aplicam só ao site atual.\nRegras locais substituem regras globais.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Clique pra tornar suas mudanças permanentes.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Clique pra reverter suas mudanças.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "todos", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imagens", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "de terceiros", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/Imagens de terceiros", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripts inline", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts primários", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts de terceiros", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames de terceiros", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domínios conectados", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versão", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Criar", + "description": "English: Create" + }, + "pickerPick": { + "message": "Escolher", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Sair", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Pré-visualizar", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtros de rede", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtros cosméticos", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clique, Ctrl-clique", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloquear elemento...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ocultar os espaços reservados dos elementos bloqueados", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Mostrar o número de requisições bloqueadas no ícone", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Desativar dicas das ferramentas", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Fazer uso do menu de contexto aonde apropriado", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Cores amigáveis para daltônicos", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aparência", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Cor de destaque personalizada", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Ativar suporte de armazenamento na nuvem", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Eu sou um usuário avançado", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Desativar pré-busca (pra impedir quaisquer requisições de redes bloqueadas)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Desativar auditoria dos hyperlinks", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Impedir o WebRTC de vazar endereços de IP locais", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportamento padrão", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Estes comportamentos padrão podem ser substituídos numa base por site", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Desativar filtragem cosmética", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloquear elementos de mídia maiores do que {{input}} KBs", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloquear fontes remotas", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Desativar JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloquear relatórios do CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Revelar nomes canônicos", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avançado", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Recursos adequados só pra usuários técnicos.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "configurações avançadas", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Última restauração:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Último backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtros de rede + {{cosmeticFilterCount}} filtros cosméticos de:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} usados de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-atualizar as listas de filtros", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Atualizar agora", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Limpar todos os caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analisar e impor filtros cosméticos", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Os filtros cosméticos servem pra esconder elementos de uma página da web os quais são considerados um incômodo visual e os quais não podem ser bloqueados pelas engines de filtragem baseadas em requisições de rede.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorar filtros cosméticos genéricos", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Os filtros cosméticos genéricos são aqueles filtros cosméticos os quais são destinados a serem aplicados em todos os sites da web. Ativar esta opção eliminará a sobrecarga da memória e da CPU adicionada as páginas da web como um resultado de lidar com filtros cosméticos genéricos.\n\nÉ recomendado ativar esta opção em dispositivos menos poderosos.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspender atividade da rede até que todas as listas de filtros estejam carregadas", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listas de hospedeiros bloqueados", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar mudanças", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Embutidos", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Anúncios", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacidade", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Proteção contra malware, segurança", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Aborrecimentos", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multi-propósito", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regiões, idiomas", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizar", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importar...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Uma URL por linha. As URLs inválidas serão ignoradas silenciosamente.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Desatualizada.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "visualizar conteúdo", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Última atualização: {{ago}}.\nClique para forçar uma atualização.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Atualizando...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Um erro de rede impediu o recurso de ser atualizado.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Um filtro por linha. Um filtro pode ser um simples nome de hospedeiro ou um filtro compatível com o EasyList. As linhas prefixadas com o ! serão ignoradas.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Não adicionar filtros de fontes não confiáveis.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importar e anexar", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportar", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "meus-filtros-estáticos-do-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar mudanças", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Regras permanentes", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Regras temporárias", + "description": "header" + }, + "rulesRevert": { + "message": "Reverter", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Submeter", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Editar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Salvar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Descartar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importar do arquivo...", + "description": "" + }, + "rulesExport": { + "message": "Exportar pro arquivo", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "minhas-regras-dinâmicas-do-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista das suas regras de filtragem dinâmica.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regras da sintaxe: ação do tipo de destino da origem (documentação completa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Organizar:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipo de regra", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Fonte", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destino", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "As diretivas dos sites confiáveis ditam em quais páginas da web o uBlock Origin deve ser desativado. Uma entrada por linha. ", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importar e anexar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "meus-sites-confiaveis-do-ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar mudanças", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domínio", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtro", + "description": "English: Filter" + }, + "logAll": { + "message": "Todos", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Sem abas", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aba atual", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Recarregar o conteúdo da aba", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Alternar o inspetor do DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Alternar o painel do pop-up", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "Wiki do uBlock Origin: O coletor", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Limpar coletor", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausar coletor (descartar todos os dados que entram)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Despausar coletor", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Alternar filtragem do coletor", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrar conteúdo do coletor", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opções de filtragem do coletor", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Não", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "importante", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloqueado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permitido", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "primário", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "de terceiros", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalhes", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtro", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista de filtros", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regra", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contexto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contexto raiz", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Grupos", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Regra da URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contexto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtro estático", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} requisições da rede de {{type}} {{br}}cujo endereço de URL corresponde {{url}} {{br}}e o qual se origina em {{origin}},{{br}}{{importance}} há um filtro de exceção correspondente.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloquear", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permitir", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "qualquer tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "de “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "de qualquer lugar", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "exceto quando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "mesmo se", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtro estático {{filter}} achado em:", + "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 achado em nenhuma das listas de filtros ativadas atualmente", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "As entradas do coletor que não preencherem todas as três condições abaixo serão descartadas automaticamente:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preservar entradas dos últimos {{input}} minutos", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preservar no máximo {{input}} carregamentos de página por aba", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preservar no máximo {{input}} entradas por aba", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Usar {{input}} linhas por entrada no modo expandido verticalmente", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ocultar colunas:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Hora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtro/regra", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contexto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Grupos", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabela", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Simples", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Formatação", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Abrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Criar um novo relatório", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Achar relatórios similares", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentação", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Leia a documentação em uBlock/wiki para saber sobre todos os recursos do uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Perguntas e suporte", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Respostas a perguntas e outros tipos de suporte de ajuda são fornecidas no subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemas com o filtro/o site da web está quebrado", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Reporte problemas com os filtros em sites específicos da web no rastreador de problemas do uBlockOrigin/uAssets. Requer uma conta no GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Importante: Evite usar outros bloqueadores com propósito similar junto do uBlock Origin pois isto pode causar problemas com filtros em sites da web específicos.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Dicas: Certifique-se que sua lista de filtros está atualizada. O coletor é a ferramenta primária pra diagnosticar problemas relacionados com os filtros.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Relatório de erro", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Reporte problemas com o próprio uBlock Origin no uBlockOrigin/uBlock-issuerastreador de problemas. Requer uma conta no GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informações para solução de problemas", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Abaixo estão informações técnicas que poderiam ser úteis quando voluntários estão tentando ajudar você a resolver um problema.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Atenção: Informações potencialmente privadas ou sensíveis são eliminadas por padrão. As informações eliminadas podem tornar mais difícil resolver um problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Reportar um problema com o filtro", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Pra evitar sobrecarregar os voluntários com relatórios duplicados por favor certifique-se que o problema já não foi reportado.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "As listas de filtros são atualizadas diariamente. Certifique-se que seu problema ainda não foi abordado nas listas de filtros mais recentes.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifique se o problema ainda existe após recarregar a página da Web problemática.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Endereço da página da web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "A página da web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "— Escolha uma entrada —", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Mostra os anúncios ou restos de anúncios", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Tem sobreposições ou outros incômodos", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detecta o uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Tem problemas relacionados a privacidade", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Funciona mal quando o uBlock Origin está ativado", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Abre abas ou janelas indesejadas", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Rotula a página da web como \"NSFW\" (\"Não é Seguro no Trabalho\")", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redigir", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Não redigir", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Política de privacidade", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Código fonte (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Colaboradores", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Código fonte", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduções", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listas de filtros", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependências externas (compatíveis com GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "As próprias listas de filtros do uBO estão hospedadas gratuitamente nos seguintes CDNs: ", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Um CDN escolhido aleatoriamente é usado quando uma lista de filtros precisa ser atualizada", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Fazer backup no arquivo", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "meu-backup-do-ublock_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaurar do arquivo...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Resetar para as configurações padrão…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Todas as suas configurações serão sobrescritas usando dados do backup salvos em {{time}}, e o uBlock₀ reiniciará. \n\nSobrescrever todas as configurações existentes usando os dados do backup?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Os dados não puderam ser lidos ou são inválidos", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Todas as suas configurações serão removidas, e o uBlock₀ reiniciará.\n\nResetar o uBlock₀ para as configurações de fábrica?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Erro da rede: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Adicionar a seguinte URL a sua lista de filtros personalizados?\n\nTítulo: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscrever", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "um minuto atrás", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minutos atrás", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "uma hora atrás", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} horas atrás", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "um dia atrás", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dias atrás", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Mostrar Painel", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Mostrar Coletor", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "desligado", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Página bloqueada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "O uBlock Origin impediu a seguinte página de carregar:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Por causa do seguinte filtro:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sem parâmetros", + "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": "Achado em:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Voltar", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Fechar esta janela", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Não me avisar de novo sobre este site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Desativar o bloqueio restrito para {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporariamente", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentemente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Prosseguir", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportar pro armazenamento na nuvem", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importar do armazenamento na nuvem", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importar do armazenamento na nuvem e unir com as configurações atuais", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Este nome de dispositivo:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Aviso! Mude estas configurações avançadas por sua própria conta e risco.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submeter", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplicar mudanças", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Reverter", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloquear elemento no frame...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscrever na lista de filtros... ", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permitir temporariamente grandes elementos de mídia", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Visualizar código fonte…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Digite um atalho", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Alternar bloqueio de rolagem", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiar pra área de transferência", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Selecionar tudo", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Alternar filtragem cosmética", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaxar modo de bloqueio", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Armazenamento usado: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KBs", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MBs", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GBs", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clique pra carregar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erros: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Não conseguiu filtrar apropriadamente na inicialização do navegador. Recarregue a página pra garantir a filtragem apropriada.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Esta entrada deve ser a última", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json new file mode 100644 index 0000000..15019cb --- /dev/null +++ b/src/_locales/pt_PT/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Finalmente, um bloqueador eficiente. Leve na CPU e memória.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Painel de controlo", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Atenção! Tem alterações não guardadas", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Permanecer", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorar", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Definições", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listas de filtros", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Os meus filtros", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "As minhas regras", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Sites fidedignos", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Atalhos", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Registador", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Acerca", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Suporte", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Visualizador de recursos", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Definições avançadas", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clique: desativar/ativar o uBlock₀ para este site.\n\nCtrl+clique: desativar o uBlock₀ apenas nesta página.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Clique para desativar o uBlock₀ para este site.\n\nCtrl+clique para desativar o uBlock₀ apenas nesta página.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clique para ativar o uBlock₀ para este site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "pedidos bloqueados", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "nesta página", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "desde a instalação", + "description": "English: since install" + }, + "popupOr": { + "message": "ou", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bloqueado(s) nesta página", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Bloqueado(s) desde a instalação", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domínios ligados", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Abrir o painel de controlo", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Entrar no modo \"zapper\" de elemento", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Entrar no modo de seleção de elemento", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Abrir o registador", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Relatar um problema neste website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Alternar o bloqueio de todos os popups para este site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clique para bloquear todos os popups neste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clique para deixar de bloquear todos os popups neste site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Alternar o bloqueio de elementos multimédia grandes para este site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clique para bloquear elementos multimédia grandes neste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clique para deixar de bloquear elementos multimédia grandes neste site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Alternar a filtragem cosmética para este site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Clique para desativar a filtragem cosmética neste site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Clique para ativar a filtragem cosmética neste site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Alternar o bloqueio de tipos de letra remotos para este site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clique para bloquear os tipos de letra remotos neste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clique para deixar de bloquear os tipos de letra remotos neste site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Clique para desativar JavaScript neste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Clique para deixar de desativar JavaScript neste site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Janelas pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elementos multimédia grandes", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtragem cosmética", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Tipos de letra remotos", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mais", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menos", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Regras globais: esta coluna é para as regras que se aplicam a todos os sites.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Clique para tornar as suas alterações permanentes.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Clique para reverter as suas alterações.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "tudo", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imagens", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "terceiros", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/imagens de terceiros", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripts inline", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripts primários", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripts de terceiros", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "frames de terceiros", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domínios ligados", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} de {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versão", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Criar", + "description": "English: Create" + }, + "pickerPick": { + "message": "Escolher", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Sair", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Pré-visualizar", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtros de rede", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtros cosméticos", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clique, Ctrl-clique", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bloquear elemento…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ocultar espaços ocupados por elementos bloqueados", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Mostrar o número de pedidos bloqueados no ícone", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Desativar dicas", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Fazer uso do menu de contexto onde apropriado", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Cores amigáveis para daltónicos", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aparência", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Cor de destaque personalizada", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Ativar suporte para armazenamento na nuvem", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Sou um utilizador avançado", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Desativar pré-obtenção (para impedir qualquer ligação para pedidos de rede bloqueados)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Desativar auditoria de hiperligações", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Impedir o WebRTC de vazar endereços IP locais", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportamento predefinido", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Estes comportamentos predefinidos podem ser substituídos numa base por site", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Desativar filtragem cosmética", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bloquear elementos multimédia maiores do que {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bloquear tipos de letra remotos", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Desativar JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bloquear relatórios CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Desvendar nomes canónicos", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avançadas", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funcionalidades adequadas apenas para utilizadores avançados", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "definições avançadas", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Último restauro:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Última cópia de segurança:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtros de rede + {{cosmeticFilterCount}} filtros cosméticos a partir de:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} utilizados de {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Atualizar automaticamente listas de filtros", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Atualizar agora", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Limpar todas as caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analisar e aplicar filtros cosméticos", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Os filtros cosméticos servem para ocultar elementos numa página web que sejam considerados incómodo visual e que não podem ser bloqueados pelo motor de filtragem baseado em pedidos de rede.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorar filtros cosméticos genéricos", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Os filtros cosméticos genéricos são destinados para aplicação em todos os sites. Se ativar esta opção irá eliminar o excesso de utilização da memória e CPU, como resultado da manipulação dos filtros cosméticos genéricos.\n\nRecomendamos a ativação desta opção em dispositivos mais fracos.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspender a atividade da rede até que todas as listas de filtros sejam carregadas", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listas de servidores bloqueados", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplicar alterações", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Integrados", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Anúncios", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privacidade", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Proteção contra malware, segurança", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Inconveniências", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multifunções", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regiões e idiomas", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizados", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importar…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Um URL por linha. Os URLs inválidos serão ignorados silenciosamente.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Desatualizada.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "ver conteúdo", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Última atualização: {{ago}}.\nClique para forçar uma atualização.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "A atualizar…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Um erro de rede impediu que o recurso fosse atualizado.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Um filtro por linha. Um filtro pode ser um simples nome de anfitrião, ou um filtro compatível com a EasyList. Linhas começadas por ! serão ignoradas.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Não adicione filtros de fontes não confiáveis.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importar e anexar…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportar…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-custom-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplicar alterações", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Regras permanentes", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Regras temporárias", + "description": "header" + }, + "rulesRevert": { + "message": "Reverter", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Aplicar", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Editar", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Guardar", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Descartar", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importar a partir de ficheiro…", + "description": "" + }, + "rulesExport": { + "message": "Exportar para ficheiro…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista das suas regras de filtragem dinâmica.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regra de sintaxe: origem destino tipo ação (documentação completa).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Ordenar:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipo de regra", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Origem", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destino", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "As diretivas de sites fidedignos determinam em que páginas web o uBlock Origin deve ser desativado. Uma entrada por linha.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importar e anexar…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportar…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplicar alterações", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tipo", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domínio", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtro", + "description": "English: Filter" + }, + "logAll": { + "message": "Todos", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Sem separador", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Separador atual", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Recarregar o conteúdo do separador", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Alternar o inspetor DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Alternar o painel de popup", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: O registador", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Limpar registador", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausar registador (descartar todos os dados a receber)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Retomar registador", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Alternar filtragem do registador", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrar conteúdo do registo", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opções de filtragem do registador", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Não", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bloqueado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permitido", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificado", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "primário", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "terceiro", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalhes", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtro", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista de filtros", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regra", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Contexto", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Contexto raiz", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Tipo de relação", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tipo", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Regra do URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Contexto:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tipo:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtro estático", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} pedidos de rede de {{type}} {{br}}cujo endereço URL corresponde a {{url}} {{br}}e que origina {{origin}},{{br}}{{importance}} existe um filtro de exceção correspondente.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bloquear", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permitir", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tipo \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "qualquer tipo", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "de \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "de qualquer lugar", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "exceto quando", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "mesmo se", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtro estático {{filter}} encontrado em:", + "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", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Entradas do registador que não preenchem todas as três condições abaixo serão automaticamente descartadas:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preservar entradas dos últimos {{input}} minutos", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preservar no máximo {{input}} carregamentos de página por separador", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preservar no máximo {{input}} entradas por separador", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Utilizar {{input}} linhas por entrada no modo verticalmente expandido", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ocultar colunas:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Hora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtro/regra", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Contexto", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Tipo de relação", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabela", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Sem formatação", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Abrir", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Criar novo relatório", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Encontrar relatórios semelhantes", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentação", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Leia a documentação em uBlock/wiki para saber mais acerca de todas as funcionalidades do uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Perguntas e suporte", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "As respostas às perguntas e outros tipos de ajuda são fornecidas no subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemas de filtros/website está com falhas", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Relate problemas de filtros com websites específicos para o controlador de problemas uBlockOrigin/uAssets. Requer uma conta GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Importante: evite a utilização de outros bloqueadores com propósitos semelhantes juntamente com o uBlock Origin, dado que isto pode causar problemas com filtros em websites específicos.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Dicas: certifique-se de que as suas listas de filtros estão atualizadas. O registador é a ferramenta principal para diagnosticar problemas relacionados com filtros.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Relatório de erros", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Relate problemas com o próprio uBlock Origin para o controlador de problemas uBlockOrigin/uBlock-issue. Requer uma conta GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informação sobre resolução de problemas", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Importante: a informação potencialmente privada ou sensível é redigida por predefinição. A informação redigida pode tornar mais difícil a resolução de um problema.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Relatar um problema de filtro", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Para evitar sobrecarregar os voluntários com relatórios duplicados, por favor verifique se o problema ainda não foi relatado.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "As listas de filtros são atualizadas diariamente. Certifique-se de que o seu problema ainda não foi abordado nas listas de filtros mais recentes.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Endereço da página web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "A página web…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Escolha uma entrada --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Mostra anúncios ou restos de anúncios", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Tem sobreposições ou outros incómodos", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Deteta o uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Tem problemas relacionados com a privacidade", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Falha quando o uBlock Origin é ativado", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Abre separadores ou janelas indesejáveis", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Rotular a página web como “NSFW” (“Não seguro para o trabalho”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redigir", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Não redigir", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Política de privacidade", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Registo de alterações", + "description": "" + }, + "aboutCode": { + "message": "Código fonte (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contribuidores", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Código fonte", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduções", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listas de filtros", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependências externas (compatíveis com GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "As listas de filtros do uBO estão livremente hospedadas nas seguintes CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Uma CDN escolhida aleatoriamente é utilizada quando uma lista de filtros precisar de ser atualizada.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Copiar para ficheiro…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restaurar a partir de ficheiro…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Restaurar predefinições…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Todas as suas definições serão substituídas utilizando os dados da cópia de segurança de {{time}}, e o uBlock₀ irá reiniciar.\n\nSubstituir todas as definições existentes utilizando os dados da cópia de segurança?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Os dados não puderam ser lidos ou são inválidos", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Todas as suas definições serão removidas e o uBlock₀ será reiniciado.\n\nRestaurar predefinições do uBlock₀?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Erro de rede: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Adicionar o seguinte URL à sua lista de filtros personalizados?\n\nTítulo: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscrever", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "há um minuto", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "há {{value}} minutos", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "há uma hora", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "há {{value}} horas", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "há um dia", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "há {{value}} dias", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Mostrar painel de controlo", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Mostrar registador", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "desativado", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Página bloqueada", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "O uBlock Origin impediu que a seguinte página fosse carregada:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Devido ao seguinte filtro:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "sem parâmetros", + "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:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Retroceder", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Fechar esta janela", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Não me avisar novamente acerca deste site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Desativar bloqueio estrito para {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporariamente", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanentemente", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceder", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportar para a nuvem", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importar a partir da nuvem", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importar a partir da nuvem e juntar às definições atuais", + "description": "tooltip" + }, + "cloudNoData": { + "message": "... ...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Nome deste dispositivo:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Atenção! Altere estas definições avançadas por sua conta e risco.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submeter", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplicar alterações", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Reverter", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bloquear elemento no frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscrever à lista de filtros…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permitir temporariamente elementos multimédia grandes", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Ver código fonte…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Digitar um atalho", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Alternar deslocamento bloqueado", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiar para a área de transferência", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Selecionar tudo", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Alternar filtragem cosmética", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaxar modo de bloqueio", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Armazenamento utilizado: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Clique para carregar", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erros: {{count}}", + "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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Esta entrada deve ser a última", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ro/messages.json b/src/_locales/ro/messages.json new file mode 100644 index 0000000..a338cbe --- /dev/null +++ b/src/_locales/ro/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "În sfârșit, un blocant eficient. Are un impact mic asupra procesorului și memoriei.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Panou de control", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Atenție! Ai modificări nesalvate", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Așteaptă", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignoră", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Opțiuni", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Liste de filtre", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Filtrele mele", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Regulile mele", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Situri de încredere", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Comenzi rapide", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Jurnal", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Despre", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Ajută-ne", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Vizualizator de resurse", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Setări avansate", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Clic: dezactivează/activează uBlock₀ pentru acest sait.\n\nCtrl+clic: dezactivează uBlock₀ doar pe această pagină.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Clic ca să dezactivezi uBlock₀ pe acest site.\n\nCtrl+clic ca să dezactivezi uBlock₀ doar pe această pagină.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Clic pentru a activa uBlock₀ pe acest site.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "cereri blocate", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "pe această pagină", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} sau {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "de la instalare", + "description": "English: since install" + }, + "popupOr": { + "message": "sau", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocate pe această pagină", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocate de la instalare", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domenii conectate", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Deschide panoul de control", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Accesați modul de eliminare elemente", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Modul alege element", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Deschide jurnalul", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Raportează o eroare cu acest sit", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Comută blocarea tuturor popup-urilor pentru acest sait", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Clic pentru a bloca toate popup-urile pe acest site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Clic pentru a nu mai bloca toate popup-urile pe acest site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Modifică modul de blocare a elementelor media de mari dimensiuni pentru acest sait", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Clic pentru a bloca elementele media de mari dimensiuni pe acest site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Clic pentru a nu mai bloca elementele media de mari dimensiuni pe acest site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Comută filtrarea vizuală pentru acest sait", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Clic pentru a dezactiva filtrele vizuale pe acest site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Clic pentru a activa filtrele vizuale pe acest site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Comută blocarea fonturilor externe pentru acest sait", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Clic pentru a bloca fonturile externe pe acest site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Clic pentru a nu mai bloca fonturile externe pe acest site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Apasă pentru a dezactiva JavaScript pe acest site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Apasă pentru a nu mai dezactiva JavaScript pe acest site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Ferestre suprapuse", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elemente media mari", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtre vizuale", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fonturi externe", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mai multe", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mai puțin", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Reguli globale: această coloană este pentru regulile care se aplică tuturor site-urilor.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Apasă pentru a face modificările permanente.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Apasă pentru a renunța la modificări.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "tot", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imagini", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "terțe", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/imagini terțe", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "scripturi înglobate", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "scripturi din saitul primar", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "scripturi din saituri terțe", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "cadre din saituri terțe", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domenii conectate", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} din {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versiune", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "cadru", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Creează", + "description": "English: Create" + }, + "pickerPick": { + "message": "Alege", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Ieșire", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Previzualizare", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtre de rețea", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtre vizuale", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Clic, Ctrl-clic", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blochează elementul…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ascunde substituenții elementelor blocate", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Arată numărul cererilor blocate pe pictogramă", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Dezactivează indiciile", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Folosește meniul contextual unde este cazul", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Accesibil pentru daltonism", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Aspect", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Aspect", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Culoare de accentuare personalizată", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Activează suportul pentru stocare în cloud", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Sunt un utilizator avansat", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Dezactivează preluarea în avans (pentru a preveni orice conexiune ce s-ar încadra în cereri de rețea blocate)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Dezactivează auditarea hiperlinkurilor", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Previne dezvăluirea adreselor IP locale prin intermediul protocolului WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Comportament implicit", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Aceste comportamente implicite pot fi suprascrise pentru fiecare sait în parte", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Dezactivează filtrele cosmetice", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blochează elementele media mai mari de {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blochează fonturile de la distanță", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Dezactivare JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blochează rapoartele CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Dezvăluie numele canonice", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avansate", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Proprietăți potrivite pentru utilizatorii avansați", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "setări avansate", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Ultima restaurare:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Ultima copie de siguranță:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtre rețea + {{cosmeticFilterCount}} filtre vizuale din:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} folosite din {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Actualizare automată a listelor de filtre.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Actualizează acum", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Golește tot din memoria tampon", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Citește și aplică filtrele vizuale.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Filtrele cosmetice servesc la ascunderea elementelor dintr-o pagină web care sunt considerate a fi deranjante din punct de vedere vizual și care nu pot fi blocate de motoarele de filtrare bazate pe solicitări de rețea.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignoră filtrele cosmetice generice", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

FIltrele cosmetice generice sunt acelea care se aplică tuturor site-urilor.

Deși sunt folosite eficient de uBlock₀, filtrele cosmetice generice pot contribui semnificativ la creșterea cantității de memorie și a utilizării procesorului pe anumite pagini, în special cele de mari dimensiuni și care sunt încărcate pentru mult timp.

Activarea acestei opțiuni va elimina încărcarea suplimentară a memoriei și a procesorului rezultată în urma folosirii filtrelor cosmetice generice, și, de asemenea, va micșora impactul uBlock₀ asupra sistemului.

Se recomandă activarea acestei opțiuni pe dispozitivele mai puțin performante.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspendă activitatea în rețea până când se încarcă toate listele cu filtre", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista adreselor blocate", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Aplică modificările", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Încorporate", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reclame", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Intimitate", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domenii malițioase", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Neplăceri", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multifuncționale", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regiuni, limbi", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personalizare", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importă…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "O adresă pe linie. Adresele nevalide vor fi ignorate fără avertizare.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "învechit", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "vezi conținut", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Ultima actualizare: {{ago}}.\nClic pentru a forța o actualizare.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Se actualizează…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "O eroare de rețea a împiedicat actualizarea resursei.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Un filtru pe linie. Un filtru poate fi un simplu nume de gazdă sau un filtru compatibil EasyList. Liniile precedate de ! vor fi ignorate.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nu adăuga filtre din surse nesigure.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importă și adaugă", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportă", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "filtrele-mele-statice-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Aplică modificările", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Reguli permanente", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Reguli temporare", + "description": "header" + }, + "rulesRevert": { + "message": "Înlătură", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Aplică", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Modifică", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Salvează", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Elimină", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importă din fișier…", + "description": "" + }, + "rulesExport": { + "message": "Exportă în fișier...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "regulile-mele-dinamice-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista regulilor tale de filtrare dinamică.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaxa pentru regulă: sursă destinație tip acțiune (documentație).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortare:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tipul regulei", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Sursa", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinaţia", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Directivele privind siturile de încredere stabilesc pe ce pagini web trebuie dezactivat uBlock Origin. O intrare pe linie.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importă și adaugă", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportă", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "situri-de-încredere-ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Aplică modificările", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tip", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domeniu", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtru", + "description": "English: Filter" + }, + "logAll": { + "message": "Tot", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Fără tab-uri", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Fila curentă", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reîncarcă conținutul tab-ului", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Comută inspector DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Comută panou pop-up", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Jurnal", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Şterge logger-ul", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Oprește logger-ul(ignoră tot traficul primit)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Pornește logger-ul", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Comută filtrarea jurnalierului", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrează conținutul jurnalierului", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opțiunile de filtrare ale jurnalierului", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nu", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "activ", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "permis", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modificat", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "primare", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "terțe", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detalii", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtru", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista filtrelor", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regulă", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Context de bază", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Apartenență", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tip", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Regulă URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tip:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtru static", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} cererile de rețea de {{type}} {{br}}când adresa URL corespunde cu {{url}} {{br}}și care își au originea {{origin}},{{br}}{{importance}} există un filtru corespondent de excepție.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blochează", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Permite", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "tip “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "orice tip", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "de la “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "de oriunde", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "exceptând când", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "chiar dacă", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtrul static {{filter}} găsit în:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Filtrul static {{filter}} nu se găsește în niciuna dintre listele de filtre activate", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Intrările din jurnal care nu îndeplinesc cele trei condiții de mai jos vor fi respinse automat:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Păstrează intrările din ultimele {{input}} minute", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Păstrează cel mult {{input}} încărcări de pagină pe filă", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Păstrează cel mult {{input}} intrări pe filă", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Folosește {{input}} linii pentru intrările în modul vertical expandat", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ascunde coloanele:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Timp", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtru/regulă", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Apartenență", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Listă", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabel", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Simplu", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Marcaj", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Deschide", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Crează o nouă sesizare", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Găsește sesizări similare", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentație", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Citește documentația de la uBlock/wiki pentru a învăța totul despre caracteristicile uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Întrebări și ajutor", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Răspunsuri la întrebări și alte informații de ajutor sunt disponibile pe subreddit-ul /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Probleme cu filtrele/siturile defecte", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Raportează probleme cu filtrele pe anumite situri în uBlockOrigin/uAssets centralizatorul de probleme. Necesită un cont GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": ">Important: Evită să folosești alte extensii cu același scop ca uBlock Origin, deoarece pot exista probleme cu filtrele pe anumite situri.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Sfat: Asigurați-vă că filtrele sunt actualizate. Registrul cu înregistrări este unealta principală pentru diagnosticarea problemelor cu filtrele.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Raportare defecte", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Raportați probleme cu uBlock Origin în uBlockOrigin/uBlock-issuecentralizatorul de probleme. Necesită un cont GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informații pentru depanare", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Mai jos sunt informații care îi pot ajuta pe voluntarii care încearcă să vă ajute în rezolvarea problemelor.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Informațiile potențial private sau sensibile sunt redactate implicit. Aceasta poate face mai dificilă rezolvarea problemelor.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Raportează o problemăcu filtrele", + "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ă.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Listele cu filtre sunt actualizate zilnic. Verificați că problema dumneavoastră nu a fost rezolvată în cele mai recente liste cu filtre.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verificați că problema există și după reîncărcarea paginii.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa paginii web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Pagina web…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Alege o intrare --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Arată reclame sau resturi de reclame", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Are acoperiri sau alte neplăceri", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detectează uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Are probleme privind confidențialitatea", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Nu mai funcționează când uBlock Origin este activat", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Deschide file sau ferestre nedorite", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Etichetează pagina ca fiind „NSFW” (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redactează", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Anulează redactarea", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Politică de confidențialitate", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Jurnal de modificări", + "description": "" + }, + "aboutCode": { + "message": "Cod sursă (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contribuitori", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Cod sursă", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Traduceri", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Liste de filtre", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dependențe externe (compatibile GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "FIltrele proprii uBO sunt găzduite gratuit de următoarele rețele de distribuție de conținut:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Un CDN ales aleator va fi folosit când listele de filtre vor trebui actualizate", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Copie de rezervă…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "salvarea-mea-ublock_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restabilește din fișier…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Restabilește reglările inițiale…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Toate opțiunile vor fi suprascrise cu datele din {{time}} și uBlock₀ va fi repornit.\n\nDorești să suprascrii toate opțiunile folosind datele salvate?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Datele nu au putut fi citite sau sunt nevalide", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Toate configurările tale vor fi eliminate și uBlock₀ va reporni.\n\nRestaurează uBlock₀ la configurările din fabrică?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Eroare de rețea: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock: Adaugă următorul URL în lista ta de filtre personalizate?\n\nTitlu: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonează-te", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "acum un minut", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "acum {{value}} minute", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "acum o oră", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "acum {{value}} ore", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "în urmă cu o zi", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "în urmă cu {{value}} zile", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Deschide panoul de control", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Arată jurnalul", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "dezactivat", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Pagină blocată", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin a prevenit încărcarea acestei pagini:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Din cauza următorului filtru", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "fără parametri", + "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": "Găsit în:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Înapoi", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Închide această fereastră", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Nu mă avertiza din nou despre acest sit", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Dezactivează blocarea strictă pentru {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporar", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanent", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Continuă", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportă către stocarea în cloud", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importă din stocarea în cloud", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importă din stocarea în cloud și combină cu setările curente", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Numele acestui dispozitiv:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Atenție: schimbă aceste setări avansate pe propriul risc.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Trimite", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Aplică modificările", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Înlătură", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "octeți", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blochează un element în cadru…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Înscrie-te la lista de filtre…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Permite temporar elementele media mari", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Vezi sursa", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Tastează o comandă rapidă", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Activează/Dezactivează Blocarea răsfoirii", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copiază în clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Alege tot", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Comută filtrele cosmetice", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relaxați modul de blocare", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Spațiu de stocare utilizat: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Apasă pentru a încărca", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Erori: {{count}}", + "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", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Aceasta intrare trebuie sa fie ultima", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ru/messages.json b/src/_locales/ru/messages.json new file mode 100644 index 0000000..1702d1b --- /dev/null +++ b/src/_locales/ru/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock₀", + "description": "extension name." + }, + "extShortDesc": { + "message": "Наконец-то, быстрый и эффективный блокировщик для браузеров.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Панель управления", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Внимание! У вас есть несохраненные изменения", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Остаться", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Игнорировать", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Настройки", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Списки фильтров", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Мои фильтры", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Мои правила", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Доверенные сайты", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Сочетания клавиш", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Логгер", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "О расширении", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Поддержка", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Активы", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Расширенные настройки", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ для этого сайта.\nCtrl+клик, чтобы отключить uBlock₀ только на этой странице.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Кликните, чтобы активировать uBlock₀ для этого сайта.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "запросов заблокировано", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на этой странице", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "с момента установки", + "description": "English: since install" + }, + "popupOr": { + "message": "или", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Заблокировано на этой странице", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Заблокировано с момента установки", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Доменов подключено", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Открыть панель управления", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Режим мгновенного временного скрытия элемента", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Войти в режим выбора элементов", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Открыть логгер", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Сообщить о проблеме на данном сайте", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Вкл/Выкл блокировку всех всплывающих окон на этом сайте", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Нажмите, чтобы блокировать все всплывающие окна на этом сайте", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Нажмите, чтобы отключить блокировку всех всплывающих окон на этом сайте", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Вкл/Выкл блокировку больших медиа-элементов на этом сайте", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Нажмите для включения блокировки больших медиа-элементов на этом сайте", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Нажмите для отключения блокировки больших медиа-элементов на этом сайте", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Вкл/Выкл косметическую фильтрацию на этом сайте", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Нажмите, чтобы отключить косметическую фильтрацию на этом сайте", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Нажмите, чтобы включить косметическую фильтрацию на этом сайте", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Вкл/Выкл блокировку сторонних шрифтов на этом сайте", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Нажмите для блокировки сторонних шрифтов на этом сайте", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Нажмите для отключения блокировки сторонних шрифтов на этом сайте", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Нажмите, чтобы отключить JavaScript на этом сайте", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Кликните, чтобы перестать блокировать JavaScript на этом сайте", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Всплывающие окна", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Большие медиа-элементы", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Косметическая фильтрация", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Загружаемые шрифты", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Больше", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Меньше", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Глобальные правила: этот столбец предназначен для правил, применяемых ко всем сайтам.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Локальные правила: этот столбец предназначен для правил, применяемых только к текущему сайту.\nЛокальные правила переопределяют глобальные.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Нажмите, чтобы сохранить изменения.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Нажмите, чтобы отменить изменения.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "все", + "description": "" + }, + "popupImageRulePrompt": { + "message": "изображения", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3rd-party ресурсы", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/изображения", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline-скрипты", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party скрипты", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party скрипты", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party фреймы", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "доменов подключено", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} из {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Версия", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "скрипт", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "фрейм", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Создать", + "description": "English: Create" + }, + "pickerPick": { + "message": "Выбрать", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Выйти", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Предпросмотр", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Сетевые фильтры", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Косметические фильтры", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Клик, Ctrl+клик", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Блокировать элемент...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Скрыть оставшееся от заблокированных элементов место", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Показывать количество заблокированных запросов на иконке", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Отключить всплывающие подсказки", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Использовать контекстное меню, где возможно", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Цветовая схема для дальтоников", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Настройки интерфейса", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Тема", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Выбрать акцент цветового оформления", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Включить поддержку облачного хранилища", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Я — опытный пользователь", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Отключить предзагрузку для предотвращения подключений для заблокированных запросов", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Отключить проверку гиперссылок", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Предотвратить утечку локального IP-адреса через WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Поведение по умолчанию", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Эти настройки могут быть указаны для каждого сайта отдельно", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Отключить косметические фильтры", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блокировать медиа-элементы больше {{input}} KБ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блокировать сторонние шрифты", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Отключить JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Блокировать CSP-отчёты", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Раскрывать CNAME записи", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Расширенные настройки", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Функции, предназначенные для технических пользователей", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "расширенные настройки", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Последнее восстановление:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Последняя резервная копия:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} сетевых фильтров + {{cosmeticFilterCount}} косметических фильтров из:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} используется из {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Автообновление списков фильтров", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Обновить сейчас", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Очистить все кэши", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Парсить и применять косметические фильтры", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Косметические фильтры применяются на веб-странице для скрытия элементов, которые создают визуальные помехи, и которые не могут быть заблокированы механизмом фильтрации сетевых запросов.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Игнорировать общие косметические фильтры", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Общие косметические фильтры — это те косметические фильтры, которые должны применяться на всех веб-сайтах. Включение этой опции снизит потребление памяти и избавит процессор от обработки общих косметических фильтров на веб-страницах.\n\nРекомендуется включить эту опцию на недостаточно мощных устройствах.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Приостановить сетевую активность, пока не запустятся все списки фильтров", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Список заблокированных хостов", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Применить изменения", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Встроенные", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Реклама", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Приватность", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Защита от вредоносных сайтов, безопасность", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Раздражающие элементы", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Многоцелевые", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Регионы, языки", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Пользовательские", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Импортировать...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Один URL на строку. Неверные URL будут проигнорированы без предупреждения.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Устарел.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "показать содержимое", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Последнее обновление: {{ago}}.\nКликните для принудительного обновления.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Обновление...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "В результате ошибки сети обновление не произошло.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Одно правило на строку. Правилом может быть имя сайта или EasyList-совместимый фильтр. Строки, начинающиеся с !, будут проигнорированы.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Не добавляйте фильтры из ненадёжных источников.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Импортировать и добавить…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Экспортировать…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Применить изменения", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Постоянные правила", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Временные правила", + "description": "header" + }, + "rulesRevert": { + "message": "Вернуть", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Утвердить", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Изменить", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Сохранить", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Сбросить", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Импорт из файла...", + "description": "" + }, + "rulesExport": { + "message": "Экспортировать в файл…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Список ваших правил динамической фильтрации.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Синтаксис правил: источник назначение тип действие (полная документация).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Сортировка:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тип правила", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Источник", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Цель", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Записи доверенных сайтов указывают на каких веб-страницах uBlock Origin должен быть отключен. Одна запись на строку.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Импортировать и добавить…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Экспортировать…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Применить изменения", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тип", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Фильтр", + "description": "English: Filter" + }, + "logAll": { + "message": "Все", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Закулисные запросы", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Текущая вкладка", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Перезагрузить содержимое вкладки", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Вкл/Выкл DOM-инспектор", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Вкл/Выкл всплывающую панель", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin вики: Логгер", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Очистить логгер", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Поставить логгер на паузу (отбрасывать все входящие данные)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Снять логгер с паузы", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Вкл/Выкл фильтрацию логгера", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "фильтрация записей логгера", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Настройки фильтрации логгера", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "модифицировано", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3rd-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Подробно", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Фильтр", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Список фильтров", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правило", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Контекст корня", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Сторона", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тип", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL правило", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тип:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статич. фильтр", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} сетевые запросы {{type}}, {{br}}URL которых совпадает с {{url}} {{br}} и которые происходят из {{origin}},{{br}}{{importance}} имеется подходящий фильтр-исключение.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блокировать", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Разрешить", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "типа “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "любой тип", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "из “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "откуда угодно", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "кроме случаев, когда", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "даже если", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Статический фильтр {{filter}} найден в:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Статический фильтр не найден ни в одном списке фильтров, включенных в данный момент", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Записи логгера, не удовлетворяющие всем трём нижеуказанным условиям, будут автоматически отброшены:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Хранить записи последних {{input}} минут", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Хранить не больше {{input}} загрузок страницы на вкладку", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Хранить не больше {{input}} записей на вкладку", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Использовать {{input}} строк для каждой записи при вертикальном расширении", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Скрыть столбцы:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Время", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Фильтр/правило", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Контекст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Сторона", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Список", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Таблица", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Простой", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Открыть", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Создать новый отчет", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Найти похожие отчеты", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Документация", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Прочитайте документацию на uBlock/wiki, чтобы узнать обо всех возможностях uBlock Origin. ", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Вопросы и поддержка", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Ответы на вопросы и другая помощь доступны в разделе /r/uBlockOrigin на reddit.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Проблемы фильтрации/сломанный сайт", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Сообщайте о проблемах фильтрации на конкретных сайтах в раздел трекера uBlockOrigin/uAssets. Требуется аккаунт GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Важно: Избегайте использования других блокировщиков схожего назначения совместно с uBlock Origin, так как это может привести к проблемам с фильтрацией на определенных сайтах.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Советы: убедитесь, что ваши списки фильтров обновлены. Логгер — основной инструмент диагностики проблем, связанных с фильтрами.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Отчет об ошибке", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Сообщайте о собственных ошибках дополнения uBlock Origin в раздел трекера uBlockOrigin/uBlock-issue. Требуется GitHub аккаунт.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Диагностика неисправностей", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Ниже представлена техническая информация, которая может быть полезна волонтерам, помогающим вам решить проблему.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Важно: Предположительно конфиденциальная информация редактируется по умолчанию. Отредактированная информация может усложнить диагностику проблемы.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Сообщить о проблемном фильтре", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Чтобы не обременять волонтеров дублированными отчетами, пожалуйста, убедитесь, что о данной проблеме еще не сообщали", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Списки фильтров обновляются ежедневно. Убедитесь, что ваша проблема не была решена в свежих списках фильтров.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Удостоверьтесь, что проблема воспроизводится даже после обновления проблемной страницы.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Адрес веб-страницы:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Веб-страница...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "--Выберите категорию--", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Показывается реклама или ее заполнители", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Всплывающие окна или другие помехи", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Обнаруживается uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Проблемы, связанные с приватностью", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Поломки, когда включен uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Открываются нежелательные вкладки или окна", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Пометить веб-страницу как “NSFW” (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Редактировать", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Отменить редактирование", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Политика конфиденциальности", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Список изменений", + "description": "" + }, + "aboutCode": { + "message": "Исходный код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Участники", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Исходный код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Переводы", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Списки фильтров", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Внешние зависимости (GPLv3-совместимые):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Собственные списки фильтров uBO свободно размещены на следующих CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "При обновлении списка фильтров используется выбранный случайным образом CDN", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Резервное копирование в файл…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Восстановить из файла...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Восстановить настройки по умолчанию...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Текущие настройки будут заменены данными из резервной копии от {{time}}, и uBlock₀ будет перезапущен.\n\nПерезаписать все существующие параметры данными из резервной копии?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Данные не могут быть прочитаны или ошибочны", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Все ваши настройки будут удалены, uBlock₀ будет перезапущен. \n\nВосстановить настройки по умолчанию?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Ошибка сети: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Добавить следующий адрес к пользовательским спискам фильтров?\n\nЗаголовок: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Подписаться", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "минуту назад", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} минут(-ы) назад", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "час назад", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} часа(-ов) назад", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "день назад", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} дня(-ей) назад", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Показать панель управления", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Показать логгер", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "выключен", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Страница заблокирована", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin предотвратил загрузку следующей страницы:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Из-за следующего фильтра", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Найден в:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Вернуться", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Закрыть это окно", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Не предупреждать меня больше про этот сайт", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Отключить строгую блокировку для {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Временно", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Навсегда", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Продолжить", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Экспорт в облачное хранилище", + "description": "tooltip" + }, + "cloudPull": { + "message": "Импорт из облачного хранилища", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Импортировать из облачного хранилища и объединить с текущими настройками", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Имя этого устройства:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Внимание! Изменяйте эти настройки на свой страх и риск.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Принять", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Применить изменения", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Вернуть", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байт", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Заблокировать элемент во фрейме...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Установить список фильтров...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Временно разрешить большие медиа-элементы", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Показать исходный код...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Введите сочетание", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Вкл/Выкл общую прокрутку", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Скопировать в буфер", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Выбрать все", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Вкл/Выкл косметическую фильтрацию", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Ослабленный режим блокировки", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Размер хранилища: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Нажмите, чтобы загрузить", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Ошибки: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Не удалось выполнить фильтрацию при запуске браузера.\nПерезагрузите страницу, чтобы обеспечить фильтрацию.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Эта запись должна быть последней", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/si/messages.json b/src/_locales/si/messages.json new file mode 100644 index 0000000..f414f59 --- /dev/null +++ b/src/_locales/si/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "අවසානයේදී, මධ්‍ය සැකසුම් ඒකකය සහ මතකය අඩුවෙන් භාවිතා කරන කාර්යක්‍ෂම අවහිරකයක් ඇත.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "යූබ්ලොක්₀ - උපකරණ පුවරුව", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Warning! You have unsaved changes", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "නවතින්න", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "නොසලකන්න", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "සැකසුම්", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filter lists", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "මාගේ පෙරහන්", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "මාගේ නීති", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "විශ්වාසදායී අඩවි", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "කෙටිමං", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "පිළිබඳව", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "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.", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "මෙම අඩවියට යූබ්ලොක්₀ සබල කිරීමට ඔබන්න.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "ඉල්ලීම් අවහිර කර ඇත", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "මෙම පිටුවෙහි", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "since install", + "description": "English: since install" + }, + "popupOr": { + "message": "හෝ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "මෙම පිටුවේ අවහිර කළ", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "ස්ථාපනයෙන් පසු අවහිර කළ", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "සම්බන්ධිත වසම්", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "උපකරණපුවරුව විවෘත කරන්න", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Enter element zapper mode", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Enter element picker mode", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Open the logger", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Toggle the blocking of all popups for this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Click to block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Click to no longer block all popups on this site", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Toggle the blocking of large media elements for this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Click to block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Click to no longer block large media elements on this site", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Click to disable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Click to block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Click to no longer block remote fonts on this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Click to disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Click to no longer disable JavaScript on this site", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "දුරස්ථ මුද්‍රණඅකුරු", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "තව", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Less", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "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.\nLocal rules override global rules.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Click to make your changes permanent.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Click to revert your changes.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "සියල්ල", + "description": "" + }, + "popupImageRulePrompt": { + "message": "images", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "තෙවන-පාර්ශවීය", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3rd-party CSS/images", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline scripts", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1st-party scripts", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3rd-party scripts", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3rd-party frames", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "සම්බන්ධිත වසම්", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "අනුවාදය", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "සාදන්න", + "description": "English: Create" + }, + "pickerPick": { + "message": "Pick", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "ඉවත් වන්න", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "පෙරදසුන", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ජාල පෙරහන්", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Cosmetic filters", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Click, Ctrl-click", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Block element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Hide placeholders of blocked elements", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Show the number of blocked requests on the icon", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Disable tooltips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "වර්ණ-අන්ධ හිතකාමී", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "මේඝ ආචයන සහාය සබල කරන්න", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "දුරස්ථ මුද්‍රණඅකුරු බ්ලොක් කරන්න", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Disable JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "අ.ආ.ප්‍ර.(සීඑස්පී) වාර්තා අවහිරකරන්න", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "වැඩිදුර සැකසුම්", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Last backup:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "දැන් යාවත්කාල කරන්න", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "වෙනස්කම් යොදන්න", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "දැන්වීම්", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "පෞද්ගලිකත්වය", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regions, languages", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "අභිරුචි", + "description": "Filter lists section name" + }, + "3pImport": { + "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.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "යාවත්කාල වෙමින්...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "නිර්යාත", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "වෙනස්කම් යොදන්න", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "තාවකාලික නීති", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "සංස්කරණය", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "සුරකින්න", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Discard", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ගොනුවකින් ඇතුල් කරන්න...", + "description": "" + }, + "rulesExport": { + "message": "ගොනුවකට නිර්යාත කරන්න", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "මගේ-ස්ථිර-නීති_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "නීතියේ වර්ගය", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "නිර්යාත", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "මට-විශ්වාස-වෙබ්-අඩවි_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "වෙනස්කම් යොදන්න", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "වර්ගය", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "වසම", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "ඒ.ස.නි.", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "පෙරහන", + "description": "English: Filter" + }, + "logAll": { + "message": "සියල්ල", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "ප්‍රථම-පාර්ශවීය", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "තෙවන-පාර්ශවීය", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "විස්තර", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "පෙරහන", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filter list", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "නීතිය", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "වර්ගය", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "ඒ.ස.නි.", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "ඒ.ස.නි. නීතිය", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "වර්ගය:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "අවහිර", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "ඉඩදෙන්න", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "වර්ගය “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ඕනෑම වර්ගයක", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "තීරු සඟවන්න:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} වේලාව", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} පෙරහන/නීතිය", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "List", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "වගුව", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "රහස්‍යතා ප්‍රතිපත්තිය", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "දායකයින්", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "පරිවර්තන", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ගොනුවකට උපස්ථ කරන්න", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "ගොනුවකින් ප්‍රත්‍යර්පණය කරන්න...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "ජාලයේ දෝෂය: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "විනාඩියකට පෙර", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "විනාඩි {{value}} කට පෙර", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "පැයකට පෙර", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "පැය {{value}} කට පෙර", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "දිනකට පෙර", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "දවස් {{value}} කට පෙර", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "උපකරණ පුවරුව පෙන්වන්න", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "ආපසු යන්න", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "මෙම කවුළුව වසන්න", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "තාවකාලිකව", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "සදාකාලිකව", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "මේඝ ආචයනයට නිර්යාත කරන්න", + "description": "tooltip" + }, + "cloudPull": { + "message": "මේඝ ආචයනයෙන් ආයාත කරන්න", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "මේඝ ආචයනයෙන් ආයාත කර වත්මන් සැකසුම් සමඟ සංයුක්ත කරන්න", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "වෙනස්කම් යොදන්න", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "බයිට", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "පසුරුපුවරුවට පිටපත් කරන්න", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "කි.බ.", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "මෙ.බ.", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ගි.බ.", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "පූරණයට ඔබන්න", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sk/messages.json b/src/_locales/sk/messages.json new file mode 100644 index 0000000..d794627 --- /dev/null +++ b/src/_locales/sk/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Konečne efektívny blokovač. Nezaťažuje CPU ani pamäť.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Ovládací panel", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Upozornenie! Máte neuložené zmeny", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Zostať", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorovať", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Nastavenia", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Zoznam filtrov", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Moje filtre", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Moje pravidlá", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Dôveryhodné stránky", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Klávesové skratky", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Zaznamenávač", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O doplnku", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Podpora", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Zobrazenie zdrojov", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Pokročilé nastavenia", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Kliknutie: zakázať/povoliť uBlock pre túto stránku.\n\nCtrl+kliknutie: zakázať uBlock₀ len pre túto stránku.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknutím zakážete uBlock₀ pre túto stránku.\n\nCtrl+kliknutie zakáže uBlock₀ len pre túto stránku.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknutím povolíte uBlock₀ pre túto stránku.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "zablokované požiadavky", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na tejto stránke", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} alebo {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od inštalácie", + "description": "English: since install" + }, + "popupOr": { + "message": "alebo", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokované na tejto stránke", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokované od inštalácie", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Pripojené domény", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Otvoriť ovládací panel", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Prejsť do režimu výberu prvku", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Prejsť do režimu výberu prvku", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Otvoriť Zaznamenávač", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Nahlásiť problém na tejto webovej stránke", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Žiadne vyskakovacie okná pre túto stránku", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknutím zakážete všetky vyskakovacie okná na tejto stránke", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknutím povolíte všetky vyskakovacie okná na tejto stránke", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Prepnúť blokovanie veľkých multimediálnych prvkov na tejto stránke", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknutím zablokovať veľké multimediálne prvky na tejto stránke", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknutím povolíte veľké multimediálne prvky na tejto stránke", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Prepnúť kozmetické filtrovanie pre túto stránku", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknutím zakážete kozmetické filtrovanie na tejto stránke", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknutím povolíte kozmetické filtrovanie na tejto stránke", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Prepnúť blokovanie vzdialených písiem na tejto stránke", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknutím zakážete vzdialené písma pre túto stránku", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknutím povolíte vzdialené písma pre túto stránku", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Kliknutím úplne zakážete JavaScript na tejto stránke", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Kliknutím už nebude úplne zakázaný JavaScript na tejto stránke", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Vyskakovacie okná", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Veľké mediálne prvky", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kozmetické filtrovanie", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Vzdialené písma", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Viac", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Menej", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globálne pravidlá: tento stĺpec slúži pre pravidlá, ktoré platia pre všetky weby.", + "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á.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknutím použijete vaše zmeny.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknutím vrátite vaše zmeny.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "všetko", + "description": "" + }, + "popupImageRulePrompt": { + "message": "obrázky", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "z tretej strany", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/obrázky tretích strán", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "vstavané skripty", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skripty prvej triedy", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skripty tretej triedy", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "rámy tretej triedy", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "pripojené domény", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} z {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Verzia", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "rámec", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Vytvoriť", + "description": "English: Create" + }, + "pickerPick": { + "message": "Vybrať", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Ukončiť", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Náhľad", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Sieťové filtre", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kozmetické filtre", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Kliknutie, Ctrl-kliknutie", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Zablokovať prvok…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Skryť zástupcov zablokovaných prvkov", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Zobraziť počet zablokovaných požiadaviek na ikone", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Zakázať tipy pre nástroje", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Používať kontextovú ponuku v prípade potreby", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Režim pre farboslepých", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Vzhľad", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Téma", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Vlastná farba témy", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Povoliť podporu cloudového úložiska", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Som pokročilý používateľ", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Zakázať prednačítavanie (zakáže akékoľvek pripojenie pre zablokované sieťové požiadavky)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Zakázať auditovanie hypertextových odkazov", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Zabrániť úniku lokálnej IP adresy cez WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Predvolené správanie", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Tieto predvolené správania môžu byť prepísané u jednotlivých stránkach", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Vypnúť kozmetické filtrovanie", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokovať multimediálne prvky väčšie ako {{input:number}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokovať vzdialené písma", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Zakázať JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Zablokovať CSP hlásenia", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Odhaliť kanonické mená", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Pokročilé", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkcie vhodné iba pre pokročilých používateľov.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "pokročilé nastavenia", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Posledná obnova:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Posledná záloha:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} sieťových filtrov + {{cosmeticFilterCount}} kozmetických filtrov z:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} použitých z {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Automaticky aktualizovať zoznamy filtrov.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Aktualizovať teraz", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Vyčistiť celú vyrovnávaciu pamäť", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Spracovať a vynútiť kozmetické filtre", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kozmetické filtre slúžia na skrytie prvkov na webovej stránke, ktoré sa považujú za vizuálne obťažujúce a ktoré nemôžu byť zablokované filtrovaním sieťových požiadavkov.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorovať generické kozmetické filtre", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Generické kozmetické filtre sú tie kozmetické filtre, ktoré sú určené na použitie na všetkých webových stránkach. Zapnutím tejto možnosti sa zníži zaťaženie pamäte a procesora v dôsledku použitia generických kozmetických filtrov.\n\nOdporúča sa povoliť túto možnosť na menej výkonných zariadeniach.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Pozastaviť sieťovú aktivitu, kým sa nenačítajú všetky zoznamy filtrov", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Zoznamy zablokovaných hostiteľov", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Použiť zmeny", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Vstavané", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamy", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Súkromie", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domény malvéru", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Obťažujúce", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Viacúčelové", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regióny, jazyky", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Vlastné", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importovať...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Jedna URL adresa na riadok. Neplatné URL adresy budú potichu ignorované.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zastarané.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "zobraziť obsah", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Posledná aktualizácia: {{ago}}.\nKliknutím vynútite aktualizáciu.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Aktualizácia...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Chyba siete zabránila aktualizácii zdroja.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Jeden filter na riadok. Filter môže byť jednoduchý názov hostiteľa alebo filter kompatibilný s Adblock Plus. Riadky začínajúce s ! budú ignorované.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Nepridávajte filtre z nedôveryhodných zdrojov.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importovať a pripojiť", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportovať", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-moje-statické-filtre_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Použiť zmeny", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Trvalé pravidlá", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Dočasné pravidlá", + "description": "header" + }, + "rulesRevert": { + "message": "Vrátiť", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Potvrdiť", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Upraviť", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Uložiť", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Zahodiť", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importovať zo súboru...", + "description": "" + }, + "rulesExport": { + "message": "Exportovať do súboru", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-moje-dynamické-pravidlá_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Zoznam vašich dynamických filtrovacích pravidiel.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Syntax pravidla: zdroj cieľ typ akcia (úplná dokumentácia).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Zoradiť:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Typ pravidla", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Zdroj", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Cieľ", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Zoznam dôveryhodných stránok pre ktoré bude uBlock Origin zakázaný. Jedna položka na riadok.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importovať a pripojiť", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportovať", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-doveryhodne-stranky_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Použiť zmeny", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Typ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Doména", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Všetky", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Za oponou", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktívna karta", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Obnoviť obsah karty", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Prepnúť DOM inšpektor", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Prepnúť na vyskakovací panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Zaznamenávač", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Vyčistiť zaznamenávač", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pozastaviť zaznamenávač (vymazať všetky prichádzajúce dáta)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Pokračovať v zaznamenávaní", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Prepnúť filtrovanie zaznamenávača", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrovať obsah zaznamenávača", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Možnosti filtrovania zaznamenávača", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Nie", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokované", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "povolené", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "zmenené", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Z prvej strany", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Z tretej strany", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Podrobnosti", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Zoznam filtrov", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Pravidlo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Kontext", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Koreňový kontext", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partnerská strana", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Typ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dynamické filtrovanie URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Kontext:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Typ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statické filtrovanie", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} sieťové požiadavky {{type}} {{br}}, ktorých URL adresa sa zhoduje s {{url}} {{br}}a pochádza {{origin}},{{br}}{{importance}} zodpovedajúci výnimkový filter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Zablokovať", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Povoliť", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "typu “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "akéhokoľvek typu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "z “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "z odkiaľkoľvek", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "pokiaľ neexistuje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "aj keď existuje", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statický filter {{filter}} bol nájdený v:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statický filter sa nepodarilo nájsť v žiadnom momentálne povolenom zozname filtrov", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Záznamy v zaznamenávači, ktoré nespĺňajú všetky 3 podmienky uvedené nižšie budú automatické zamietnuté:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Ponechať záznamy za posledných {{input}} minút", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Ponechať načítaných aspoň {{input}} strán na kartu", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Ponechať načítaných aspoň {{input}} položiek na kartu", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Pre každú položku zobraziť {{input}} riadky vo vertikálnom rozšírenom režime", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Skryť stĺpce:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Čas", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/pravidlo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Kontext", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Zdroj požiadavky", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Zoznam", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabuľka", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Neformátované", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Formátované", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Otvoriť", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Vytvoriť nové hlásenie", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Vyhľadať podobné hlásenia", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentácia", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Prečítajte si dokumentáciu na uBlock/wiki a dozviete sa o všetkých funkciách uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Otázky a podpora", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odpovede na otázky a iné druhy podpory pomoci sa poskytujú na subreddite /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problémy s filtrom/webová stránka je nefunkčná", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Nahlásenie problémov s filtrom s konkrétnymi webovými stránkami na uBlockOrigin/uAssets issue tracker. Vyžaduje sa GitHub účet.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Dôležité: Vyhnite sa používaniu iných podobne zameraných blokátorov spolu s uBlock Origin, pretože to môže spôsobiť problémy s filtrovaním na konkrétnych webových stránkach.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tipy: Uistite sa, že je váš zoznam filtrov aktuálny. Záznamenávač je primárnym nástrojom na diagnostiku problémov súvisiacich s filtrami.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Nahlásiť chybu", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Nahlásenie problémov so samotným uBlock Origin nauBlockOrigin/uBlock-issue issue tracker. Vyžaduje sa GitHub účet.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informácie o riešení problémov", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Nasledujú technické informácie, ktoré môžu byť užitočné, keď sa vám dobrovoľníci pokúšajú pomôcť vyriešiť problém.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Dôležité: Potenciálne súkromné alebo citlivé informácie sú štandardne upravované. Upravené informácie môžu sťažiť riešenie problému.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Nahlásiť problém s filtrom", + "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ý.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Zoznamy filtrov sa aktualizujú denne. Uistite sa, že váš problém už nebol vyriešený v najnovších zoznamoch filtrov.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Overte, či problém pretrváva aj po opätovnom načítaní problematickej webovej stránky.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa webovej stránky:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Webová stránka…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Vyberte položku --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Zobrazuje reklamy alebo zvyšky reklám", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Je prekrytá alebo má iné nedostatky", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Deteguje uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Má problémy súvisiace so súkromím", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Má problém s funkčnosťou, keď je povolený uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Otvára nechcené karty alebo okná", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Označiť webstránku ako “NSFW” (Nie je bezpečné pre prácu”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Upraviť", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Neupravovať", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Zásady ochrany osobných údajov", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Zoznam zmien", + "description": "" + }, + "aboutCode": { + "message": "Zdrojový kód (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Prispievatelia", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Zdrojový kód", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Preklady", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Zoznam filtrov", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Externé závislosti (kompatibilné s GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Vlastné zoznamy filtrov uBO sú voľne dostupné na nasledujúcich CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Pri aktualizácii zoznamu filtrov sa použije náhodne vybraná CDN.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Zálohovať do súboru", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-moja-záloha_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Obnoviť zo súboru...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Obnoviť na predvolené nastavenia...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Všetky vaše nastavenia budú prepísané pomocou dáta zálohovaných dňa {{time}} a uBlock sa reštartne.\n\nPrepísať všetky existujúce nastavenia pomocou zálohovaných dát?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Dáta sa nepodarilo načítať alebo sú neplatné", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Všetky vaše nastavenia budú odstránené a uBlock sa reštartne.\n\nObnoviť uBlock na predvolené nastavenia?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Chyba siete: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Pridať nasledujúcu URL do zoznamu vlastných filtrov?\n\nNázov: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Pridať", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "pred minútou", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "pred {{value}} minútami", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "pred hodinou", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "pred {{value}} hodinami", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "pred dňom", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "pred {{value}} dňami", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Zobraziť ovládací panel", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Zobraziť Zaznamenávač", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "vypnutý", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Blokovaná stránka", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin zabránil načítaniu nasledujúcej stránky:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Kvôli nasledujúcemu filtru", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bez parametrov", + "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": "Nájdený v:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Naspäť", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zatvoriť toto okno", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Už ma na túto stránku neupozorňovať", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Zakázať prísne blokovanie pre {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Dočasne", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Natrvalo", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Pokračovať", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportovať do cloudového úložiska", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importovať z cloudového úložiska", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importovať z cloudového úložiska a zlúčiť so súčasnými nastaveniami", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Názov tohto zariadenia:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Upozornenie! Zmenu pokročilých nastavení vykonávate na vlastné nebezpečenstvo.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Poslať", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Použiť zmeny", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Vrátiť", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajtov", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Zablokovať prvok v ráme…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Prihlásiť sa k odberu zoznamu filtrov…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Dočasne povoliť veľké multimediálne prvky", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Zobraziť zdrojový kód", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Zadajte klávesovú skratku", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Prepnúť zámok posúvania", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopírovať do schránky", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Vybrať všetko", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Prepnúť kozmetické filtrovanie", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Zmierniť režim blokovania", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Využité miesto: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kliknite pre načítanie", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Chyby: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Pri spustení prehliadača sa nepodarilo správne filtrovať.\nZnova načítajte stránku, aby ste zaistili správne filtrovanie.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sl/messages.json b/src/_locales/sl/messages.json new file mode 100644 index 0000000..7963d85 --- /dev/null +++ b/src/_locales/sl/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Končno, učinkovita, procesorju in pomnilniku prijazna razširitev za blokiranje oglasov.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Nadzorna plošča", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Pozor! Spremembe niso shranjene", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Ostani", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Prezri", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Nastavitve", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtri tretjih oseb", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Moji filtri", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Moja pravila", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Seznam dovoljenih", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Bližnjice", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Dnevnik omrežnih zahtev", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "O razširitvi", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Podpora", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — pregled sredstev", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Napredne nastavitve", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klik: onemogoči/omogoči uBlock₀ za to stran.\n\nCtrl+klik: onemogoči uBlock₀ samo na tej strani.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Kliknite, da onemogočite uBlock₀ za to stran.\n\nPritisnite Ctrl in kliknite, da onemogočite uBlock₀ samo na tej strani.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Kliknite, da omogočite uBlock₀ za to stran.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blokirane zahteve", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "na tej strani", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ali {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "od namestitve", + "description": "English: since install" + }, + "popupOr": { + "message": "ali", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blokirano na tej strani", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blokirano od namestitve", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Povezane domene", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Klikni za odpiranje nadzorne plošče", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Vklopi način izbire elementov", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Vklopi način izbire elementov", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Pojdi na dnevnik omrežnih zahtev", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Prijavi napako na tej strani", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Vklop/Izklop blokiranja vseh pojavnih oken za to stran", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Kliknite, da omogičite blokiranje vseh pojavnih oken za to stran", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Kliknite, da onemogočite blokiranje vsah pojavnih oken na tej strani", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Vklop/izklop blokiranja večjih medijev za to stran", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Kliknite, da omogičite blokiranje večjih medijev za to stran", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Kliknite, da onemogočite blokiranje večjih medijev za to stran", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Vklop/Izklop kozmetičnih filtrov za to stran", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Kliknite, da onemogočite kozmetično filtriranje na tej strani", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Kliknite, da omogočite kozmetično filtriranje na tej strani", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Vklopi/izklopi blokiranje oddaljenih pisav za to stran", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Kliknite, da omogočite blokiranje oddaljenih pisav na tej strani", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Kliknite, da onemogočite blokiranje oddaljenih pisav na tej strani", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klikni, da onemogočiš JavaScript na tej strani", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klikni, da prenehaš onemogočati JavaScript na tej strani", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pojavna okna", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Veliki predstavnostni elementi", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kozmetično filtriranje", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Oddaljene pisave", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Več", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Manj", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globalna pravila: ta stolpec je za pravila, ki se uveljavljajo za vse strani.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokalna pravila: ta stolpec je za pravila, ki se uveljavljajo samo za trenutno stran. Lokalna pravila preglasijo globalna pravila.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Kliknite za uveljavitev sprememb.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Kliknite za preklic sprememb.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "vse", + "description": "" + }, + "popupImageRulePrompt": { + "message": "slike", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "tretjih oseb", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "css/slike tretje osebe", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "vrinjene skripti", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "strani lastni skripti", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skripti tretjih oseb", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "okvirji tretjih oseb", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "povezane domene", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} od {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Različica", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Ustvari", + "description": "English: Create" + }, + "pickerPick": { + "message": "Izberi", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Končaj", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Predogled", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Omrežni filtri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kozmetični filtri", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klik, Ctrl-klik", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blokiraj element", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Skrij držala blokiranih elementov", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Prikaži število blokiranih zahtevkov na ikoni", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Onemogoči namige", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Izkoristite kontekstni meni, kjer je to primerno", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Način prijazen barvno slepim uporabnikom", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Izgled", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Barva akcenta po meri", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Omogoči podporo za shrambo v oblaku", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Sem napreden uporabnik (Potrebno branje)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Onemogoči prednalaganje strani (da se prepreči kakršno koli povezavo za blokirane zahteve omrežja)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Onemogoči revizijo hiperlinkov (Hyperlink-auditing)", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prepreči izpostavitev lokalnega IP naslova preko WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Privzeto ravnanje", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Te privzete nastavitve lahko spremenite za posamezne strani", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Onemogoči kosmetično filtriranje", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blokiraj medijske elemente večje kot {input:number} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blokiraj oddaljene pisave", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Onemogoči JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blokiraj CSP poročila", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Napredno", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funkcije primerne zgolj za napredne uporabnike", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "napredne nastavitve", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Zadnja obnovitev:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Zadnja varnostna kopija:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} omrežnih in {{cosmeticFilterCount}} kozmetičnih filtrov od:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "uporabljenih {{used}} od {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Samodejno posodabljanje seznama filtrov.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Posodobi zdaj", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Sprosti celoten predpomnilnik", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Razčleni in uveljavi kozmetične filtre.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

Ta opcija omogoči razčlenjevanje in uveljavljanje Adblock Plus kompatibilnih filtrov za “skrivanje elementov” Le-ti filtri so v bistvu kozmetični in služijo skrivanju elementov na spletnih straneh, ki jih lahko obravnavamo kot \"vizualna nadloga\", in taki, ki se jih preko filtrov zahtev omrežja ne da blokirati.

\n

Vklop te funkcije poveča spominski odtis uBlock₀.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignoriraj generične kozmetične filtre", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

Generični vizualni filtri so vizualni filtri, ki naj bi bili uporabljeni na vseh spletnih straneh.

Kljub temu, da je njihova uporaba v uBlock₀ učinkovita, generični vizualni filtri lahko, na nekaterih spletnih straneh (še posebno na velikih in starih), pripomorejo k opazni dodatni porabi pomnilnika in uporabi CPE.

Omogočitev te funkcije bo zmanjšala porabo pomnilnika in uporabo CPE, ki nastane kot rezultat dodajanja generičnih vizualnih filtrov, in tudi zmanjšala porabo pomnilnika dodatka uBlock₀.

Priporočeno je, da omogočite to možnost na manj zmogljivih napravah.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Prekini aktivnosti omrežja, dokler niso naloženi vsi filtri", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Seznam blokiranih gostiteljev", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Uveljavi spremembe", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Lokalno", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Oglasi", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Zasebnost", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Zlonamerne domene", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "\t\nNadlegovanje", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Večnamenski", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regije, jeziki", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Po meri", + "description": "Filter lists section name" + }, + "3pImport": { + "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.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "zastarelo", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Zadnja posodobitev: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Posodabljanje ...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Omrežna napaka je preprečila posodobitev virov.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "En filter na vrstico. Filter je lahko navadno ime gostitelja, ali pa Adblock Plus kompatibilen filter. Vrstice z znakom ‘!’ bodo ignorirane.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Uvozi in dodaj", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Izvozi", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "moji-ublock-staticni-filtri_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Uporabi spremembe", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Stalna pravila", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Začasna pravila", + "description": "header" + }, + "rulesRevert": { + "message": "Povrni", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Stori", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Uredi", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Shrani", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Zavrži", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Uvozi iz datoteke...", + "description": "" + }, + "rulesExport": { + "message": "Izvozi v datoteko", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "moji-ublock-dinamicna-pravila_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Seznam vaših dinamičnih pravil filtriranja.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Sintaksa pravil: vir destinacija tip akcija (polna dokumentacija (v angleščini)).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Razvrsti", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Tip pravila", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Vir", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Cilju", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Uvozi in dodaj", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Izvozi", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "moj-ublock-seznam-dovoljenih_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Uveljavi spremembe", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Vrsta", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domena", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Vse", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Za zaveso", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Trenutni zavihek", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Ponovno naloži vsebino zavihka", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Preklopi DOM pregledovalnik", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Preklopi pojavno okno", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Dnevnik omrežnih zahtev", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Počisti dnevnik omrežnih zahtev", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Ustavi dnevnik omrežnih zahtev (zavrne vse prihajajoče zahteve)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Nadaljuj dnevnik omrežnih zahtev", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Preklopi filtriranje dnevnika", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtriraj vnose dnevnika", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Nastavitve filtriranja dnevnika", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ni", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blokiran", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "dovoljeno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "spremenjeno", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1. osebni", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3. osebni", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Podrobnosti", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Seznam filtrov", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Pravilo", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Vsebina", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Glavna vsebina", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Pripadnost", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Vrsta", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Dinamično URL filtriranje", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Vsebina:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Vrsta:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statično filtriranje", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} zahteve omrežja {{type}} {{br}}katerih URL naslov se ujema z {{url}} {{br}}in izvirajo iz {{origin}},{{br}}{{importance}} obstaja ustrezen filter izjeme.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blokiraj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Dovoli", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "vrsta {{type}}", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "vsaka vrsta", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "iz “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "iz kjerkoli", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "razen če", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "tudi če", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statičen filter {{filter}} najden v:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statični filter {{filter}} ni bil najden v nobenem izmed trenutno izbranih seznamov", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Zapisi, ki ne ustrezajo vsem spodaj podanim pogojem, bodo avtomatsko zavrženi:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Ohrani vnose izpred zadnjih {{input}} minut", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Ohrani največ {{input}} nalaganj strani na zavihek", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Ohrani največ {{input}} vnosov na zavihek", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Uporabi {{input}} vrstic pri vsakem vnosu v navpično razširjenem načinu", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Skrij stolpce:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} čas", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} filter/pravilo", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} vsebina", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Pripadnost", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Seznam", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabela", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Navaden", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Odpri", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Ustvari novo poročilo", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Najdi podobna poročila", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacija", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Preberi dokumentacijo na uBlock/wiki, da izveš vse o funkcijah uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Vprašanja in podpora", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Odgovori na vprašanja in druga pomoč so na voljo na forumu /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Težave s filtrom/stran ne deluje", + "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.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Pomembno: Izogibajte se sočasni uporabi podobnih orodij za blokiranje, to lahko povzroči težave s filtrom na posameznih straneh.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: Preverjajte, da so vaši seznami filtrov redno posodobljeni. Zapisovalnik je glavno orodje za diagnostiko težav s filtri.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Prijavi napako", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Prijavi težave z uBlock Origin na uBlockOrigin/uBlock-issuesledilnik težav. Potreben je GitHub račun.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Informacije za odpravljanje težav", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Prijavi napako filtra", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Zaradi preprečitve obremenjevanja prostovoljcev s podvojenimi poročili prosim preveri da težava še ni bila sporočena.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Naslov spletne strani:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Spletna stran …", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Izberi vnos --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Prikaže reklame ali ostanke reklam", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ima probleme povezane z zasebnostjo", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Pravilnik o zasebnosti", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Dnevnik sprememb", + "description": "" + }, + "aboutCode": { + "message": "Izvorna koda (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Razvijalci", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Izvorna koda", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Prevodi", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Seznami filtrov", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Zunanje odvisnosti (GPLv3-kompatibilne):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ob posodobitvi seznama filtrov se uporabi naključno izbran CDN", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Naredi varnostno kopijo v datoteko", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "moja-ublock-varnostna-kopija_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Obnovi iz datoteke...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Ponastavi na privzete nastavitve...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Vse vaše nastavitve bodo prepisane s podatki, ki so bili varnostno shranjeni {{time}}. uBlock₀ se bo ponovno zagnal.\n\nPrepišem vse obstoječe nastavitve z varnostno shranjenimi podatki?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Podatki varnostne kopije niso uspeli biti uspešno prebrani oz. so neveljavni", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Vse vaše spremembe bodo izbrisane, uBlock₀ pa se bo ponovno zagnal.\n\nPonastavim uBlock₀ na tovarniške nastavitve?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Ne morem se povezati do {{url}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Dodam sledeči URL na listo lastnih filtrov?\n\nNaslov: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Naročite se", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 minuto nazaj", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minut nazaj", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "1 uro nazaj", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ur nazaj", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "1 dan nazaj", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dni nazaj", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Prikaži nadzorno ploščo", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Prikaži dnevnik", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "izklop", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock₀ je preprečil nalaganje naslednje strani:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Zaradi sledečega filtra", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "brez parametrov", + "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": "Najden v:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Nazaj", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Zapri to okno", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Onemogoči striktno blokiranje za {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Začasno", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Trajno", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Izvozi v shrambe oblaka", + "description": "tooltip" + }, + "cloudPull": { + "message": "Uvozi iz shrambe oblaka", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Uvozi iz oblaka in spoji s trenutnimi nastavitvami", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Ime te naprave:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Opozorilo! Sprememba teh naprednih nastavitev na lastno odgovornost.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Predloži", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Uveljavi spremembe", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Povrni", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "biti", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blokiraj element v okvirju", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Naroči se na seznam filtrov..", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Začasno dovoli velike medijske elemente", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Vnesite bližnjico", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Preklopi zaklenjeno drsenje", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiraj v odložišče", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Izberi vse", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Preklopi lepotno filtriranje", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Sprostite način blokiranja.", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Uporabljena shramba: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Kliknite za prikaz", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/so/messages.json b/src/_locales/so/messages.json new file mode 100644 index 0000000..08cc0ad --- /dev/null +++ b/src/_locales/so/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Ugu dambeyntii, xannibaado hufan. Ku fudud oo ku saabsan CPU iyo xusuusta.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock? - Dashboard", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Digniin! Waxaad leedahay isbedelo aan la keydin", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Joog", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Iska daa", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Dejinta", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Liisaska sifee", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "filtarradayda", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Xeerarkayga", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Goobaha lagu kalsoon yahay", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Jid gaaban", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock? - Logger", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Ku saabsan", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Taageero", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock? - Daawaha hantida", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Dejinta horumarsan", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Guji: dami/damar uBlock? goobtan. ", + "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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Ctrl+guji: dami uBlock? kaliya boggan.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "Guji si aad u joojiso uBlock? ee goobtan. ", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "on this page", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "Ctrl+guji si aad u joojiso uBlock? kaliya boggan.", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "Guji si aad awood ugu siiso uBlock? goobtan.", + "description": "English: since install" + }, + "popupOr": { + "message": "codsiyada la xannibay", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "boggan", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "{{count}} ({{boqolkiiba}}%)", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "tan iyo markii la rakibo", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "ama", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Xiray boggan", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Xirmay tan iyo markii la rakibay", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Domains ku xiran", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Fur dashboard-ka", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Geli qaabka zapper element", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Geli qaabka xulashada walxaha", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Fur qoraha", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Bedeli xannibaadda dhammaan soo-baxayaasha goobtan", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Guji si aad u xannibto dhammaan popup-yada goobtan", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Guji si aadan mar dambe u xannibin dhammaan soo-bandhigyada goobtan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "U beddel xannibaadda walxaha waaweyn ee warbaahinta ee goobtan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Guji si aad u xannibto qaybaha warbaahinta waaweyn ee boggan", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Guji si aanad mar dambe u xannibin qaybaha warbaahinta waaweyn ee boggan", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "U beddel shaandhaynta qurxinta goobtan", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Guji si aad u joojiso shaandhaynta isqurxinta ee goobtan", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Guji si aad awood ugu siiso shaandhaynta goobtan", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "U beddel xannibaadda xarfaha fog ee boggan", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Guji si aad u xannibto farta fog ee goobtan", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Guji si aadan mar dambe u xannibin farta fog ee goobtan", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Guji si aad JavaScript uga joojiso goobtan", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Guji si aad mar dambe u damin JavaScript ee goobtan", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "daaqadaha soo booda", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Qaybaha warbaahinta waaweyn", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Shaandhaynta qurxinta", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Farta fog", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "JavaScript", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Wax badan", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "In ka yar", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "Xeerarka caalamiga ah: tiirkan waxaa loogu talagalay xeerar khuseeya dhammaan bogagga.", + "description": "" + }, + "popupImageRulePrompt": { + "message": "Xeerarka maxalliga ah: tiirkan waxaa loogu talagalay xeerar khuseeya goobta hadda jirta oo keliya. ", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Xeerarka maxalliga ah ayaa meesha ka saaraya xeerarka caalamiga ah.", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Guji si aad isbeddelkaaga uga dhigto mid joogto ah.", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "Guji si aad u soo celiso isbedeladaada", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "dhammaan", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "sawiro", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "xisbiga 3aad", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "CSS/sawirrada xisbiga 3aad", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "xarfaha xariiqda", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Qoraallada xisbiga 1-aad", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "domains ku xiran", + "description": "English: Create" + }, + "pickerPick": { + "message": "{{tirinta}} ka baxsan {{ total}}", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Nooca", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "?: Xooga saar safafka leh meeraha xisbiga 3aad", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "?: Xooga saar safafka leh meeraha xisbiga 3aad", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Abuur", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Dooro", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Jooji", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Horudhac", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Shabakadda shabkada", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Shaandhooyinka qurxinta", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Guji, Ctrl-guji", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Cunsurka xannibi...", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Qari meel-hayeyaasha walxaha xanniban", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ku muuji tirada codsiyada la xannibay ee sumadda", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Isticmaal macnaha guud marka ay habboon tahay", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Midab-indho la'aan saaxiibtinimo", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Daar taageerada kaydinta daruuraha", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Waxaan ahay isticmaale horumarsan (akhris loo baahan yahay)", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "goobaha horumarsan", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Dami soo-keenista ka hor (si looga hortago xidhiidh kasta ee codsiyada shabakada la xidhay)", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Jooji xisaabinta hyperlink", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Ka ilaali WebRTC inay soo daadato cinwaannada IP-ga maxalliga ah", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Dabeecada aan caadiga ahayn", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Dabeecadahan aan caadiga ahayn waa laga gudbi karaa si ku saleysan goob kasta", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Dami shaandhaynta qurxinta", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "Dami tilmaanta aaladaha", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Jooji walxaha warbaahinta ee ka weyn {{input}} KB", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Jooji xarfaha fogfog", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "Dami JavaScript", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "Jooji warbixinnada CSP", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Ka fur magacyada canonical", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Soo celinta u dambaysay:", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Kaydka u dambeeya:", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "filtarrada shabkada {{netFilterCount}} ? {{cosmeticFilterCount}} filtarrada qurxinta ee:", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "{{la isticmaalay}} la isticmaalay {{ total}}", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Si otomaatig ah u cusbooneysii liisaska shaandhada", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Cusbooneysii hadda", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Kala saar oo dhaqan geli filtarrada qurxinta", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Shaandhooyinka isqurxintu waxay u adeegaan inay ku qariyaan walxaha ku jira bogga shabakadda kuwaas oo loo arko inay dhib ku yihiin aragga, oo aanay xannibi karin matoorada shaandhaynta ku salaysan codsiga shabakadda.", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Iska daa filtarrada guud ee qurxinta", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Shaandhooyinka isqurxinta guud waa filtarrada qurxinta kuwaas oo loogu talagalay in lagu dabaqo dhammaan shabakadaha internetka. Awood u yeelashada doorashadan waxay meesha ka saaraysaa xusuusta iyo dusha sare ee CPU ee lagu daray boggaga internetka taasoo ka dhalatay maaraynta filtarrada isqurxinta guud. ", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Waxaa lagu talinayaa in lagu suurtageliyo doorashadan aaladaha awoodda yar.", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Liisaska martida la xannibay", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Codso isbeddelada", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Lagu dhex dhisay", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Xayeysiisyada", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Qarsoodi", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Goobaha Malware", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "Cadhada", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Ujeedo badan", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Gobollada, luqadaha", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Caadiyan", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Soo deji...", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Hal URL laynkiiba. URL-yada aan ansax ahayn waa la iska indho-tiraa aamusnaan.", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Waqtigii dhacay", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "fiiri nuxurka", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Cusbooneysii ugu dambeysay: {{ago}} ", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Guji si aad u qasbi cusbooneysiinta", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Cusbooneysiinta...", + "description": "header" + }, + "rulesRevert": { + "message": "Cilad shabakadeed ayaa ka hor istaagtay in kheyraadka la cusboonaysiiyo.", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Hal filter halkii sadar Shaandheeyaha wuxuu noqon karaa magaca martida loo yahay ee cad, ama shaandhada ku habboon Adblock Plus. Khadadka horgalayaasha leh ! waa la iska indhatiraa", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Soo deji oo ku dheji", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Dhoofinta", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Codso isbeddelada", + "description": "" + }, + "rulesExport": { + "message": "Xeerarka joogtada ah", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "Xeerarka ku meel gaadhka ah", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Soo noqo", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Ballanqaad", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Wax ka beddel", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Badbaadin", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Tuur", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Ka soo deji faylka...", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "U Dhoofinta faylka", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Liiska xeerarka shaandhaynta firfircoon.", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "Xeerka syntax: nooca goobta loo socdo (full documents ).", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Kala sooc:", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Nooca qaanuunka", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Xigasho", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Meesha loo socdo", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Awaamiirta goobta lagu kalsoon yahay ayaa tilmaamaysa boggaga internetka ee uBlock Origin waa in la curyaamiyo. Hal gelitaan halkii sadar. Awaamiirta aan ansax ahayn si aamusnaan ah ayaa loo indhatiraa oo faallo looga bixin doonaa.", + "description": "English: Filter" + }, + "logAll": { + "message": "Soo deji oo ku dheji", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Dhoofinta", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Codso isbeddelada", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Nooca", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Domain", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "URL", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Shaandhayso", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Dhammaan", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Shaxda", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "tab hadda", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "Dib u soo rar nuxurka tab", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Bedeli kormeeraha DOM", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Beddel guddiga soo booda", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "Nadiifi logger", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "Jooji logger (ka tuur dhammaan xogta soo socota)", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "Jooji gooyaha", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Beddel shaandhaynta logger", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "shaandhayso waxa ku jira logger", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Xulashada shaandhaynta Logger", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Maya", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "dhacdo", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "xannibay", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "ogol yahay", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "wax laga beddelay", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "xisbiga 1aad", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "xisbiga 3aad", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Faahfaahin", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Shaandhayso", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Liiska kala shaandheynta", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Xeer", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Dulucda", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "macnaha guud", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Xaflada", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Nooca", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "URL", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "Xeerka URL", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "Dulucda:", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "Nooca:", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "Shaandheeyaha taagan", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "{{action}} codsiyada shabakada {{type}} {{br}} URL kee u dhigma {{url}} {{br}}oo asal ahaan ka soo jeeda {{asalka}},{{br}}{{{muhiimada} } waxaa jira shaandheyn ka reeban oo ku habboon.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Block", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Allow", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "ku qor \"{{type}}\"", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "nooc kasta", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "ka \"{{asalka}}\"", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "meel kasta ka yimid", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "marka laga reebo", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "xataa haddii", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "Shaandheeyaha taagan {{filter}} ayaa laga helay:", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "Shaandhaynta taagan lagama helin mid ka mid ah liisaska shaandhaynta hadda karti u leh", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "Gelida Logger ee aan buuxin dhammaan saddexda shuruudood ee hoose si toos ah ayaa loo tuurayaa:", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "Kaydi gelida daqiiqadihii ugu dambeeyay {{Input}}", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Ilaali ugu badnaan {{input}} culayska bogga tabkiiba", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Ilaali ugu badnaan {{input}} gelinta tab kasta", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Isticmaal {{input}} khadadka gelistaba qaab si toosan loo fidiyay", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Qari tiirarka:", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "{{Input}} Waqtiga", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "{{input}} Shaandhayso/xukun", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "{{Input}} Dulucda", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "{{Input}} Xaflada", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Liiska", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Miis", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Cad", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Markdown", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Furan", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Dukumeenti", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Ka akhri dukumeentiga uBlock/wiki si aad wax uga ogaato dhammaan astaamaha uBlock Origin.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Su'aalo iyo taageero", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Jawaabaha su'aalaha iyo noocyada kale ee taageerada caawimada waxaa lagu bixiyaa subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Arrimaha shaandhaynta/mareegaha ayaa jabay", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Ka warbixi arrimaha shaandhaynta shabakadaha gaarka ah uBlockOrigin/uAssets soo saara raadraacayaasha. Wuxuu u baahan yahay akoon GitHub", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Muhiim: Iska ilaali isticmaalka xannibaadaha kale ee la midka ah oo ay la socdaan uBlock Origin, sababtoo ah tani waxay sababi kartaa arrimo shaandhaynta shabakadaha gaarka ah.", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Talooyin: Hubi in liisaska shaandhayntaadu ay cusub yihiin. Logger waa aaladda koowaad ee lagu baadho arrimaha shaandhada la xiriira.", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Warbixinta cayayaanka", + "description": "" + }, + "aboutCode": { + "message": "Ka warbixi arrimaha uBlock Origin laftiisa uBlockOrigin/uBlock-issue arin tracker. Wuxuu u baahan yahay akoon GitHub", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Macluumaadka Cilad-bixinta", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Hoos waxaa ah macluumaadka farsamada oo laga yaabo inay faa'iido leedahay marka tabaruceyaashu ay isku dayayaan inay kaa caawiyaan xallinta dhibaatada.", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Muhiim: Macluumaad gaar ah ama mid xasaasi ah ayaa si toos ah wax looga beddelay. Macluumaadka dib loo habeeyey ayaa laga yaabaa inay sii adkeeyaan xallinta mushkiladda.", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Dib u habeyn", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Aan waxba laga beddelin", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Qaanuunka Arrimaha Khaaska ah", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Changelog", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Koodhka isha (GPLv3)", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "Wax ku darsaday", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Source code", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Turjumaada", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Liisaska sifee", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Ku tiirsanaanta dibadda (GPLv3-ku habboon):", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Liisaska shaandhaynta uBO ayaa si xor ah loogu martigaliyay kuwa soo socda CDNs:", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "CDN si aan kala sooc lahayn loo soo doortay ayaa la isticmaalaa marka liiska shaandhada loo baahan yahay in la cusboonaysiiyo", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Ku soo celi faylka", + "description": "No longer used" + }, + "subscribeButton": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "Ka soo celi faylka...", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "Dib u deji dejinta caadiga ah...", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "Dhammaan dejimahaaga waa lagu beddeli doonaa iyadoo la adeegsanayo xogta la xoojiyay {{waqtiga}}, iyo uBlock? ayaa dib u bilaaban doona. ", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} hours ago", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "Dib u qor dhammaan dejimaha jira adiga oo isticmaalaya xogta la taageeray?", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "Xogta lama akhrin karo ama waa khalad", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Dhammaan dejimahaaga waa laga saari doonaa, oo uBlock? dib ayuu u bilaabi doonaa. ", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "Dib u deji uBlock? u dejisay dejinta warshadda?", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "Cilada shabakada: {{msg}}", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "uBlock?: Ku dar URL-kan soo socda liisaska shaandhaynta gaarka ah? ", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Ciwaanka: \"{{ciwaanka}}\" ", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "URL: {{url}}", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Subscribe dheh", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "hal daqiiqo ka hor", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "{{value}} daqiiqo kahor", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "saacad ka hor", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "{{value}} saac kahor", + "description": "tooltip" + }, + "cloudPull": { + "message": "maalin ka hor", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "{{value}} maalmo kahor", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Muuji Logger", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "off", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "UBlock Origin ayaa ka diiday bogga soo socda in la soo raro:", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "shaandhada soo socota awgeed", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "aan xuduud lahayn", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "Laga helay:", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Ku noqo", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Xir daaqadan", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Dami xannibaadda adag ee {{hostname}}", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Si ku meel gaar ah", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Si joogto ah", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "U dhoofi kaydinta daruuraha", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Ka soo deji kaydinta daruuraha", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "... ", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "...", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "Qalabkan magaca:", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "Digniin! Beddel goobahan horumarsan khatartaada.", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "Gudbi", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Codso isbeddelada", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sq/messages.json b/src/_locales/sq/messages.json new file mode 100644 index 0000000..d6c5a65 --- /dev/null +++ b/src/_locales/sq/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Më në fund, një bllokues efikas që nuk e rëndon procesorin dhe memorien.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Paneli i kontrollit", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Kujdes! Nuk keni ruajtur ndryshimet", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Qëndroj", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Shpërfill", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Parametrat", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Listat e filtrave", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Filtrat e mi", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Rregullat e mia", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Faqet e besuara", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shkurtoret", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Regjistri i kërkesave", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Info", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Ndihma teknike", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Ilustruesi i aseteve", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Parametrat e avancuar", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Ç/aktivizoni uBlock₀ te ky uebsajti.\n\nKlikimi+Ctrl e çaktivizon uBlock₀ vetëm te kjo faqja.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Çaktivizoni uBlock₀ te ky uebsajti.\n\nKlikimi+Ctrl e çaktivizon uBlock₀ vetëm te kjo faqja.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Aktivizoni uBlock₀ te ky uebsajti.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "kërkesa të bllokuara", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "te kjo faqe", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ose {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "që prej instalimit", + "description": "English: since install" + }, + "popupOr": { + "message": "ose", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Te kjo faqe janë bllokuar", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Nga fillimi janë bllokuar", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domenet që janë lidhur", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Hapni panelin e kontrollit", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Asgjësuesi i elementeve", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Përzgjedhësi i elementeve", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Regjistri i kërkesave", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Raportoni problemin me uebsajtin", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Zh/Bllokoni të gjitha dritaret modale te uebsajti", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Bllokoni të gjitha dritaret modale te uebsajti", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Zhbllokoni të gjitha dritaret modale te uebsajti", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Zh/Bllokoni elementet e mëdha multimediale te uebsajti", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Bllokoni elementet e mëdha multimediale te uebsajti", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Zbllokoni elementet e mëdha multimediale te uebsajti", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Ç/Aktivizoni filtrat kozmetikë te uebsajti", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Çaktivizoni filtrat kozmetikë te uebsajti", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Aktivizoni filtrat kozmetikë te uebsajti", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Zh/Bllokoni modelet e jashtme shkronjore te uebsajti", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Bllokoni modelet e jashtme shkronjore te uebsajti", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Zhbllokoni modelet e jashtme shkronjore te uebsajti", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Çaktivizoni JavaScript-in te uebsajti", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Aktivizoni JavaScript-in te uebsajti", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Dritaret modale", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Elementet e mëdha multimediale", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Filtrat kozmetikë", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Modelet e jashtme shkronjore", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Më shumë", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Më pak", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Rregullat globale: rregullat në këtë shtyllë aplikohen për të gjitha uebsajtet.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Rregullat lokale: rregullat në këtë shtyllë aplikohen vetëm për këtë uebsajtin. \nKëto kanë përparësi mbi rregullat globale.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Ruani përgjithnjë ndryshimet.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Ktheni ndryshimet.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "të gjitha", + "description": "" + }, + "popupImageRulePrompt": { + "message": "imazhet", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "palët e treta", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/imazhet nga palët e treta", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "skriptet e integruara", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "skriptet nga pala kryesore", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "skriptet nga palët e treta", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "kuadrot nga palët e treta", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domenet që janë lidhur", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} nga {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Versioni", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "kuadër", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Krijoj", + "description": "English: Create" + }, + "pickerPick": { + "message": "Përzgjedh", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Mbyll", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Parashikoj", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Filtrat e rrjetit", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Filtrat kozmetikë", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Kliko, Kliko me Ctrl", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Bllokoj elementin…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Fsheh treguesin e elementeve të bllokuara", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Shfaq në ikonë numrin e kërkesave të bllokuara", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Çaktivizoj përshkrimet e shkurtra", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Përdor menunë kontekstuale sipas rrethanave", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Përshtat ngjyrat për daltonikët", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Paraqitja", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Motivi", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Personalizoj ngjyrën e theksuar", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktivizoj renë informatike", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Kam njohuri të thelluara", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Çaktivizoj kërkesat paraprake (për të shmangur lidhjet me kërkesat e bllokuara)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Çaktivizoj analizën e lidhjeve hipertekstuale", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Nuk lejoj WebRTC-në që të zbulojë adresat IP lokale", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Vlerat standarde", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Këto vlera mund të ndryshohen sipas uebsajtit", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Çaktivizoj filtrat kozmetikë", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Bllokoj elementet multimediale më të mëdha se {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Bllokoj modelet e jashtme shkronjore", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Çaktivizoj JavaScript-in", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Bllokoj raportet e CSP-së", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Demaskoj emrat kanonikë", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Parametrat e avancuar", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funksione të përshtatshme vetëm për specialistët", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "parametrat e avancuar", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Rindërtimi i fundit:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Kopja e fundit:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} filtra rrjeti + {{cosmeticFilterCount}} filtra kozmetikë nga:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "përdor {{used}} nga {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Përditësoj automatikisht filtrat", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Përditësoj tani", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Heq të gjitha stoqet", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Analizoj dhe zbatoj filtrat kozmetikë", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Filtrat kozmetikë shërbejnë për të fshehur nga ana vizive elementet e padëshirueshme të faqes, të cilat nuk bllokohen me metodën standarde të filtrimit sipas kërkesës.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Nuk marr parasysh filtrat kozmetikë jospecifikë", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Filtrat kozmetikë jospecifikë janë filtra që aplikohen për të gjitha faqet e internetit. Me aktivizimin e këtij opsioni ulet ngarkesa e memories dhe procesorit.\n\nKy opsion rekomandohet për aparatet kompjuterike jo shumë të shpejta.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Pezulloj aktivitetin deri kur të jenë gati të gjitha listat", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lista e hosteve të bllokuara", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Ruaj ndryshimet", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Lokale", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamat", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Privatësia", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Domenet e rrezikshme, siguria", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Elementet e bezdisshme", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Për qëllime të ndryshme", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Sipas rajonit, gjuhës", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Personale", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importoj…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Një URL për rresht. Nuk do të merren parasysh adresat e pasakta.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "E vjetër.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "shfaqni përmbajtjen", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Përditësimi i fundit: {{ago}}.\nKlikoni për ta përditësuar vetë.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Përditëson…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Një problem me rrjetin kompjuterik pengoi përditësimin e informacionit.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Një filtër për rresht. Filtri mund të jetë thjesht emri i një hosti ose si ata që përdor EasyList. Nuk do të merren parasysh rreshtat që fillojnë me !.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Mos shtoni filtra nga burime të pabesueshme.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importoj dhe shtoj…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Eksportoj…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Ruaj ndryshimet", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Rregullat e përhershme", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Rregullat e përkohshme", + "description": "header" + }, + "rulesRevert": { + "message": "Rikthej", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Aplikoj", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Modifikoj", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Regjistroj", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Anuloj", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importoj nga skedari…", + "description": "" + }, + "rulesExport": { + "message": "Eksportoj në skedar…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista e rregullave për filtrimin dinamik.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rregullat e sintaksës: burimi destinacioni lloji veprimi (dokumentimi i plotë).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Rendit:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Lloji i rregullës", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Burimi", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destinacioni", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Kjo listë paraqet faqet e besuara të internetit në të cilat uBlock Origin duhet çaktivizuar. Një element për rresht.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importoj dhe shtoj…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Eksportoj…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Ruaj ndryshimet", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Lloji", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domeni", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtri", + "description": "English: Filter" + }, + "logAll": { + "message": "Të gjitha", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Në prapaskenë", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Skeda aktuale", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Freskoni përmbajtjen e skedës", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Ç/Aktivizoni strukturën DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Ç/Aktivizoni panelin modal", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Regjistri i kërkesave", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Pastroni regjistrin", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Ndërprisni regjistrimin (e gjithë të dhënave të tjera)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Rifilloni regjistrimin", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Ç/Aktivizoni filtrat e regjistrit", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtroni zërat në regjistër", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Opsionet e filtrimit të regjistrit", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Jo", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "plot ngjarje", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "e bllokuar", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "e lejuar", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "e modifikuar", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "palët kryesore", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "palët e treta", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detajet", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtri", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Lista e filtrave", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Rregulla", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Konteksti", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Konteksti bazë", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Palët", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Lloji", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Filtrimi sipas URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Konteksti:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Lloji:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Filtrimi statik", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} kërkesat e {{type}} {{br}}që korrespondojnë me adresën {{url}} {{br}}dhe që e kanë origjinën {{origin}},{{br}}{{importance}} ekziston një filtër përjashtues i njëjtë.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Bllokoj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Lejoj", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "llojit “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "çdo lloji", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "nga “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "ngado", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "përveçse kur", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "edhe kur", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Filtri statik {{filter}} gjendet në:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Nuk u gjet filtri statik në asnjërën prej listave aktive", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Zërat në regjistër do të fshihen automatikisht kur nuk plotësojnë këto tri kushte:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Ruaj zërat e {{input}} minutave të fundit", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Ruaj jo më shumë se {{input}} faqe të reja për skedë", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Ruaj jo më shumë se {{input}} zëra për skedë", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Në pamjen e zgjeruar përdor {{input}} rreshta për zë", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Shtyllat e fshehura:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Ora", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtri/rregulla", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Konteksti", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Palët", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Listë", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabelë", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "E paformatuar", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Hap", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Krijoj raport të ri", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Gjej raporte të ngjashme", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentacioni", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Lexoni uBlock/wiki që të mësoni më shumë për funksionet e uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Pyetjet dhe ndihma teknike", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Në forumin e dedikuar Reddit /r/uBlockOrigin mund të bëni pyetje dhe të kërkoni çdolloj ndihme tjetër.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Problemet me filtrat/faqet me defekte", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Problemet e disa faqeve me filtrat duhen raportuar në ditarin e problemeve uBlockOrigin/uAssets. Duhet një konto GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Kujdes: uBlock Origin nuk duhet përdorur njëkohësisht me aplikacione të ngjashme bllokuese, pasi mund të keni probleme me filtrat.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Këshilla: Sigurohuni që të përditësoni listat e filtrave. Regjistri është instrumenti kryesor për diagnostikimin e problemeve me filtrat.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Raportimi i problemeve", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Problemet e uBlock Origin duhen raportuar në ditarin e problemeve uBlockOrigin/uBlock-issue. Duhet një konto GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Diagnostikimi i problemeve", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Informacioni teknik i mëposhtëm u shërben personave të cilët përpiqen të zgjidhin problemin që keni.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Kujdes: Informacionet me sfond privat dhe delikat censurohen automatikisht. Informacioni i censuruar mund ta vështirësojë zgjidhjen e problemit.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Raportoni problemet me filtrat", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Verifikoni a është raportuar më parë problemi që të mos i lodhni vullnetarët e tjerë me të njëjtat gjëra.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Listat e filtrave përditësohen rregullisht. Sigurohuni që problemi qëndron edhe me listat e reja.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verifikoni a qëndron problemi nëse e freskoni sërish faqen në fjalë.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Adresa e faqes:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Faqja…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Zgjidhni --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shfaq reklama ose pjesë reklamash", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ka mbivendosje ose parregullsi të tjera", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "E di që përdor uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ka probleme me privatësinë", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Bllokohet kur aktivizoj uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Hap skeda ose dritare të panevojshme", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Etiketoj faqen si “NSFW” (“E papërshtatshme për punë”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Censuroj", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Nuk censuroj", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Politika e privatësisë", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Ditari i ndryshimeve", + "description": "" + }, + "aboutCode": { + "message": "Materiali burimor (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Kontribuesit", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Materiali burimor", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Përkthimet", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Listat e filtrave", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Programet kushtëzuese (sipas GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Listat e filtrave të uBO mundësohen falas në CDN-të e mëposhtme:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Përditësimi i listave do të kryhet nëpërmjet një CDN-je rastësore.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Kopjoj në skedar…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Rindërtoj sipas skedarit…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Kthej parametrat fillestarë…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Të gjithë parametrat do të mbishkruhen me të dhënat e kopjuara më {{time}}, dhe uBlock₀ do të hapet sërish.\n\nDo mbishkruani parametrat aktualë?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Të dhënat nuk lexohen ose mund të jenë dëmtuar", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Të gjithë parametrat do të fshihen dhe uBlock₀ do të hapet sërish.\n\nDo ktheni parametrat origjinalë?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Problem me rrjetin kompjuterik: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Do e shtoni adresën në listën e personalizuar të filtrave?\n\nTitulli: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abonohem", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "një minutë më parë", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuta më parë", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "një orë më parë", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} orë më parë", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "një ditë më parë", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} ditë më parë", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Paneli i kontrollit", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Regjistri i kërkesave", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "fikur", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Faqe e bllokuar", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin po pengon hapjen e faqes:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Për shkak të filtrit", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "pa parametra", + "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": "Gjendet në:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Kthehem", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Mbyll dritaren", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Mos më lajmëro për këtë faqen", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Zhbllokoj mënyrën strikte për {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Përkohësisht", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Gjithnjë", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Vazhdoj", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Eksportoni në renë informatike", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importoni nga reja informatike", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importoni nga reja informatike dhe bashkoni me parametrat aktualë", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Emri i aparatit:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Kujdes! Mbani ju përgjegjësi nëse i ndryshoni parametrat e avancuar.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Parashtroj", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Ruaj ndryshimet", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Rikthej", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bajt", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Bllokoj elementin në kuadër…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Abonohem në listën e filtrave…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Lejoj përkohësisht elementet e mëdha multimediale", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Shikoj kodin burimor…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Vendosni kombinimin", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Ç/Aktivizoni lëvizjen me rrëshqitje", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopjoj në memorie", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Përzgjedh të gjitha", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Ç/Aktivizoj filtrat kozmetikë", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Dobësoj mënyrën e bllokimit", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Hapësira e përdorur: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klikoni për ta hapur", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Probleme: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Kur hapet shfletuesi nuk bëhet filtrimi i duhur. Freskoni faqen për ta filtruar mirë.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sr/messages.json b/src/_locales/sr/messages.json new file mode 100644 index 0000000..54ee936 --- /dev/null +++ b/src/_locales/sr/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Коначно, ефикасан блокатор. Ниски процесорски и меморијски захтеви.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Контролна табла", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Упозорење! Имате промене које нису сачуване", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Остани", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Игнориши", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Подешавања", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Листе филтера", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Моји филтери", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Моја правила", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Поуздани сајтови", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Пречице", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Евиденција", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "О програму", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Подршка", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Прегледач ресурса", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Напредна подешавања", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Клик: онемогући/омогући µBlock₀ за овај сајт.\n\nCtrl+клик: онемогући/омогући µBlock₀ само за ову страницу.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Кликните да бисте онемогућили µBlock₀ за овај сајт.\n\nCtrl+клик да бисте онемогућили µBlock₀ само на овој страници.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Кликните да бисте омогућили µBlock₀ за овај сајт.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "блокирани захтеви", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на овој страници", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} или {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "од инсталације", + "description": "English: since install" + }, + "popupOr": { + "message": "или", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Блокирано на овој страници", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Блокирано од инсталације", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Повезани домени", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Отвори контролну таблу", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Режим уклањања елемената", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Режим избора елемената", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Отвори евиденцију", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Пријавите проблем на овом веб сајту", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Укључи/искључи блокирање свих искачућих прозора за овај сајт", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Кликните за блокирање свих искачућих прозора на овом сајту", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Кликните да бисте зауставили блокирање свих искачућих прозора на овом сајту", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Укључи/искључи блокирање великих мултимедијалних елемената за овај сајт", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Кликните за блокирање великих мултимедијалних елемената на овом сајту", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Кликните да бисте зауставили блокирање великих мултимедијалних елемената на овом сајту", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Укључи/искључи естетско филтрирање за овај сајт", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Кликните да бисте онемогућили естетско филтрирање на овом сајту", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Кликните да бисте омогућили естетско филтрирање на овом сајту", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Укључи/искључи блокирање удаљених фонтова за овај сајт", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Кликните за блокирање удаљених фонтова на овом сајту", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Кликните да бисте зауставили блокирање удаљених фонтова на овом сајту", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Кликните да онемогућите JavaScript на овом сајту", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Кликните да JavaScript не буде више онемогућен на овом сајту", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Искачући прозори", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Велики мултимедијски елементи", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Естетско филтрирање", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Удаљени фонтови", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Више", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Мање", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Општа правила: ова колона је за правила која се примењују на свим сајтовима.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Локална правила: ова колона је за правила која се примењују само на тренутном сајту.\nЛокална правила имају предност у односу на општа.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Кликните да бисте промене учинили трајним.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Кликните да бисте вратили промене.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "све", + "description": "" + }, + "popupImageRulePrompt": { + "message": "слике", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "треће стране", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/слике трећих страна", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "уметнуте скрипте", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Корисничке скрипте", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Скрипте трећих страна", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Оквири трећих страна", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "повезани домени", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} од {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Верзија", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "скрипта", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "оквир", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Креирај", + "description": "English: Create" + }, + "pickerPick": { + "message": "Изабери", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Изађи", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Преглед", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Мрежни филтери", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Естетски филтери", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Клик, Ctrl-клик", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Блокирај елемент...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Сакриј држаче блокираних елемената", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Прикажи број блокираних захтева на иконици", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Онемогући описе алатке", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Користи контекстни мени где је прикладно", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Мод за далтонисте", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Изглед", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Тема", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Прилагођена наглашена боја", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Укључи подршку за складиште у облаку", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Ја сам напредни корисник", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Онемогући оптимизацију учитавања (да би се спречила свака веза блокираних мрежних захтева)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Онемогући проверавање хиперлинкова", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Спречи WebRTC да пропушта локалну IP адресу", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Подразумевано понашање", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Ова подразумевана понашања могу бити поништена за појединачне веб сајтове", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Онемогући естетско филтрирање", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блокирај мултимедијалне елементе веће од {{input}} kB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блокирај удаљене фонтове", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Онемогући JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Блокирај CSP извештаје", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Откриј канонска имена", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Напредно", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Функције прикладне само за техничке кориснике", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "напредна подешавања", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Последње враћање:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Последња резервна копија:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "мрежних филтера: {{netFilterCount}} + естетских филтера: {{cosmeticFilterCount}} из:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} искоришћено од {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Аутоматски ажурирај листе филтера", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Ажурирај сада", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Очисти сав кеш", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Рашчлани и примени естетске филтере.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Естетски филтери служе за сакривање елемената на веб страници који се сматрају визуелном сметњом и који не могу бити блокирани од стране мрежних захтева базираних на филтрирању.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Игнориши опште естетске филтере.", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Општи естетски филтери су они естетски филтери који су намењени за примену на свим сајтовима. Омогућавањем ове опције, елиминисаће се повећана потрошња меморије и оптерећење процесора на страницама као резултат руковања општим естетским филтерима.\n\nПрепоручује се да се ова опција омогући на мање моћним уређајима.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Обустави мрежну активност док се не учитају све листе филтера", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Списак блокираних хостова", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Примени промене", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Уграђени", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Рекламе", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Приватност", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Заштита од злонамерног софтвера, безбедност", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Сметње", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Вишенаменски", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Регионални, језички", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Прилагођени", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Увези...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Једна адреса по реду. Неисправне адресе ће бити тихо игнорисане.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Застарело.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "приказ садржаја", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Последње ажурирање: {{ago}}.\nКликните да бисте ажурирали.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Ажурирање...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Грешка на мрежи је спречила ажурирање ресурса.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Један филтер по реду. Филтер може бити назив хоста или филтер компатибилан са EasyList форматом. Редови са префиксом ! ће бити игнорисани.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Не додавај филтере из непоузданих извора.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Увези и додај", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Извези", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "моји-ublock-филтери_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Примени промене", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Стална правила", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Привремена правила", + "description": "header" + }, + "rulesRevert": { + "message": "Врати", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Потврди", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Уреди", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Сачувај", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Одбаци", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Увези из датотеке...", + "description": "" + }, + "rulesExport": { + "message": "Извези у датотеку...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "моја-ublock-динамичка-правила_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Списак правила за динамичко филтрирање.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Правила синтаксе: извор одредиште тип акција(сва документација).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Сортирај:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тип правила", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Извор", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Одредиште", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Смернице поузданих сајтова диктирају на којим веб страницама uBlock Origin треба да буде онемогућен. Један унос по реду.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Увези и додај", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Извези", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "моји-ublock-поуздани-сајтови_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Примени промене", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тип", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Филтер", + "description": "English: Filter" + }, + "logAll": { + "message": "Све", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Иза сцене", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Тренутна картица", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Поновно учитавање садржаја картице", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Укључи/искључи DOM инспектор", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Укључи/искључи искачући панел", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Евиденција", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Очисти евиденцију", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Паузирај евиденцвију (одбаци све долазне податке)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Настави евидентирање у дневнику", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Укључи/искључи филтрирање евиденције", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "филтрирај уносе евиденције", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Опције филтрирања евиденције", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Не", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "важно", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "блокирано", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "дозвољено", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "измењено", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "прве стране", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "треће стране", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Детаљи", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Филтер", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Листа филтера", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правило", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Контекст корена", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Страна", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тип", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Правило URL адресе", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тип:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статички филтер", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} мрежни захтев {{type}} {{br}} чија УРЛ адреса одговара {{url}} {{br}} и која долази од {{origin}},{{br}} {{importance}} постоји одговарајући филтер изузетак.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блокирај", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Дозволи", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "тип “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "сваки тип", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "од “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "било одакле", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "осим кад", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "чак иако", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Статички филтер {{filter}} пронађен у:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Статички филтер није могуће пронаћи нити у једној тренутно омогућеној листи филтера", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Уноси у евиденцији који не испуњавају сва три услова испод биће аутоматски одбачени:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Задржи уносе из последњих {{input}} минута", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Задржи највише {{input}} учитавања страница по картици", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Задржи највише {{input}} уноса по картици", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Користи {{input}} линија по уносу у усправном проширеном режиму", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Сакриј колоне:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Време", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Филтер/правило", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Контекст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Страна", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Листа", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Табела", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Обично", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Отвори", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Креирај нови извештај", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Пронађи сличне извештаје", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Документација", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "\nПрочитајте документацију на uBlock/wiki да бисте сазнали све о функцијама uBlock Origin-а.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Питања и подршка", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Одговори на питања и друге врсте подршке налазе се у подредиту /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Проблеми са филтером/веб сајт не фукционише", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Пријавите проблеме са филтерима на одређеним веб сајтовима на uBlockOrigin/uAssets, страници за праћење проблема. Неопходан је GitHub налог.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Важно: Избегавајте коришћење других блокатора сличне намене заједно са uBlock Origin-ом, јер то може изазвати проблеме са филтерима на одређеним веб сајтовима.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Савет: Уверите се да су ваше листе филтера ажуриране. Управљач евиденцијом је примарни алат за дијагностиковање проблема у вези са филтером.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Пријава грешке", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Пријавите проблеме са самим uBlock Origin-ом на uBlockOrigin/uBlock-issue, страници за праћење проблема. Неопходан је GitHub налог.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Информација о решавању проблема", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Испод су техничке информације које могу бити корисне када волонтери покушавају да вам помогну да решите проблем.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Важно: Потенцијално приватне или осетљиве информације се подразумевано редигују. Редиговане информације могу отежати решавање проблема.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Пријављивање проблема са филтером", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Да не бисте оптерећивали волонтере дуплим извештајима, проверите да ли је проблем већ пријављен.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Листе филтера се ажурирају свакодневно. Уверите се да ваш проблем није већ решен у најновијим листама филтера.\n", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Проверите да ли проблем и даље постоји након поновног учитавања проблематичне веб странице.\n", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Адреса веб странице:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Веб страница...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Изаберите ставку --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Приказује рекламе или остатке реклама", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Има преклапања или друге сметње", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Открива uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Има проблеме у вези са приватношћу", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Фукционише неправилно када је uBlock Origin омогућен", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "\nОтвара нежељене картице или прозоре", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Изначите веб страницу као „NSFW“ (“Није безбедна за рад”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Редигуј", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Поништи редиговање", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Политика приватности", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Списак измена", + "description": "" + }, + "aboutCode": { + "message": "Изворни код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Сарадници", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Изворни код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Преводи", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Листе филтера", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Спољне зависности (компатибилно са GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Сопствене листе филтера uBO-a се слободно хостују на следећим CDN-овима:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Насумично одабрани CDN се користи када листу филтера треба ажурирати.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Сачувај резервну копију у датотеку...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Врати из датотеке...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Врати на подразумевана подешавања...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Сва ваша подешавања ће бити прегажена резервном копијом података сачуваним {{time}} и uBlock₀ ће се поново покренути.\n\nПрегазити сва постојећа подешавања резервном копијом података?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Подаци се не могу прочитати или су неисправни", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Сва ваша подешавања ће бити обрисана и µBlock ће се поново покренути.\n\nВрати µBlock на првобитна подешавања?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Грешка на мрежи: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Додати следећу URL адресу у вашу прилагођену листу филтера?\n\nНазив: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Претплати се", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "пре један минут", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "пре {{value}} минута", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "пре један сат", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "пре {{value}} сата/и", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "пре један дан", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "пре {{value}} дана", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Прикажи контролну таблу", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Прикажи евиденцију", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "искључен", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Страница је блокирана", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin је спречио учитавање следеће странице:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "због следећег филтера", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Пронађен у:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Иди назад", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Затвори овај прозор", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Не упозоравај ме поново на овај сајт", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Искључи строго блокирање за {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Привремено", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Трајно", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Настави", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Извези у складиште у облаку", + "description": "tooltip" + }, + "cloudPull": { + "message": "Увези из складишта у облаку", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Увези из складишта у облаку и споји са тренутним подешавањима", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Назив овог уређаја:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Упозорење! Мењате ова напредна подешавања на сопствени ризик.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Пошаљи", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Примени промене", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Врати", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "бајтови", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Блокирај елемент у оквиру...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Претплатите се на листу филтера...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Привремено дозволи велике мултимедијалне елементе", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Прикажи изворни код…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Укуцајте пречицу", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Закључај/откључај померање", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Копирај у оставу", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Изабери све", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Укључи/искључи естетско филтрирање", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Опуштени режим блокирања", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Искоришћеност складишта: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "kB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Кликните за учитавање", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Грешака: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Није могуће правилно филтрирати при покретању прегледача. Поново учитајте страницу да бисте осигурали правилно филтрирање.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json new file mode 100644 index 0000000..b091a77 --- /dev/null +++ b/src/_locales/sv/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Äntligen en effektiv blockerare. Snäll mot både processor och minne.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Kontrollpanel", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Varning! Du har inte sparat dina ändringar", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stanna kvar", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignorera", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Inställningar", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filterlistor", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Mina filter", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Mina regler", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Betrodda webbplatser", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Genvägar", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Loggaren", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Om", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Tillgångsvisare", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Avancerade inställningar", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Klick: inaktivera/aktivera uBlock₀ för denna webbplats.\n\nCtrl+klick: inaktivera uBlock₀ enbart på denna sida.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Klicka för att inaktivera uBlock₀ för denna webbplats.\n\nCtrl+klicka för att inaktivera uBlock₀ enbart på denna sida.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Klicka för att aktivera uBlock₀ på denna webbplats.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "blockerade förfrågningar", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "på denna sida", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "sedan installationen", + "description": "English: since install" + }, + "popupOr": { + "message": "eller", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blockerat på denna sida", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blockerat sedan installationen", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Anslutna domäner", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Öppna kontrollpanelen", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Gå till elementzapperläge", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Gå till elementväljarläge", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Öppna loggaren", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Rapportera ett problem på denna webbplats", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Växla blockering av popup-fönster för den här webbplatsen", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Klicka för att blockera alla popup-fönster på denna webbplats", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Klicka för att inte längre blockera alla popup-fönster på denna webbplats", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Växla blockering av stora medieelement för denna webbplats", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Klicka för att blockera stora medieelement på denna webbplats", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Klicka för att inte längre blockera stora medieelement på denna webbplats", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Växla kosmetiska filter för denna webbplats", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Klicka för att inaktivera kosmetiska filter på denna webbplats", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Klicka för att aktivera kosmetisk filtrering på denna webbplats", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Växla blockeringen av fjärrtypsnitt på denna webbplats", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Klicka för att blockera fjärrtypsnitt på denna webbplats", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Klicka för att inte längre blockera fjärrtypsnitt på denna webbplats", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Klicka för att inaktivera JavaScript på denna webbplats", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Klicka för att aktivera JavaScript på denna webbplats", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Popup-fönster", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Stora medieelement", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kosmetisk filtrering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fjärrtypsnitt", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mer", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Mindre", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Globala regler: den här kolumnen avser regler som gäller för alla webbplatser.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Lokala regler: den här kolumnen avser endast regler som gäller för den aktuella webbplatsen.\nLokala regler åsidosätter globala regler.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Klicka för att göra dina ändringar permanenta.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Klicka för att ångra dina ändringar.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "alla", + "description": "" + }, + "popupImageRulePrompt": { + "message": "bilder", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Tredjepart", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/bilder från tredjepart", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "inline skript", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Förstapartskript", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Tredjepartskript", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Tredjepartramar", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "anslutna domäner", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} av {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "skript", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ram", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Skapa", + "description": "English: Create" + }, + "pickerPick": { + "message": "Välj", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Avsluta", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Förhandsgranska", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Nätverksfilter", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kosmetiska filter", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Klick, Ctrl-klick", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Blockera element…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Dölj platshållare för blockerade element", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Visa antalet blockerade förfrågningar på ikonen", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Inaktivera verktygstips", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Använd innehållsmenyn där det är lämpligt", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Färgblindsanpassat", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Utseende", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Anpassad accentfärg", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Aktivera stöd för molnlagring", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Jag är en avancerad användare", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Inaktivera förhämtning (för att förhindra anslutning av blockerade nätverksförfrågningar)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Inaktivera hyperlänksrevidering", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Förhindra WebRTC från att läcka lokala IP-adresser", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Standardbeteende", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Dessa standardbeteenden kan åsidosättas per webbplats", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Inaktivera kosmetisk filtrering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Blockera medieelement större än {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Blockera fjärrtypsnitt", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Inaktivera JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Blockera CSP-rapporter", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Ta fram kanoniska namn", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Avancerat", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Funktioner som endast är lämpliga för tekniska användare", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "avancerade inställningar", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Senast återställd:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Senaste säkerhetskopia:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} nätverksfilter + {{cosmeticFilterCount}} kosmetiska filter från:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} använda av {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Uppdatera filterlistor automatiskt", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Uppdatera nu", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Rensa alla cachar", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Tolka och tillämpa kosmetiska filter", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kosmetiska filter tjänar till att dölja element på en webbsida som bedöms vara en visuell olägenhet och som inte kan blockeras av nätverksbegärningsbaserade filtermotorer.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignorera allmänna kosmetiska filter", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Allmänna kosmetiska filter är de kosmetiska filter som är avsedda att tillämpas på alla webbplatser. Att aktivera detta alternativ kommer att eliminera minnes- och processoranvändningen som läggs till på webbsidor som ett resultat av hantering av allmänna kosmetiska filter.\n\nDet rekommenderas att aktivera detta alternativ på mindre kraftfulla enheter.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Stäng av nätverksaktiviteten tills alla filterlistor har laddats", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Listor över blockerade värdar", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Verkställ ändringar", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Inbyggda", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Annonser", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Integritet", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Skydd mot skadlig programvara, säkerhet", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Störande", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Mångsidiga", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Regioner, språk", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Anpassade", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Importera…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "En webbadress per rad. Ogiltiga webbadresser ignoreras tyst.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Föråldrad.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "visa innehåll", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Senast uppdaterad: {{ago}}\nKlicka för att påtvinga en uppdatering.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Uppdaterar…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Ett nätverksproblem har förhindrat resursen från att uppdateras.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Ett filter per rad. Ett filter kan vara ett vanligt värdnamn eller ett EasyList-kompatibelt filter. Rader med prefixet ! ignoreras.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Lägg inte till filter från opålitliga källor.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Importera och lägg till…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Exportera…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "mina-ublock-statiska-filter_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Verkställ ändringar", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanenta regler", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporära regler", + "description": "header" + }, + "rulesRevert": { + "message": "Ångra", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Skicka", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Redigera", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Spara", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Förkasta", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Importera från fil…", + "description": "" + }, + "rulesExport": { + "message": "Exportera till fil…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "mina-ublock-dynamiska-regler_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Lista över dina dynamiska filterregler.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Regelsyntax: källa mål typ åtgärd (full dokumentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sortera:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Regeltyp", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Källa", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Mål", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Direktiven för betrodda webbplatser anger vilka webbsidor som uBlock Origin ska inaktiveras på. En post per rad.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Importera och lägg till…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Exportera…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "mina-ublock-betrodda-webbplatser_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Verkställ ändringar", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Typ", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domän", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "Alla", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Bakom kulissen", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Aktuell flik", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Uppdatera flikinnehåll", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Växla DOM-inspektören", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Växla popup-panelen", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Loggaren", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Rensa loggaren", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Pausa loggaren (kassera alla inkommande data)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Fortsätt loggaren", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Växla loggarens filtrering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filtrera loggarens innehåll", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Loggarens filtreringsalternativ", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Inte", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "händelserikt", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blockerad", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "tillåten", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "ändrad", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Förstapart", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Tredjepart", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Detaljer", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filter", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filterlista", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Regel", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Innehåll", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Rotinnehåll", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partsrelation", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Typ", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "Webbadress", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Webbadressregel", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Innehåll:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Typ:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statiskt filter", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} nätverksförfrågningar av {{type}} {{br}}vilkas webbadresser matchar {{url}} {{br}}och som kommer från {{origin}},{{br}}{{importance}} det finns ett matchande undantagsfilter.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Blockera", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Tillåt", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "typ \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "alla typer", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "från \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "från var som helst", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "utom när", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "även om", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Det statiska filtret {{filter}} hittades i:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statiskt filter kunde inte hittas i någon av de aktuella aktiverade filterlistorna", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Loggarens poster som inte uppfyller alla tre villkoren nedan kommer automatiskt att kasseras:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Bevara poster från de {{input}} senaste minuterna", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Bevara högst {{input}} sidinläsningar per flik", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Bevara högst {{input}} poster per flik", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Använd {{input}} rader per inmatning i vertikalt expanderat läge", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Dölj kolumner:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tid", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/regel", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Innehåll", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partsrelation", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Lista", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tabell", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Enkel", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Öppna", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Skapa ny rapport", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Hitta liknande rapporter", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Dokumentation", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Läs dokumentationen på uBlock/wiki för att lära dig allt om uBlock Origins funktioner.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Frågor och support", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Svar på frågor och andra typer av hjälp finns på subredditen /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filterproblem/webbplatsen fungerar inte", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Rapportera filterproblem med specifika webbplatser till uBlockOrigin/uAssets problemhanteringssystemet. Kräver ett GitHub-konto.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Viktigt: Undvik att använda andra reklamblockerare tillsammans med uBlock Origin, eftersom detta kan orsaka filterproblem på specifika webbplatser.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Tips: Se till att dina filterlistor är uppdaterade. Loggaren är det primära verktyget för att diagnostisera filterrelaterade problem.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Felrapport", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Rapportera problem med själva uBlock Origin till uBlockOrigin/uBlock-issue ärendehanteringssystemet. Kräver ett GitHub-konto.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Felsökningsinformation", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Nedan finns teknisk information som kan vara användbar när volontärer försöker hjälpa dig att lösa ett problem.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Viktigt: Potentiellt privat eller känslig information redigeras bort som standard. Bortredigerad information kan göra det svårare att lösa ett problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Rapportera ett filterproblem", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "För att undvika att belasta volontärer med dubbletter av rapporter, kontrollera att problemet inte redan har rapporterats.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filterlistor uppdateras dagligen. Se till att ditt problem inte redan har åtgärdats i de senaste filterlistorna.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Kontrollera att problemet kvarstår efter att du har laddat om den krånglande webbsidan.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Hemsidans adress:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Webbsidan…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Välj en post --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Visar annonser eller rester av annonser", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Har överlägg eller andra olägenheter", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Upptäcker uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Har integritetsrelaterade problem", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Fungerar inte när uBlock Origin är aktiverad", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Öppnar oönskade flikar eller fönster", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Märk webbsidan som \"NSFW\" (“Inte lämplig på jobbet”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Bortredigerad", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Oredigerad", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Integritetspolicy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Ändringslogg", + "description": "" + }, + "aboutCode": { + "message": "Källkod (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Bidragsgivare", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Källkod", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Översättningar", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filterlistor", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Externa beroenden (GPLv3-kompatibla):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO:s egna filterlistor finns fritt tillgängligt på följande CDN:er:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Ett slumpmässigt valt CDN kommer att användas när en filterlista behöver uppdateras.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Säkerhetskopiera till fil…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "min-ublock-sakerhetskopia_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Återställ från fil…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Återställ till standardinställningarna…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Alla dina inställningar kommer att skrivas över med data som har säkerhetskopierats {{time}} och uBlock₀ kommer att starta om.\n\nVill du skriva över befintliga inställningar med säkerhetskopierad data?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Data kunde inte läsas eller är ogiltiga", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Alla dina inställningar kommer att tas bort och uBlock₀ kommer att starta om.\n\nÅterställ uBlock₀ till fabriksinställningar?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Nätverksfel: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Lägg till följande webbadress till dina anpassade filterlistor?\n\nTitel: \"{{title}}\"\nWebbadress: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Prenumerera", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "en minut sedan", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} minuter sedan", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "en timme sedan", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} timmar sedan", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "en dag sedan", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} dagar sedan", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Visa kontrollpanelen", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Visa loggaren", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "av", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Sidan blockerad", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin har förhindrat följande sida från att läsas in:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "På grund av följande filter", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "utan parametrar", + "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": "Hittades i:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Gå tillbaka", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Stäng det här fönstret", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Varna mig inte igen om den här sidan", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Inaktivera strikt blockering av {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Temporärt", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Permanent", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Fortsätt", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Exportera till molnlagring", + "description": "tooltip" + }, + "cloudPull": { + "message": "Importera från molnlagring", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Importera från molnlagring och sammanfoga med aktuella inställningar", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Enhetens namn:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Varning! Ändra dessa avancerade inställningar på egen risk.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Skicka", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Verkställ ändringar", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Ångra", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Blockera element i ramar…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Prenumerera på filterlista…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Tillåt tillfälligt stora medieelement", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Visa källkoden…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Ange en genväg", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Växla rullningslås", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Kopiera till urklipp", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Markera allt", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Växla kosmetisk filtrering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Lätta på blockeringsläge", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Använt utrymme: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Klicka för att ladda", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Fel: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Det gick inte att filtrera ordentligt vid webbläsarstart. Ladda om sidan för att säkerställa korrekt filtrering.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/sw/messages.json b/src/_locales/sw/messages.json new file mode 100644 index 0000000..a546d80 --- /dev/null +++ b/src/_locales/sw/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Hatimaye, kizuizi kinachofaa. Nyepesi kwenye CPU na kumbukumbu.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Dashibodi", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Ilani! Una mabadiliko ambazo hazijahifadhika.", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Baki", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Puuza", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Mipangilio", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Chuja orodha", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Vichujio vyangu", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Kanuni zangu", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Orodha-ruhusu", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Njiamikato", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ - Batli", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Kuhusu", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Usaidizi", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ - Kitazama rasilimali", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Mipangilio pevu", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Bofya: lemaza/wezesha uBlock₀ kwenye tovuti hii.\n\nCtrl+bofya: lemaza uBlock₀ kwenye ukurasa huu pekee.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Bofya kulemaza uBlock₀ kwenye tovuti hii.\n\nCtrl+bofya kulemaza uBlock₀ kwenye ukurasa huu pekee.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Bofya kuwezesha uBlock₀ kwenye tovuti hii.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "Maombi yaliyozuiliwa", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "kwenye ukurasa huu", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "tangu usakinishaji", + "description": "English: since install" + }, + "popupOr": { + "message": "au", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Yaliyozuiliwa kwenye ukurasa huu", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Yaliyozuiliwa tangu usakinishaji", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Vikoa vilivyounganishwa", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Fungua dashibodi", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Ingia mtindo wa kufyatua vipengele", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Ingia mtindo wa kuchagua vipengele", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Fungua batli", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Ripoti shida na tovuti hii", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Togoa uzuiaji wa vibukizi kwenye tovuti hii", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Bofya kuzuia vibukizi vyote kwenye tovuti hii", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Bofya kusitisha kuzuia vibukizi vyote kwenye tovuti hii", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Togoa uzuiaji wa vipengele vya midia kubwa kwenye tovuti hii", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Bofya kuzuia vipengele vya midia kubwa kwenye tovuti hii", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Bofya kusitisha kuzuia vipengele vya midia kubwa kwenye tovuti hii", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Togoa uchujaji wa kurembesha kwenye tovuti hii", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Bofya kulemaza uchujaji wa kurembesha kwenye tovuti hii", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Bofya kuwezesha uchujaji wa kurembesha kwenye tovuti hii", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Togoa uzuiaji wa fonti za mbali kwenye tovuti hii", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Bofya kuzuia fonti za mbali kwenye tovuti hii", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Bofya kusitisha kuzuia fonti za mbali kwenye tovuti hii", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Bofya kulemaza JavaScript kwenye tovuti hii", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Bofya kusitisha kulemaza JavaScript kwenye tovuti hii", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Vidirisha ibukizi", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Vipengele vya midia kubwa", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Uchujaji wa kurembesha", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Fonti za mbali", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Zaidi", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Chache", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Kanuni za kila mahali: safuwima hii ni ya kanuni zinazotekelezeka kwenye tovuti zote.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Bofya kufanya mabadiliko yako yadumu.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Bofya kurejelesha mabadiliko yako.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "zote", + "description": "" + }, + "popupImageRulePrompt": { + "message": "picha", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "Mhusika wa tatu", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS ya mhusika wa tatu/picha", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "hati za mstari wa ndani", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Hati za mhusika wa kwanza", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Hati za mhusika wa tatu", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Fremu za mhusika wa tatu", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "vikoa vilivyounganishwa", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} kati ya {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Toleo", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Unda", + "description": "English: Create" + }, + "pickerPick": { + "message": "Teua", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Ondoka", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Hakiki", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Vichujio vya mtandao", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Vichujio vya kurembesha", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Bofya, Ctrl+bofya", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Zuia kipengele...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ficha vishikilia nafasi za vipengele vilivyozuiliwa", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Onyesha idadi ya maombi yaliyozuiliwa kwenye ikoni", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Lemaza vidokezozana", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Tumia menyu muktadha panapofaa", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Rahisi na upofu wa rangi", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Mwonekano", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Mandhari", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Rangi ya lafudhi maalum", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Wezesha auni wa hifadhi ya wingu", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Mimi na mtumiaji mahiri", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Lemaza kuleta-mapema (kuepuka uunganishaji wowote wa maombi yaliyozuiliwa)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Lemaza ukaguzi wa viungo-wavuti", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Zuia WebRTC kuvuja anwani za IP za ndani", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Tabia chaguo-msingi", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Tabia hizi chaguo-msingi zinaweza kubatilishwa kwenye msingi wa kila tovuti", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Lemaza uchujaji wa kurembesha", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Zuia vipengee vya midia vilivyo kubwa kuliko KB {{input}}", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Zua fonti za mbali", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Lemaza JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Zuia ripoti za CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Fichua majina kawaida", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Mahiri", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Vipengele vinawafaa watumiaji maarufu tu.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "mipangilio pevu", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Rejesho ya mwisho:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Chelezo ya mwisho:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "Vichujio vya mtandao {{netFilterCount}} + vichujio vya kurembesha {{cosmeticFilterCount}} kutoka:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} zimetumika kati ya {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Sasisha kiotomatiki orodha ya vichujio", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Sasisha sasa", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Takasa kashe zote", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Changanua na lazimisha vichujio vya kurembesha", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Vichujio vya kurembesha vinasaidia kuficha vipengele kwenye ukurasa tovuti ambavyo vinaweka kuwa vizuizi vya mwonekano, na ambavyo haviwezi zuiliwa kupitia injini ya vichujio vinavyotegemea maombi ya mtandao.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Puuza vichujio vya kurembesha vya kijeneriki", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Vichujio jeneriki vya kurembesha ni vichujio vya kurembesha ambavyo vinafaa kutumika kwenye tovuti zote. Kuwezesha chaguo hii kutaondoa mzigo wa kumbukumbu na CPU unaoongezwa kwenye kurasa tovuti baada ya kuzingatia vichujio jeneriki vya kurembesha.\n\nUnapendekezwa kuwezesha chaguo hii kwenye vifaa vyenye uwezo zaidi.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Simamisha shughuli za mtandao hadi orodha zote zimepakiwa", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Tekeleza mabadiliko", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Vijengwa ndani", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Mtngzo", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Faragha", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Vikoa vya programu hasidi", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Vikasirisho", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "\nVya anuwai", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Mikoa, lugha", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Inayokufaa", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Leta...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "URL moja kila laini. URL batili zitapuuzwa kimya kimya.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Zilizoisha muda.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "tazama yaliyomo", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Sasisho ya mwisho: {{ago}}.\nBofya kulazimisha sasisho.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Inasasisha...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Tatizo la mtandao imezuia rasilimali kusasishwa.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Chujia moja kila laini. Chujio inaweza kuwa kuwa jina pangishi (hostname), au chujio linalotumika na Adblock Plus. Laini zilizo na viambishi awali za ! zitapuuzwa.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Leta na ambatisha", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Hamisha", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "chujio-zangu-tuli-za-ublock_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Tekeleza mabadiliko", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Kanuni za kudumu", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Kanuni za muda", + "description": "header" + }, + "rulesRevert": { + "message": "Rudisha", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Kabidhi", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Hariri", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Hifadhi", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Tupa", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Leta kutoka faili...", + "description": "" + }, + "rulesExport": { + "message": "Hamisha kuenda faili", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "chujio-zangu-badilifu-za-ublock_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Orodha ya kanuni zako badilifu za uchujaji", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Kanuni za sintaksi: tendo la aina ya chanzo fikio (Kumbukumbu kamili).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Panga:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Aina ya kanuni", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Chanzo", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Fikio", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Orodha ya vikubaliwa inaamrisha ni kwenye kurasa zipi uBlock Origin italemazwa. Ingizo moja tu kila laini. Maelekezi batili yatapuuzwa kimyakimya na kufanywa kuwa maoni.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Leta na ambatisha", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Hamisha", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "orodhakubalizi-yangu-ya-ublock_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Tekeleza mabadiliko", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Aina", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Kikoa", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Kichujio", + "description": "English: Filter" + }, + "logAll": { + "message": "Zote", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Bila vichupo", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Kichupo cha sasa", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Pakia upya yaliyomo kwenye kichupo", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Togoa kikaguzi cha DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Togoa paneli ibukizi", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "wiki ya uBlock Origin: Batli", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Futa batli", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Sitisha batli (puuza data yote inayoingia)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Wacha kusitisha batli", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Togoa uchujaji batli", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "chuja yaliyomo kwenye batli", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Machaguo ya uchujaji batli", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Sio", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "imezuiliwa", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "imekubaliwa", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "imebadilishwa", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Mhusika wa kwanza", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Mhusika wa tatu", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Ufafanuzi", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Kichujio", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Orodha ya vichujio", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Kanuni", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Muktadha", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Muktadha shina", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Aina", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Kanuni ya URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Muktadha:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Aina:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Chujio tuli", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} maombi ya mtanda ya {{type}} {{br}} ambayo anwani ya URL inafanana na {{url}} {{br}} ambayo asili ni {{origin}},{{br}}{{importance}} kunayo chujio kighairi inayofanana.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Zuia", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Ruhusu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "aina \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "aina yoyote", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "kutoka \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "kutoka popote", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "isipokuwa wakati", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "hata kama", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Chujio tuli {{filter}} ilipatikana kwenye:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Chujio tuli haikupatikana popote kwenye orodha za machujio zilizowezeshwa", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Maingizo ya batli yasiyokamilisha masharti yote matatu hapo chini yatatupiliwa mbali kiotomatiki.", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Hifadhi maingizo za dakika {{input}} zilizopita", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Hifadhi hadi upakiaji-kurasa {{input}} kwenye kila kichupo", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Hifadhi hadi maingizo {{input}} kwenye kila kichupo", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Tumia laini {{input}} kila ingisho katika mtindo ya safuwima iliyopanuliwa.", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ficha safuwima:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Wakati", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Kichujio/kanuni", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "Muktadha", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Orodha", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Meza", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Ghafi", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Fungua", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Unda ripoti mpya", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Pata ripoti sawia", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Kumbukumbu", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Soma mwongozo kwa uBlock kujua vipengele vyote vya uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Maswali na usaidizi", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Majibu ya maswali na usaidizi wote mwingine yanapatikana kwenye subreddit ya /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Shida na vichujio/tovuti imeharibika", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Ripoti shida za vichujio za tovuti maalum kwenyeuBlockOrigin/uAssetskifuatiliaji cha shida. Itahitaji akaunti ya GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Muhimu: Epuka kutumia vizuizi vingine pamoja na uBlock Origin, maana shida zinaweza kutokea kwenye tovuti kadhaa.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Vidokezo: Hakikisha orodha zako ni zimesasishwa. Kirekodi ndicho kifaa kuu cha kutatua shida za vichujio.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Ripoti hitilafu", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Ripoti shida na uBlock Origin yenyewe kwenyeuBlockOrigin/uBlock-issuekifuatiliaji cha shida.Itahitaji akaunti ya Github.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Maelezo ya utafutatuzi", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Ifuatayo ni taarifa ya kiteknolojia inayoweza kuwa ya manufaa wakati waliojitolea wakijaribu kukusaidia.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Muhimu: Taarifa inayoweza kuwa nyeti hutolewa, kama chaguo-msingi. Taarifa iliyotolewa huenda ikanya utatuzi wa shide iwe ngumu zaidi.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Ripoti shida ya kichujio", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Ili usiwasumbue wasaidizi waliojitolea kwa ripoti rudufu, tafadhali hakikisha kuwa shida haijaripotiwa bado.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Anwani ya tovuti:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Tovuti husika…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Chagua ingizo --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Inaonyesha matangazo au mabakshishi yake", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Ina matandazo au sumbufu zingine", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Inagundua uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Ina shida za faragha", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Huenda vibaya uBlock Origin ikiwezeshwa", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Hufungua vichupo au vidirisha visivyotakikana", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Ipe tovuti lebo ya \"NSFW\" (\"Haifai Kazini\")", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Sera ya faragha", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Yaliyobadilika", + "description": "" + }, + "aboutCode": { + "message": "Msimbo wa chanzo (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Wachangiaji", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Msimbo chanzo", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Tafsiri", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Orodha za vichujio", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Msimbo wa chanzo (inatangamana na GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Orodha za vichujio za uBO hupangishwa kwenye CDN hizi.", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN iliyochaguliwa kwa unasibu hutumika orodha ya kichujio inapohitaji kusasishwa", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Cheleza kwenye faili", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "chelezo-yangu-ya-ublock_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Rejesha kutoka faili...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Weka upya hadi mipangilio chaguo-msingi...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Mipangilio yako yote itaandikwa upya kutumia data iliyochelezwa mnamo {{time}}, na uBlock₀ itaanza upya.\n\nAndika upya mipangilio yote kutumia chelezo ya data?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Data haisomeki au ni batili", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Mipangilio yako yote itaondolewa, na uBlock₀ itaanza upya.\n\nWeka upya uBlock₀ hadi mipangilio ya mwanzo?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Tatizo la mtandao: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Ongeza URL ifuatayo kwenye orodha za uchujaji zinazokufaa?\n\nKicha: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Jisajili", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "dakika moja iliyopita", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "dakika {{value}} zilizopita", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "saa moja iliyopita", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "masaa {{value}} yaliyopita", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "jana", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "siku {{value}} zilizopita", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Onyesha dashibodi", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Onyesha batli", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "zimwa", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin imezuia ukurasa huu kupakia:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Kwa sababu ya kichujio kifuatacho", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "bila parameta", + "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": "Ilipatwa katika:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Rudi nyuma", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Funga dirisha hii", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Lemaza uzuiaji kali kwa {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Kwa muda", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Daima", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Hamisha hadi hifadhi ya wingu", + "description": "tooltip" + }, + "cloudPull": { + "message": "Leta kutoka hifadhi ya wingu", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Leta kutoka hifadhi ya wingu na unganisha na mipangilio ya sasa", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Jina la kifaa hiki:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Ilani! Badilisha mipangilio hii mahiri kwa hiari yako.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Wasilisha", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Tekeleza mabadiliko", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Rudisha", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "baiti", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Zuia kipengee kwenye fremu...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Jisajili kwenye orodha hii…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Ruhusu kwa muda vipengele vya midia kubwa", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Charaza njiamkato", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Togoa kubingiriza kuliofungwa", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Nakili hadi ubao-nakili", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Chagua yote", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Pumzisha mtindo wa kuzuia", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Hifadhi iliyotumika: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Bofya kupakia", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ta/messages.json b/src/_locales/ta/messages.json new file mode 100644 index 0000000..5a13a9d --- /dev/null +++ b/src/_locales/ta/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "இறுதியாக, ஒரு திறமையான விளம்பரத் தடுப்பான். கணினியின் மையச் செயற்பகுதியின் மேலும் நினைவகத்தின் மேலும் இலகுவானது.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ - நிர்வாக மையம்", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "எச்சரிக்கை! உங்களிடம் சேமிக்கப்படாத மாற்றங்கள் உள்ளன", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "இருங்கள்", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "பொருட்படுத்தாதே", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "அமைப்புகள்", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "வடிகட்டி பட்டியல்கள்", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "என் வடிகட்டிகள்", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "என் விதிமுறைகள்", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "அனுமதிப்பட்டியல்", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "குறுக்குவழிகள்", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — பிணையக் கோரிக்கைப் பதிகை", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "எம்மைப் பற்றி", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "ஆதரவு", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock -- உடைமை பார்வையாளர்", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "மேம்பட்ட அமைப்புகள்", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "இந்த தளத்தில் ‍‍‍uBlock₀ ஐ முடக்கவோ/இயக்கவோ: இங்கே சுட்டு.\nCtrl+click: என்ற குறுக்குவிசையின் மூலம் uBlock₀ ஐ இந்தப் பக்கத்தில் மட்டும் முடக்கு.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "இந்த வலைத்தளத்திற்கு uBlock முடக்க, கிளிக் செய்யவும்.\n\nuBlockகை இந்த வலைத்தளத்திற்கு முடக்க Ctrl+click செய்யவும்.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "இந்த வலைத்தளத்திற்கு uBlockகை செயல்படுத்த கிளிக் செய்க.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "தடுக்கப்பட்ட கோரிக்கைகள்", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "இந்த இணையப் பக்கத்தில்", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} அல்லது {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "நிறுவியது முதல்", + "description": "English: since install" + }, + "popupOr": { + "message": "அல்லது", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "இப்பக்கத்தில் தடுக்கப்பட்டது", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "நிறுவியதிலிருந்து தடுக்கப்பட்டது", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "களங்கள் இணைக்கப்பட்டுள்ளன", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "நிர்வாக மையத்தை திறக்க இங்கே சொடுக்கவும்", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "பகுதி தெரிவு முறைமைக்கு நுழை", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "உறுப்புத் தெரிவு முறைமைக்குச் செல்லவும்", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "பிணையக் கோரிக்கைப் பதிவிற்கு செல்", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "இத்தளத்திலொரு சிக்கலைப் புகாரளி", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "இத்தளத்தில் அனைத்து மேல்விரிகளையும் தடுப்பதை மாற்றவும்", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "இந்த தளத்தில் உள்ள அனைத்து பாப்அப்களையும் தடுக்க கிளிக் செய்க", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "இத்தளத்தில் உள்ள எல்லா பாப்அப்களையும் இனி தடுக்காமலிருக்க சொடுக்குக", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "இத்தளத்திற்கான பெரிய ஊடக கூறுகளைத் தடுப்பதை நிலைமாற்று", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "இத்தளத்தில் பெரிய ஊடக கூறுகளைத் தடுக்க சொடுக்குக", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "இத்தளத்தில் பெரிய ஊடக கூறுகளை இனி தடுக்காமலிருக்க சொடுக்குக", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "இத்தளத்திற்கான ஒப்பனை வடிகட்டியை மாற்றவும்", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "இத்தளத்தில் ஒப்பனை வடிகட்டலை முடக்க சொடுக்குக", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "இத்தளத்தில் ஒப்பனை வடிகட்டலை இயக்க சொடுக்குக", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "இத்தளத்திற்கான தொலைநிலை எழுத்துருக்கள் தடையை மாற்றவும்", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "இத்தளத்தில் தொலை எழுத்துருக்களைத் தடுக்க சொடுக்குக", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "இத்தளத்தில் தொலை எழுத்துருக்களை இனி தடுக்காமலிருக்க சொடுக்குக", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "இத்தளத்தில் ஜாவாஸ்கிரிப்டை முடக்க சொடுக்குக", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "இத்தளத்தில் ஜாவாஸ்கிரிப்டை இனி முடக்காமலிருக்க சொடுக்குக", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "பாப்-அப் சாளரங்கள்", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "பெரிய ஊடக கூறுகள்", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "ஒப்பனை வடிகட்டுதல்", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "தொலை எழுத்துருக்கள்", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "ஜாவாஸ்கிரிப்ட்", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "மேலும்", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "குறைந்து", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "உலகளாவிய விதிகள்: இந்நெடுவரிசை அனைத்து தளங்களுக்கும் பொருந்தும் விதிகளுக்கானது.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "அக விதிகள்: இந்நெடுவரிசை தற்போதைய தளத்திற்கு மட்டுமே பொருந்தும் விதிகளுக்கானது.அக விதிகள் உலகளாவிய விதிகளை மீறுகின்றன.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "இங்கே சுட்டி உங்கள் மாற்றங்களை நிரந்தரமாக்கவும்.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "இங்கே சுட்டி உங்கள் மாற்றங்களைப் பழைய நிலைக்குத் திருப்பவும்.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "அனைத்தும்", + "description": "" + }, + "popupImageRulePrompt": { + "message": "படங்கள்", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "மூன்றாம் தரப்பு", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "மூன்றாம் தரப்பு CSS/படங்கள்", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "உள்வரி உரைகள்", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1‍-ஆம் தரப்பு உரைகள்", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "மூன்றாம் தரப்பு உரைகள்", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "மூன்றாம் தரப்பு சட்டங்கள்", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "ஆள்களங்கள் இணைக்கப்பட்டுள்ளது", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "மொத்தம் {{total}} இல் {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "பதிப்பு", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "உருவாக்கு", + "description": "English: Create" + }, + "pickerPick": { + "message": "எடு", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "வெளியேறு", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "முன்னோட்டம்", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "இணைய வடிகட்டிகள்", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "ஒப்பனை வடிகட்டி", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "சொடுக்கு, Ctrl-சொடுக்கு", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "உறுப்பைத் தடு...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "தடுக்கப்பட்ட உறுப்புகளின் பெட்டிகளை மறை", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "தடுக்கப்பட்ட கோரிக்கைகளின் எண்ணிக்கையைப் பாவையில் காட்டவும்", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "உதவிக்குறிப்புக்களை முடக்கு", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "தக்க இடங்களில் சூழல் பட்டியலைக் காட்டு", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "நிறம்-அறியாதோருக்கு ஏதுவாக", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "தோற்றம்", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "நிறவமைவு", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "தனிப்பயன் உரப்பு நிறம்", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "மேகக்கணி சேமிப்பக ஆதரவு இயக்கு", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "நான் ஒரு மேம்பட்ட பயனர் (வாசித்தல் தேவை)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "முன்கூட்டியே பெறுவதை முடக்கு (தடுக்கப்பட்ட பிணைய கோரிக்கைகளுக்கான எந்தவொரு தொடர்பையும் தடுக்க)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "உரலியிணைப்புத் தணிக்கையை முடக்கவும்", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "உங்கள் தனிப்பட்ட IP முகவரியை WebRTC வெளிக்காட்டாதபடி தடுக்க", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "இயல்பான நடத்தை", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "இந்த இயல்புநிலை நடத்தைகள் ஒரு தள அடிப்படையில் மீறப்படலாம்", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "ஒப்பனை வடிகட்டியை தடை செய்", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Elements {உள்ளீடு}} KB ஐ விட பெரிய ஊடக உறுப்புகளைத் தடு", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "தொலை எழுத்துருக்களை தடு", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "ஜாவாஸ்கிரிப்டை முடக்கு", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP அறிக்கைகளைத் தடு", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "நியமன பெயர்களை அவிழ்த்து விடுங்கள்", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "உயரமைவு", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "நுட்பமான பயனர்களுக்கு மட்டுமே ஏற்ற அம்சங்கள்.", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "மேம்பட்ட அமைப்புகள்", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "இறுதியாக மீட்பதற்கு:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "கடைசி மறுபிரதி:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} பிணைய வடிகட்டிகள் + {{cosmeticFilterCount}} ஒப்பனை வடிகட்டிகளிலிருந்து:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "மொத்தம் {{total}} இல் {{used}} பயன்படுத்தப்பட்டது", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "வடிகட்டி பட்டியல்களை தானாக புதுப்பி.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "இப்போது புதுப்பிக்கவும்", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "தற்காலிகச் சேமிப்புகள் அனைத்தையும் அகற்று", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "இலக்கணகூறை விவரி மற்றும் ஒப்பனை வடிகட்டிகளை செயல்படுத்து.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

இந்தத் தேர்வு Adblock Plus-க்கு ஏற்ற “உறுப்பு மறைக்கும்” வடிகட்டிகளைப் படிப்பதையும் பயன்படுத்துவத்தையும் செயல்படுத்தும். இந்த வடிகட்டிகள் அடிப்படையில் மேலோட்டமானவை. இணையப் பக்கத்தின் தோற்றத்தில் தொந்தரவாகக் கருதப்பட்டு, ஆனால் இணையக்கோரிக்கைகளை வடிகட்டும் எஞ்சினின் மூலம் தடுக்கப்பட முடியாத பக்க-உறுப்புகளை, பார்வையிலிருந்து மட்டும் மறைக்கும்

இந்தத் தேர்வு uBlock₀-இன் நினைவக உபயோகத்தை அதிகரிக்கும்.

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "பொதுவான ஒப்பனை வடிகட்டிகளை புறக்கணி", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "பொதுவான ஒப்பனை வடிப்பான்கள் அனைத்து ஒப்பனை வடிப்பான்களாகும், அவை எல்லா வலைத்தளங்களிலும் பொருந்தும். இந்த விருப்பத்தை இயக்குவது பொதுவான ஒப்பனை வடிப்பான்களைக் கையாளுவதன் விளைவாக வலைப்பக்கங்களில் சேர்க்கப்பட்ட நினைவகம் மற்றும் CPU மேல்நிலை ஆகியவற்றை நீக்கும்.குறைந்த சக்திவாய்ந்த சாதனங்களில் இந்த விருப்பத்தை இயக்க பரிந்துரைக்கப்படுகிறது.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "தடைசெய்யப்பட்ட வழங்கிகளின் பட்டியல்", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "மாற்றங்களைச் செயல்படுத்து", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "உள்ளமைக்கப்பட்ட", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "விளம்பரங்கள்", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "தனியுரிமை", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "தீப்பொருள் ஆள்களங்கள்", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "எரிச்சல்கள்", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "பல்நோக்கு வடிகட்டி", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "மாநில பகுதிகள், மொழிகள் வாரியான", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "தனிபயன்", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "இறக்குமதி ...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "ஒரு வரிக்கு ஒரு இணைய முகவரி. ‘!’ எனும் எழுத்தில் தொடங்கும் வரிகள் புறக்கணிக்கப்படும். தவறான முகவரிகளும் அமைதியாகப் புறக்கணிக்கப்படும்.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "காலாவதியாகிவிட்டது", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "உள்ளடக்கத்தைக் காண்க", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "கடைசி புதுப்பிப்பு: {{முன்பு}}.\nபுதுப்பிப்பை கட்டாயப்படுத்த கிளிக் செய்க.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "புதுப்பிக்கிறது...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ஒரு பிணைய பிழை வளத்தைப் புதுப்பிப்பதைத் தடுத்தது.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "ஒரு வரிக்கு ஒரு வடிகட்டி. வடிகட்டி என்பது வெறும் வழங்கிப்பெயராக இருக்கலாம், அல்லது Adblock Plus-க்குப் பொருந்தும் வடிகட்டியாக இருக்கலாம். ‘!’ எனும் எழுத்தில் தொடங்கும் வரிகள் புறக்கணிக்கப்படும்.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "இறக்குமதி செய் மற்றும் இணை", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "ஏற்று", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "மாற்றங்களைச் செயல்படுத்து", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "நிரந்தரமான விதிகள்", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "தற்காலிக விதிகள்", + "description": "header" + }, + "rulesRevert": { + "message": "முன்நிலையாக்கு", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "உறுதியளி", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "தொகு", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "சேமி", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "நிராகரி", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "கோப்பிலிருந்து இறக்குமதி செய் ...", + "description": "" + }, + "rulesExport": { + "message": "கோப்பினுள் ஏற்று", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "உங்களுடைய மாறுநிலை வடிகட்டி விதிப் பட்டியல்கள்.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "விதி தொடரியல்: மூல இலக்கு வகை செயல் ( முழு ஆவணங்கள் ).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "வகைபடுத்து:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "விதி வகை", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "மூல", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "இலக்கு", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "எந்தெந்தப் பக்கங்களில் uBlock₀ முடக்கப்பட வேண்டுமென்பதை அனுமதிப்பட்ட கட்டளைகள் ஆணையிடுகின்றன. வரிக்கு ஒரு இடுகை மட்டுமே. தவறான கட்டளைகள் அமைதியாகப் புறக்கணிக்கப்படும்.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "இறக்குமதி செய்து சேர்", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "ஏற்று", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "மாற்றங்களைச் செயல்படுத்து", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "வகை", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ஆள்களம்", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "உரலி", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "வடிகட்டு", + "description": "English: Filter" + }, + "logAll": { + "message": "அனைத்தும்", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "இ.தளங்களின் பின்னால் நடப்பவை", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "தற்போதைய தாவல்", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "தாவல் உள்ளடக்கத்தை மீண்டும் ஏற்றவும்", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM இன்ஸ்பெக்டரை நிலைமாற்று", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "பாப்அப் பலகையை நிலைமாற்று", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock தோற்றம் விக்கி: லாகர்", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "லாகரை அழி", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "லாகரை இடைநிறுத்து (உள்வரும் எல்லா தரவையும் நிராகரி)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "லாகர் இடைநிறுத்தம் தவிர்", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "லாகர் வடிகட்டலை நிலைமாற்று", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "பதிகை உருப்படிகளை வடிகட்டு", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "லாகர் வடிகட்டுதல் விருப்பங்கள்", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "இல்லை", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "தடுக்கப்பட்டது", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "அனுமதிக்கப்படுகிறது", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "மாற்றப்பட்டது", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "முதல் கட்சி", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "மூன்றாம் தரப்பு", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "விவரங்கள்", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "வடிகட்டி", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "வடிகட்டி பட்டியல்", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "விதி", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "சூழல்", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "வேர் சூழல்", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "கட்சித்தன்மை", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "வகை", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "இணைய முகவரி", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "உரலி விதி", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "சூழல்:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "வகை:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "நிலையான வடிகட்டுதல்", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{origin}} தொடங்கும், {{br}}{{url}}-குப் பொருந்தும் முகவரி கொண்ட{{br}}{{type}} பிணையக் கோரிக்கைகளை {{action}},{{br}}பொருந்தும் விதிவிலக்கு வடிகட்டி {{importance}}.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "முடக்கு", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "அனுமதி", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "\"{{type}}\" வகை", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "எந்த வகையும்", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}”-இல் இருந்து", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "எங்கிருந்தும்", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "இல்லாவிட்டால் மட்டும்", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "இருந்தாலும் கூட‌", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "நிலையான வடிப்பான் {{வடிகட்டி}} இதில் காணப்படுகிறது:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "தற்போது இயக்கப்பட்ட வடிகட்டி பட்டியல்களில் நிலையான வடிப்பானைக் கண்டுபிடிக்க முடியவில்லை", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "கீழே உள்ள மூன்று நிபந்தனைகளையும் பூர்த்தி செய்யாத லாகர் உள்ளீடுகள் தானாக நிராகரிக்கப்படும்:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "கடைசி {{உள்ளீடு} from நிமிடங்களிலிருந்து உள்ளீடுகளைப் பாதுகாக்கவும்", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "ஒரு தாவலுக்கு அதிகபட்சம் {{உள்ளீடு}} பக்க சுமைகளைப் பாதுகாக்கவும்", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "ஒரு தாவலுக்கு அதிகபட்சம் {{உள்ளீடு}} உள்ளீடுகளை பாதுகாக்கவும்", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "செங்குத்தாக விரிவாக்கப்பட்ட பயன்முறையில் ஒரு நுழைவுக்கு {{input}} கோடுகளைப் பயன்படுத்தவும்", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "நெடுவரிசைகளை மறை:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} நேரம்", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} வடிகட்டி/சட்டம்", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} சூழல்", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} கட்சித்தன்மை", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "பட்டியல்", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "பொருளடக்கம்", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "வெற்று", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "மார்க் டவுன்", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "திற", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "புதிய புகாரை உருவாக்கு", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "ஒரேமாதிரியான புகார்களைக் கண்டறி", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "வலைப்பக்கத்தின் முகவரி:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "வலைப்பக்கம்...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "தனியுரிமைசார் சிக்கல்களுள்ளன", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin இயக்கப்பட்டிருந்தால் உடையும்", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "தனியுரிமை கொள்கை", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "மாற்றப்பதிவு", + "description": "" + }, + "aboutCode": { + "message": "மூல நிரல் (பொது மக்கள் உரிமம் பதிப்பு 3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "பங்களிப்பாளர்கள்", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "மூல குறியீடு", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "மொழிபெயர்ப்புகள்", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "பட்டியல்களை வடிகட்டவும்", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "வெளிப்புற சார்புகள் (GPLv3- இணக்கமானது):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO வின் சொந்த வடிகட்டி பட்டியல்கள் பின்வருவனவற்றில் இலவசமாக வழங்கப்படுகின்றன CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "வடிகட்டி பட்டியலைப் புதுப்பிக்க வேண்டியிருக்கும் போது சீரற்ற முறையில் தேர்ந்தெடுக்கப்பட்ட CDN பயன்படுத்தப்படுகிறது", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "கோப்பிற்கு காப்பு பிரதி எடு", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "கோப்பிலிருந்து மீட்டெடு...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "இயல்புநிலை அமைப்புகளுக்கு அகரமாக்கு...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "உங்கள் எல்லா அமைப்புகளும் காப்புப் பதிவைப் {{time}} பயன்படுத்தி மேலெழுதப்படும், பிறகு uBlock மறுதொடக்கம்.\n\nகாப்புப்பட்ட தரவைப் பயன்படுத்தி உள்ள எல்லா அமைப்புகளையும் மேலெழுதவா?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "தரவை வாசிக்க முடியவில்லை அ செல்லாதது", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "உங்கள் எல்லா அமைப்புகளும் அகற்றப்படும், பிறகு uBlock மீண்டும் தொடங்கும்.\n\nuBlockகை தொழிற்சாலை அமைப்புகளை மீட்டமைக்கவ?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "பிணையத்தில் பிழை: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: பின்வரும் உரலியை உங்களுடைய தனிபயன் வடிகட்டியில் சேர்க்கலாமா?\n\nதலைப்பு: \"{{title}}\"\nஉரலி: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "சந்தாதராகு", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ஒரு நிமிடம் முன்பு", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} நிமிடங்கள் முன்பு", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ஒரு மணி நேரம் முன்பு", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} மணிநேரம் முன்பு", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ஒரு நாள் முன்பு", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} நாள் முன்பு", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "நிர்வாக மையத்தைக் காட்டுக", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "பதிவேட்டைக் காண்பி", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "முடக்கத்தில்", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin பின்வரும் பக்கத்தை ஏற்றுவதில் இருந்து தடுத்தது:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "பின்வரும் வடிகட்டியினால்:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "இதனுள் கண்டறியப்பட்டது:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "பின் செல்", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "இச்சாளரத்தை மூடு", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}}-இல் கண்டிப்பான தடையைச்‌ செயலிழக்கச் செய்", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "தற்காலிகமாக", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "நிரந்தரமாக", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "மேகக்கணினி சேமிப்பகத்திற்கு ஏற்று", + "description": "tooltip" + }, + "cloudPull": { + "message": "மேகக்கணினி சேமிப்பகத்திலிருந்து இறக்கு", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "மேகக்கணினி சேமிப்பகத்திலிருந்து இறக்கியபின் நடப்பு அமைப்புகளுடன் இணை", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "இந்தச் சாதனத்தின் பெயர்:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "எச்சரிக்கை! இந்த மேம்பட்ட அமைப்புகளை உங்கள் சொந்த ஆபத்தில் மாற்றவும்.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "சமர்ப்பி", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "மாற்றங்களைச் செயல்படுத்து", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "முன்நிலையாக்கு", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "பைட்டுகள்", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "சட்டத்தில் தொகுதி உறுப்பு ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "வடிகட்டி பட்டியலுக்கு குழுசேர்...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "தற்காலிகமாகப் பெரிய ஒலி‍-ஒளி-படத்தொகுப்புகளின் கூறுகளை அனுமதி", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "குறுக்குவழியைத் தட்டச்சு செய்க", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "ஸ்க்ரோலிங் பூட்டு மாற்று", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "நினைவிக்கு நகலெடு", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "எல்லாம் தேர்ந்தெடு", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "ஒப்பனை வடிகட்டுதலை மறுநிலைமாற்று", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "தடுப்பு பயன்முறையை தளர்த்தவும்", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "பயன்படுத்தப்பட்ட சேமிப்பகத்தின் அளவு: {{value}} பைட்டுகள்", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "ஏற்ற கிளிக் செய்க", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/te/messages.json b/src/_locales/te/messages.json new file mode 100644 index 0000000..21797c8 --- /dev/null +++ b/src/_locales/te/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "మొత్తానికి RAM ఇంకా CPU పై తేలికయిన, ఒక సమర్థవంతమైన నిరోధిని.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — నియంత్రణా వేదిక", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "హెచ్చరిక! మీరు భద్రపరచని మార్పులు ఉన్నాయి", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "ఉండు", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "వదిలేయి", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "ఐచ్చికాలు", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "3వ-పక్ష వడపోతలు", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "నా వడపోతలు", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "నా నియమాలు", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "నమ్మే సైట్లు", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "షార్ట్కట్లు", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — నెట్వర్కు అభ్యర్ధనల చిట్టా", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "మా గురించి", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "సహాయం", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — వనరుల పట్టిక", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "అధునాతన అమరికలు", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "ఈ సైట్లో uBlock₀ను చేతనపరచడానికి లేదా అచేతనపరచడానికి క్లిక్ చేయండి.\n\nకేవలం ఈ పేజిలో uBlock₀ను అచేతనపరచడానికి Ctrl కీ వొత్తి పట్టుకొని క్లిక్ చేయండి.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "ఈ సైట్లో uBlock₀ను అచేతనపరచడానికి క్లిక్ చేయండి.\n\nకేవలం ఈ పేజిలో uBlock₀ను అచేతనపరచడానికి Ctrl కీ వొత్తి పట్టుకొని క్లిక్ చేయండి.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "ఈ సైట్లో uBlock₀ను చేతనపరచడానికి క్లిక్ చేయండి.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "నిలువరించబడిన అభ్యర్ధనలు", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ఈ వెబ్ పేజిలో", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} లేదా {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "సంస్థాపన నుండి", + "description": "English: since install" + }, + "popupOr": { + "message": "లేదా", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "ఈ పేజిలో నిరోధించినవి", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "స్థాపించినప్పటి నుండి నిరోధించినవి", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "అనుసందానమైన డొమైన్లు", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "నియంత్రణా పట్టికను తెరచుటకు క్లిక్ చేయండి", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "భాగాలను ఎంచుకొని తొలగించు ప్రక్ర్యియనారంభించు", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "భాగాలను ఎంచుకొని తొలగించు ప్రక్ర్యియనారంభించు", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "అభ్యర్ధనల చిట్టా తెరువుము", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "ఈ వెబ్‌సైట్‌లో సమస్యను నివేదించండి", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "ఈ వెబ్సైట్ లో అన్ని పాప్అప్స్ ని నిషేధించు/అనుమతించు", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "ఇకపై ఈ సైట్లో అన్ని పపప్లను నిరోధించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "ఇకపై ఈ సైట్లో అన్ని పపప్లను అనుమతించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "ఈ సైట్లో వున్న భారి దృశ్య/శ్రవణ అంశాల నిరోధనా స్థితిని మార్చు", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "ఈ సైట్లో పెద్ద పరిమాణం మీడియా అంశాలను నిరోధించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "ఇకపై ఈ సైట్లో పెద్ద పరిమాణం మీడియా అంశాలను అనుమతించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "ఈ వెబ్ సైట్ లో కాస్మెటిక్ వడపోతల వాడుక స్థితిని మార్చు", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "ఈ వెబ్ సైట్ లో కాస్మెటిక్ ఫిల్టరింగ్ ని అచేతనపరచుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "ఈ వెబ్ సైట్ లో కాస్మెటిక్ ఫిల్టరింగ్ ని చేతపరచుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "ఈ సైట్ లో ఖతుల వాడుకని సక్రియ లేదా నిర్వీర్యపరచు", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "ఈ సైట్లోని రిమోట్ ఫాంట్లను నిరోధించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "ఇకపై ఈ సైట్లో రిమోట్ ఫాంట్లను అనుమతించుటకు క్లిక్ చేయండి", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "ఈ సైటులో జావాస్క్రిప్టును అచేతనం చేయయానికి నొక్కండి", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "ఈ సైట్‌లో జావాస్క్రిప్ట్‌ను ఇకపై నిలిపివేయడానికి క్లిక్ చేయండి", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "పాప్-అప్ విండోలు", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "పెద్ద మీడియా అంశాలు", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "నిశ్చలాత్మక వడపోత", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "రిమోట్ ఫాంట్‌లు", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "జావాస్క్రిప్ట్", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "మరిన్ని", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "తక్కువ", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "సామాన్య నియమాలు: ఈ నిలువరుసలో వున్న నియమాలు అన్ని సైట్లకు వర్తిస్తాయి.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "స్థానిక నియమాలు: ఈ నిలువరుసలో వున్న నియమాలు కేవలం ప్రస్తుత సైట్ కే వర్తిస్తాయి.\nసామాన్య నియమాలపై స్థానిక నియమాలు అతిక్రమిస్తాయి.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "మీ మార్పులను శాశ్వతపరచడానికి క్లిక్ చేయండి.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "మీ మార్పులను తిరిగి పూర్వావస్థకు చేర్చుటకు క్లిక్ చేయండి.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "అన్ని", + "description": "" + }, + "popupImageRulePrompt": { + "message": "చిత్రాలు", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "సైట్-ఏతరుల అంశాలు", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "సైట్-ఏతరుల సిఎస్ఎస్/చిత్రాలు", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "లోబడిన స్క్రిప్ట్లు", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "సైట్ యొక్క స్క్రిప్ట్స్", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "సైట్-ఏతరుల స్క్రిప్ట్లు", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "సైట్-ఏతరుల ఫ్రేమ్స్", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "అనుసంధానించబడిన డొమైన్లు", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} లో {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "సంస్కరణ", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "స్క్రిప్ట్", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "ఫ్రేమ్", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "సృష్టించు", + "description": "English: Create" + }, + "pickerPick": { + "message": "ఎంచుకోనుము", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "నిశ్క్రమించు", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "పరిశీలించు", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "నెట్వర్క్ అభ్యర్దన వడపోతలు", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "కాస్మెటిక్ వడపోతలు", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "క్లిక్, Ctrl+క్లిక్", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "దీన్ని నిరోధించు", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "నిరోధించబడిన అంశాలయోక్క స్థానసంగ్రాహకాలను దాచుము", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "చిహ్నంపై నిరొధించబడిన అభ్యర్దనల సంఖ్య చూపుము", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "టూల్టిప్స్ ను అచేతనపరచు", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "అనువైనచోట్లలో కుడి-క్లిక్ మెనూని ఉపయోగించుము", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "వర్ణ అంధులకనుకూలమైన", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "స్వరూపం", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "థీమ్", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "అనుకూల యాస రంగు", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "క్లౌడ్ లో పొందుపర్చడాన్న్ది అనుమతించు", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "మీరు నిపుణత కలిగిన వినియోగాదారులైతే (అవసరమైన సమాచారం)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "అంశాలను ముందుగానే తీసుకురావడాన్ని నిషేధించు (ఎవైనా అవాంఛనీయ అనుసంధానాలను నివారించడానికి)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "చిరునామాల తానిఖిని దాటవేయు", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTCని మీ స్థానిక IP చిరునామాలను బహిర్గతపరచనివ్వొద్దు", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "సామాన్య ప్రవర్తన", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "ఈ సామాన్య ప్రవర్తనను ఒక్కో సైట్లో ప్రత్యేకంగా మార్చుకోవోచ్చు", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "కాస్మెటిక్ వడపోతను నిర్వీర్యపరచు", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "పరిమాణంలో {{input:number}} కేబీల కన్నా పెద్దవైన అంశాలను నిరోధించు", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "బయటి ఖతులను నిరోధించు", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "జావాస్క్రిప్ట్‌ను ఆపివేయి", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP నివేదికలను నిరోధించు", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "కానానికల్ పేర్లను తెరవండి", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "ఆధునిక", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "సాంకేతిక వినియోగదారులకు మాత్రమే సరిపోయే ఫీచర్లు", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "అధునాతన అమరికలు", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "గత పునరుద్ధారణ:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "గత నకలు:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "ఈ క్రింది మూలాల నుండి వచ్చిన {{netFilterCount}} నెట్వర్క్ వడపోతలు + {{cosmeticFilterCount}} కాస్మెటిక్ వడపోతలు:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} లో వాడుతున్నది {{used}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "వడపోత జాబితాలను స్వయంచాలకంగా నవీకరించుము.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "జాబితా నవీకరించుము", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "తాత్కాలిక నిలువలను త్యజించు", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "పదనిరుపనచేసి కాస్మెటిక్ వడపోతలను ఉపయోగించు.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "

ఈ ఎంపిక Adblock Plus-అనుకూల “అంశాల దాచిపెట్టే” ఫిల్టర్లు ని పదనిరుపనచేసి అమలుపరుస్తుంది. ఈ వఫిల్టర్లు చాలావరకు కాస్మెటిక్ అయివుంటాయి, అవి నెట్వర్క్ అభ్యర్ధన నిరోదన ద్వారా నిరోధించాబడలేని అవాంఛిథ అంశాలను దాచుటకు ఉపకరిస్తాయి.

ఈ ఎంపిక ను ఎంచుకున్నయేడల uBlock₀ యొక్క మెమరీ వాడుక పెరిగే ఆస్కారమున్నది

", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "కాస్మెటిక్ వడపోతలను విస్మరించు", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "

సాధారణ కాస్మెటిక్ ఫిల్టర్లు అన్ని సైట్లపై ఉపయోగించబడుతాయి.

వీటిని uBlock₀ సమర్థవంతంగా ఉపయోగించగలిగినా, కొన్ని భారీ లేదా దీర్ఘకాలికంగా వీక్షిస్తున్న పేజీలలో CPU ఇంకా RAM వాడుకను ఇవి పెంచగలవు.

ఈ ఎంపికను ఎంచుకోవడంవలన, సాధారణ కాస్మెటిక్ ఫిల్టర్లు కొరకు అదనపు CPU ఉపయోగాన్ని నివారిస్తుంది, పైగా uBlock₀ యొక్క RAM వాడుక తగ్గడానికి తోడ్పడుతుంది.

అల్పసామర్ధ్య పరికరాలలో దీన్ని ఎంచుకోవడం శ్రేయస్కరం.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "అన్ని ఫిల్టర్ జాబితాలు లోడ్ అయ్యే వరకు నెట్‌వర్క్ కార్యాచరణను నిలిపివేయండి", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "నిరోధించబడిన చిరునామాల జాబితా", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "మార్పులను అమలుపరచు", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "అంతర్నిర్మితం", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "ప్రకటనలు", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "గోప్యత", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "మాల్వేర్ డొమైన్లు", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "అసౌకర్యాల పట్టిక", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "బహూలార్ధక", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "ప్రాంతాలు, భాషలు", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "సొంత నిర్దేషణ", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "దిగుమతిచేయు...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "ఒక్కో పంక్తిలో ఒక URL. పంక్తిలో మొదట ‘!’ ఉన్నచో ఆ పంక్తి పరిగనించబడదు. చెల్లని URLలు మౌనంగా విస్మరించబడుతాయి.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "పాతబడింది", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "దీన్ని చూపించు", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "గత నవీకరణ: {{ago}}.\nనవీకరించుటకు క్లిక్ చెయ్యండి.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "నవీకరిస్తోంది...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "ఈ చిట్టా అనుసంధాన వైఫల్యం వలన నవికరించబడలేదు.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "ఒక్కో పంక్తిలో ఒక ఫిల్టర్ నమోదు. పేర్కొనబడే ఫిల్టర్, కేవలం హోస్టుపేరు లేదా Adblock Plusకి అనువైన ఫిల్టర్ కావొచ్చు. పంక్తిలో మొదట ‘!’ ఉన్నచో ఆ పంక్తి పరిగణలోకి తీసుకొబడదు.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "అవిశ్వసనీయ మూలాల నుండి ఫిల్టర్‌లను జోడించవద్దు.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "దిగుమతిచేసి పోడిగించుము", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "ఎగుమతి చేయు", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "మార్పులను భద్రపరచు", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "శాశ్వత నియమాలు", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "తాత్కాలిక నియమాలు", + "description": "header" + }, + "rulesRevert": { + "message": "మార్పులను తిరస్కరించు", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "మార్పులను భద్రపరచు", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "చక్కదిడ్డుము", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "భద్రపరచు", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "పారవేయు", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "ఫైల్ నుండి దిగుమతి చేయుము...", + "description": "" + }, + "rulesExport": { + "message": "ఫైల్కు ఎగుమతి చేయుము", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "మీ క్రియాశీలక జల్లెడ నియమాల జాబితా.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "నియమనిర్మాన పద్ధతి: మూలం గమ్యం రకం చర్య (పూర్తి వివరాలు).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "క్రమబద్ధీకరించు", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "రూల్ రకం", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "మూలం", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "గమ్యం", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "uBlock Origin అచేతనబడించిన హోస్టూల జాబితా, ఇది మీరు కూర్చినది,. ఒక్కో పంక్తికి ఒక్కో నమోదు. చెల్లని నమోదులు మౌనంగా విస్మరించబడుతాయి.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "దిగుమతిచేసి పోడిగించుము", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "ఎగుమతి", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "మార్పులను భద్రపరచు", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "రకం", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "డొమైన్", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "జల్లెడ", + "description": "English: Filter" + }, + "logAll": { + "message": "అన్ని", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "తెర వెనుక", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "ప్రస్తుత ట్యాబ్", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "టాబ్ కంటెంట్‌ను మళ్లీ లోడ్ చేయండి", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM ఇన్స్పెక్టర్ను టోగుల్ చేయండి", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "పాపప్ ప్యానెల్‌ను టోగుల్ చేయండి", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock మూలం వికీ: లాగర్", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "లాగర్ క్లియర్", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "లాగర్ను పాజ్ చేయండి (అన్ని ఇన్కమింగ్ డేటాను విస్మరించండి)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "లాగర్ను పాజ్ చేయండి", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "లాగర్ ఫిల్టరింగ్‌ను టోగుల్ చేయండి", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "చిట్టాలోని నమోదులను జల్లెడపరచు", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "లాగర్ ఫిల్టరింగ్ ఎంపికలు", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "కాదు", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "నిరోధించబడినవి", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "అనుమతించబడింది", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "సవరించబడింది", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "మొదటి పార్టీ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "మూడవ పార్టీ", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "వివరాలు", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ఫిల్టర్", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "ఫిల్టర్ జాబితా", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "నియమం", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "సందర్భం", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "రూట్ సందర్భం", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "పార్టీనెస్", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "రకం", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "క్రియాశీలక URL ఫిల్టరింగ్", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "సందర్భం:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "రకం:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "నిశ్చలాత్మక ఫిల్టరింగ్", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{origin}} నుండి మొదలయ్యి, {{br}}{{url}} తో సరిపోలిన url గల {{br}}{{type}} నెట్వర్క్ అభ్యర్ధనలను {{action}}, {{br}}అదీ వడపోతల జాబితాలో {{importance}}.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "తిరస్కరించు", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "అనుమతించు", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "“{{type}}” రకమైన", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "ఏటువంటిదైనా", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}” నుండి", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "ఎక్కడినుండైనా", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "మినహాయింపు వుంటే", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "మినహాయింపు వున్నా", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "నిశ్చలాత్మక ఫిల్టర్ అయిన {{filter}} క్రింది వాటిలో కలదు:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "నిశ్చలాత్మక ఫిల్టర్ అయిన {{filter}} ప్రస్తుతం ఉత్తేజపరిచిన ఫిల్టర్ జాబితాలలో కనుగొనబడలేదు", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "దిగువ మూడు షరతులను నెరవేర్చని లాగర్ ఎంట్రీలు స్వయంచాలకంగా విస్మరించబడతాయి:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "చివరి {{input}} నిమిషాల నుండి ఎంట్రీలను భద్రపరచండి", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "ప్రతి ట్యాబ్‌కు గరిష్టంగా {{input}} పేజీ లోడ్లను భద్రపరచండి", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "ప్రతి ట్యాబ్‌కు గరిష్టంగా {{input}} ఎంట్రీలను భద్రపరచండి", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "నిలువుగా విస్తరించిన మోడ్‌లో ప్రతి ఎంట్రీకి {{input}} పంక్తులను ఉపయోగించండి", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "నిలువు వరుసలను దాచు:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} సమయం", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} ఫిల్టర్ / నియమం", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} e సందర్భం", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}}పార్టీనెస్", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "జాబితా", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "పట్టిక", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "సాదా", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "మార్క్డౌన్", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "తెరవండి", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "కొత్త నివేదికను సృష్టించండి", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "సారూప్య నివేదికలను కనుగొనండి", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "డాక్యుమెంటేషన్", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock ఆరిజిన్ యొక్క అన్ని లక్షణాల గురించి తెలుసుకోవడానికి uBlock/wiki వద్ద డాక్యుమెంటేషన్ చదవండి.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "అనవసరమైన ట్యాబ్‌లు లేదా విండోలను తెరుస్తుంది", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "వెబ్ పేజీని “NSFW”గా లేబుల్ చేయండి (“పని కోసం సురక్షితం కాదు”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "గోప్యతా విధానం", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "మార్పుల సంచిక", + "description": "" + }, + "aboutCode": { + "message": "మూలం (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "ప్రాజెక్ట్కు సహాయ పడిన వారు", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "మూల కోడ్", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "అనువాదాలు", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "జాబితాలను ఫిల్టర్ చేయండి", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "బాహ్య ఆధారపడటం (GPLv3- అనుకూలమైనది):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO యొక్క సొంత ఫిల్టర్ జాబితాలు కింది వాటిలో ఉచితంగా హోస్ట్ చేయబడతాయి CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "ఫిల్టర్ జాబితాను అప్‌డేట్ చేయాల్సిన అవసరం వచ్చినప్పుడు యాదృచ్ఛికంగా ఎంచుకున్న CDN ఉపయోగించబడుతుంది", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "ఫైల్ లో భద్రపరచు", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "ఫైల్ నుండి పునరుద్దరించు...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "సంస్థాపన అమరికలను పునరుద్దరించు...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "మీరు పేర్కొన్న ఐచ్చిక్కాలన్ని {{time}}నకు తీసుకున్న నకలు డేటాతో తిరగారాయబడుతాయి, ఆ పిమ్మట uBlock₀ పునఃప్రారంభమవుతుంది.\n\nమీ ఐచ్చికాలను తిరగరాయుట మీకు సమ్మతమేనా?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "డేటాను చదవడంలో లోపం సంభవించినది(డేటా పాడైవుంది లేదా అందుబాటులో లేదు)", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "ఐచ్చికాలలో మీరు చేసిన మార్పులన్నీ తొలగించనా పిమ్మట uBlock₀ పునఃప్రారంభిన్చాబాడును.\n\nమరి సంస్థాపన ఐచ్చికాలను పునరుద్ధరించాలా?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "అనుసంధాన వైఫల్యం: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: ఈ URLని మీ నిర్దేశిత ఫిల్టర్ పట్టికకు జతపరచాలా?\n\nశీర్షిక: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "సభ్యత్వాన్ని పొందండి", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ఒక నిమిషం క్రితం", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} నిమిషాల క్రితం", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ఒక గంట క్రితం", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} గంటల క్రితం", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ఒక రోజు క్రితం", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} రోజుల క్రితం", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "నియంత్రణా పట్టికను చూపు", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "నెట్వర్క్ అభ్యర్ధనల చిట్టాను చూపు", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "అచేతనం", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "పేజీ బ్లాక్ చేయబడింది", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "ఈ తరువాయి పేజిని uBlock Origin బ్రౌజరులోకి ఎక్కిన్చనివ్వలేదు:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "ఇది ఈ క్రింది వడపోతననుసారించి తీసుకోబడిన చర్య", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "ఈ వడపోత వున్న జాబితా పేరు:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "వెనక్కి వెళ్ళు", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "విండో మూయుము", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}} తో అనుసంధానాన్ని అనుమతించాలా?", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "తాత్కాలికంగా", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "శాశ్వతంగా", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "క్లౌడ్ లో పొందుపరచు", + "description": "tooltip" + }, + "cloudPull": { + "message": "క్లౌడ్ నుండి దిగుమతిపరచు", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "అంతర్జాలంలో భద్రపరచిన ఎంపికలను దిగుమతి చేసి ప్రస్తుత ఎంపికలకు జోడించు", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "ఈ పరికరం పేరు:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "హెచ్చరిక! ఈ అధునాతన అమరికలను జాగ్రత్తతో మార్చండి.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "పంపించు", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "మార్పులను అమలుపరచు", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "మార్పులను తిరస్కరించు", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "బైట్లు", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "ఫ్రేమ్‌లో మూలకాన్ని బ్లాక్ చేయండి ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "ఫిల్టర్ జాబితాకు సభ్యత్వం పొందండి ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "భారి దృశ్య/శ్రవణ అంశాలను తాత్కాలికంగా అనుమతించు", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "షార్ట్కట్ టైప్ చేయండి", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "లాక్ చేసిన స్క్రోలింగ్‌ను టోగుల్ చేయండి", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "క్లిప్‌బోర్డ్‌కు కాపీ చేయండి", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "నిరోధించే మోడ్‌ను రిలాక్స్ చేయండి", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "ఉపయోగించిన నిల్వ: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "కేబీ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "ఏంబీ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "జీబీ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "లోడ్ చేయడానికి క్లిక్ చేయండి", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "ఇది అంతిమంగా వుండాల్సిన నమోదు", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/th/messages.json b/src/_locales/th/messages.json new file mode 100644 index 0000000..e812407 --- /dev/null +++ b/src/_locales/th/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "มาแล้ว! โปรแกรมบล็อกโฆษณาเบาเบา ไม่กิน ซีพียู หรือ แรม", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — หน้าหลัก", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "คำเตือน! คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "อยู่ต่อ", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "ไม่สนใจ", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "การตั้งค่า", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "ตัวกรองจากที่อื่น", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "ตัวกรองของฉัน", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "กฎของฉัน", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "รายการยกเว้น", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Shortcuts", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ประวัติ", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "เกี่ยวกับ", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "ช่วยเหลือ", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Asset viewer", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "การตั้งค่าขั้นสูง", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Click: เปิด/ปิดการทำงานของ uBlock₀ สำหรับเว็บไซต์นี้ \nCtrl+click: ปิดการทำงานของ 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.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "กดเพื่อเปิดใช้่งาน uBlock₀ สำหรับเว็บนี้", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "การร้องขอถูกปฏิเสธ", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "ในหน้านี้", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} or {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "จากวันที่ติดตตั้ง", + "description": "English: since install" + }, + "popupOr": { + "message": "หรือ", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Blocked on this page", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "เปิด dashboard", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "เข้าสู่โหมดโจมตีองค์ประกอบ", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "เข้าสู่โหมดเลือก element", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "เปิดบันทึกการทำงาน", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "เปลี่ยนสถานะการบล็อกป็อบอัพบนเว็บไชต์นี้", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "คลิกเพื่อบล็อกป๊อปอัปทั้งหมดในเว็บไซต์นี้", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "คลิกเพื่อยกเลิกการบล็อกป๊อปอัปทั้งหมดในเว็บไซต์นี้", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "เปลี่ยนสถานะการบล็อกองค์ประกอบ media ขนาดใหญ่บนเว็บไชต์นี้", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "คลิกเพื่อปิดกั้นองค์ประกอบชนิด Media ที่มีขนาดใหญ่ในเว็บไซต์นี้", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "คลิกเพื่อยกเลิกการปิดกั้นองค์ประกอบชนิด Media ที่มีขนาดใหญ่ในเว็บไซต์นี้", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Toggle cosmetic filtering for this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "คลิกเพื่อปิดการใช้ฟิลเตอร์บนเว็บไซต์นี้", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Click to enable cosmetic filtering on this site", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Toggle the blocking of remote fonts for this site", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "คลิกเพื่อบล็อกฟอนต์จากเว็บไซต์นี้", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "คลิกเพื่อยกเลิกการบล็อกป๊อปอัปทั้งหมดในเว็บไซต์นี้", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "กดเพื่อปิดการใช้งาน JavaScript บนเว็บไซต์นี้", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "กดเพื่อยกเลิกการบล็อก JavaScript บนเว็บไซต์นี้", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "หน้าต่าง Pop-up", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "องค์ประกอบ media ขนาดใหญ่", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "ฟิลเตอร์", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "ฟอนต์ที่เว็บไชต์กำหนด", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "เพิ่มเติม", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "แสดงน้อยลง", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "กฏทั่วเว็บ: คอลัมน์นี้มีไว้สำหรับกฏที่ใช้กับทุกเว็บไซต์", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "กฏเว็บเดียว: คอลัมน์นี้มีไว้สําหรับกฏบนเว็บไซต์นี้เท่านั้น\nกฏเว็บเดียวจะถูกใช้งานก่อนกฏครอบคลุม", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "คลิกเพื่อให้ทําให้การเปลี่ยนแปลงถาวร", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "ยกเลิกการเปลี่ยนแปลง", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "ทั้งหมด", + "description": "" + }, + "popupImageRulePrompt": { + "message": "รูปภาพ", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "บุคคลที่ 3", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/รูปภาพ บุคคลที่ 3", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "สคริปท์อินไลน์", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "สคริปภายใน", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "สคริปท์บุคคลที่3", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "กรอบบุคคลที่3", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "โดเมนที่เชื่อมต่อ", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} ใน {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "เวอร์ชัน", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "สคริปต์", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "กรอบ", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "สร้าง", + "description": "English: Create" + }, + "pickerPick": { + "message": "เลือก", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "ออก", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "ตัวอย่าง", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "ฟิลเตอร์เครื่อข่าย", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "ฟิลเตอร์", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "คลิก, Ctrl-คลิก", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "บล็อคองค์ประกอบ", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "ซ่อนตัวยึดตําแหน่งขององค์ประกอบที่ถูกบล็อก", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "แสดงจำนวนคำขอเครือข่ายที่ถูกปฏิเสธบนไอคอน", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "ปิดคำอธิบาย", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "เป็นมิตรกับคนตาบอดสี", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "รูปแบบการแสดงผล", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "รูปแบบการแสดงผล", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "เปิดการเก็บข้อมูลบน Cloud", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "ฉันเป็นผู้ใช้ขั้นสูง (โปรดอ่านเอกสารสำคัญ)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "ปิดกั้นองค์ประกอบชนิด Media ที่มีขนาดใหญ่กว่า {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "ปิดการใช้งาน JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "ขั้นสูง", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "การตั้งค่าขั้นสูง", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Last restore:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "การสำรองข้อมูลครั้งล่าสุด", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "อัปเดตรายการตัวกรองอัตโนมัติ", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "อัปเดตเดี๋ยวนี้", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "ล้างแคชทั้งหมด", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "โฆษณา", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "ความเป็นส่วนตัว", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware domains", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "ภูมิภาค, ภาษา", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "กำหนดเอง", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "นำเข้า...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "หนึ่ง URL ต่อบรรทัด URL ที่ไม่ถูกต้องจะถูกละเว้น", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "ล้าสมัย", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "อัพเดตล่าสุด: {{ago}}", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "กำลังอัปเดต...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "หนึ่งตัวกรองต่อบรรทัด ตัวกรองอาจเป็น hostname หรือตัวกรองที่เข้ากันได้กับ EasyList, บรรทัดที่ขึ้นต้นด้วย ! จะถูกละเว้น\n", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Export…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Permanent rules", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Temporary rules", + "description": "header" + }, + "rulesRevert": { + "message": "คืนกลับ", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "แก้ไข", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "บันทึก", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "ละทิ้ง", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Import from file…", + "description": "" + }, + "rulesExport": { + "message": "Export to file…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "เรียง", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "แหล่งที่มา", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "ส่งออก", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "ประเภท", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Domain", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filter", + "description": "English: Filter" + }, + "logAll": { + "message": "ทั้งหมด", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Current tab", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "หยุดการบันทึก Log (ลบทิ้งทั้งหมด)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Not", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "blocked", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "allowed", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1st-party", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "บุคคลที่ 3", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "รายละเอียด", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "ตัวกรอง", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "รายการตัวกรอง", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "กฎ", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Context", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Type", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Context:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "ประเภท", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "บล็อก", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "อนุญาต", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "type “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "any type", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "from “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "from anywhere", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "ถึงแม้ว่า", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "ซ่อนคอลัมน์", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Time", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filter/rule", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "รายการ", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Table", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "เปิด", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "สร้างรายงานใหม่", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- เลือกรายการ --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "ผู้ร่วมพัฒนา", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "การแปลภาษา", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN ที่สุ่มเลือกจะถูกใช้เมื่อจำเป็นต้องอัปเดตรายการตัวกรอง", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Network error: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: เพิ่ม URL ต่อไปนี้ในรายการตัวกรองแบบกำหนดเองของคุณหรือไม่ ?\n\nชื่อ: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "เมื่อนาทีที่แล้ว", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} นาทีที่แล้ว", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "เมื่อชั่วโมงที่แล้ว", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} ชั่วโมงที่แล้ว", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "เมื่อวันก่อน", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} วันที่แล้ว", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Show Dashboard", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "off", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "เพจถูกบล็อค", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin ป้องกันไม่ให้โหลดหน้าต่อไปนี้:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "เนื่องจากตัวกรองดังต่อไปนี้", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "พบใน:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "ย้อนกลับ", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Close this window", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "ปิดใช้งานการปิดกั้นสำหรับ {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "ชั่วคราว", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "ถาวร", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "ดำเนินการ", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Export to cloud storage", + "description": "tooltip" + }, + "cloudPull": { + "message": "Import from cloud storage", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Import from cloud storage and merge with current settings", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Submit", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Apply changes", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Revert", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "ไบต์", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "สมัครรับรายชื่อตัวกรอง...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "อนุญาตองค์ประกอบชนิด Media ขนาดใหญ่ชั่วคราว", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "ดูต้นฉบับ", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Copy to clipboard", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "หน่วยความจำที่ใช้: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "กิโลไบต์", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "เมกะไบต์", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "คลิกเพื่อโหลด", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/tr/messages.json b/src/_locales/tr/messages.json new file mode 100644 index 0000000..f02c332 --- /dev/null +++ b/src/_locales/tr/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Sonunda, etkili bir engelleyici. İşlemciyi ve belleği yormaz.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Kontrol paneli", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Uyarı! Kaydedilmemiş değişiklikleriniz var", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Kal", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Yok say", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Ayarlar", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Filtre listeleri", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Filtrelerim", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Kurallarım", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Güvenilen siteler", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Kısayollar", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Günlükçü", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Hakkında", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Destek", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — Kaynak görüntüleyici", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Gelişmiş ayarlar", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Tıklama: uBlock₀'i bu site için devre dışı bırak/etkinleştir.\n\nCtrl+tıklama: uBlock₀'i yalnızca bu sayfada devre dışı bırak.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "uBlock₀'i bu sitede devre dışı bırakmak için tıklayın.\n\nuBlock₀'i yalnızca bu sayfada devre dışı bırakmak için Ctrl+tıklayın.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "uBlock₀'i bu sitede etkinleştirmek için tıklayın.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "engellenen istekler", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "bu sayfada", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} (%{{percent}})", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "kurulumdan beri", + "description": "English: since install" + }, + "popupOr": { + "message": "ya da", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Bu sayfada engellenen", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Kurulumdan beri engellenen", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Bağlanılan alan adları", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Kontrol panelini açar", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Öge silme moduna gir", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Öge seçme moduna gir", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Günlükçüyü açar", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Bu web sitesinde bir sorunu bildir", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Bu site için açılır pencere engellemeyi aç/kapat", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Bu sitede açılır pencerelerin tümünü engellemek için tıklayın", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Bu sitede açılır pencerelerin tümünü artık engellememek için tıklayın", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Bu site için büyük medya ögelerini engellemeyi aç/kapat", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Bu sitede büyük medya ögelerini engellemek için tıklayın", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Bu sitede büyük medya ögelerini artık engellememek için tıklayın", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Bu site için kozmetik filtrelemeyi aç/kapat", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Bu sitede, kozmetik filtrelemeyi devre dışı bırakmak için tıklayın", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Bu sitede, kozmetik filtrelemeyi etkinleştirmek için tıklayın", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Bu site için uzak yazı tiplerini engellemeyi aç/kapat", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Bu sitede uzak yazı tiplerini engellemek için tıklayın", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Bu sitede uzak yazı tiplerini artık engellememek için tıklayın", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "JavaScript'i bu sitede devre dışı bırakmak için tıklayın", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Artık bu sitede JavaScript'i devre dışı bırakmamak için tıklayın", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Açılır pencereler", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Büyük medya ögeleri", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Kozmetik filtreleme", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Uzak yazı tipleri", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Daha fazla", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Daha az", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Genel kurallar: bu sütun tüm sitelere uygulanan kurallar içindir.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Değişikliklerinizi kalıcı kılmak için tıklayın.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Değişikliklerinizi geri almak için tıklayın.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "tümü", + "description": "" + }, + "popupImageRulePrompt": { + "message": "resimler", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "3. taraf", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "3. taraf CSS/resimler", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "satır içi betikleri", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "1. taraf betikler", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "3. taraf betikler", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "3. taraf çerçeveler", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "bağlanılan adresler", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{total}} taneden {{count}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Sürüm", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "betik", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "çerçeve", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Oluştur", + "description": "English: Create" + }, + "pickerPick": { + "message": "Seç", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Çık", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Ön İzleme", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Ağ filtreleri", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Kozmetik filtreler", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Tıkla, Ctrl-tıkla", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Ögeyi engelle…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Engellenmiş ögelerin yertutucularını gizle", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Engellenen istek sayısını simge üstünde göster", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "İpuçlarını kapat", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Uygun olduğunda içerik menüsünü kullan", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Renk körü dostu", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Görünüm", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Tema", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Özel vurgu rengi", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Bulut depolama desteğini etkinleştir", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "İleri düzey kullanıcıyım", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Kaynak ön getirimini devre dışı bırak (engellenmiş ağ istekleri için her bağlantıyı engellemek için)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Köprü denetimini devre dışı bırak", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "WebRTC'nin yerel IP adreslerini sızdırmasını engelle", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Varsayılan davranış", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Bu varsayılan davranışlar site bazında geçersiz kılınabilir", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Kozmetik filtreleri devre dışı bırak", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "{{input}} KB'tan büyük medya ögelerini engelle", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Uzak yazı tiplerini engelle", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "JavaScript'i devre dışı bırak", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "CSP raporlarını engelle", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Kuralsal isimleri ortaya çıkar", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Gelişmiş", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Yalnız teknik kullanıcılara uygun ayarlar", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "gelişmiş ayarlar", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Son geri yükleme:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Son yedekleme:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} ağ filtresi + {{cosmeticFilterCount}} kozmetik filtre:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{total}} taneden {{used}} adedi kullanıldı", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Filtre listelerini kendiliğinden güncelle", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Şimdi güncelle", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Tüm önbellekleri temizle", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Kozmetik filtreleri incele ve uygula", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Kozmetik filtreler, bir web sayfasında görsel rahatsızlık yaratan ve ağ isteği-tabanlı filtreleme motorlarınca engellenemeyen ögelerin gizlenmesini sağlar.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Genel kozmetik filtreleri yok say", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Genel kozmetik filtreler tüm web sayfalarına uygulanacak kozmetik filtrelerdir. Bu seçeneğin etkinleştirilmesi, genel kozmetik filtrelerin işlenmesi nedeniyle web sayfalarına eklenen bellek ve işlemci yükünü ortadan kaldırır.\n\nDaha az güçlü aygıtlarda bu seçeneğin etkinleştirilmesi önerilir.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Ağ etkinliğini, tüm filtre listeleri yüklenene kadar askıya al", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Engellenmiş alan adlarının listesi", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Değişiklikleri uygula", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Yerleşik", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Reklamlar", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Gizlilik", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Zararlı alan adları", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Can sıkıcı ögeler", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Çok-amaçlı", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Bölgeler, diller", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Özel", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "İçe aktar…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Her satırda bir URL. Geçersiz URL'ler sessizce yok sayılacaktır.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Güncel değil.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "içeriği görüntüle", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Son güncelleme: {{ago}}.\nGüncelleştirmeye zorlamak için tıklayın.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Güncelleniyor…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Bir ağ hatası kaynağın güncellenmesini engelledi.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Her satırda bir filtre. Bir filtre yalın bir alan adı veya EasyList-uyumlu bir filtre olabilir. ! ile başlayan satırlar yok sayılacaktır.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Güvenilmeyen kaynaklardan filtre eklemeyin.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "İçe aktar ve ekle", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Dışa aktar", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-statik-filtrelerim_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Değişiklikleri uygula", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Kalıcı kurallar", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Geçici kurallar", + "description": "header" + }, + "rulesRevert": { + "message": "Geri al", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "İşle", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Düzenle", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Kaydet", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "İptal et", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Dosyadan al…", + "description": "" + }, + "rulesExport": { + "message": "Dosyaya aktar", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "ublock-dinamik-kurallarım_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Dinamik filtreleme kurallarınızın listesi.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Kural sözdizimi: kaynak hedefi türü işlemi (bütün belgeler).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sıralama:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Kural türü", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Kaynak", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Hedef", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Güvenilen site yönergeleri, uBlock Origin'in devre dışı bırakılması gerektiği web sayfalarını belirler. Her satırda bir girdi.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "İçe aktar ve ekle", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Dışa aktar", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "ublock-güvenilen-sitelerim_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Değişiklikleri uygula", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Tür", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Alan adı", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Filtre", + "description": "English: Filter" + }, + "logAll": { + "message": "Tümü", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Sekmesiz", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Geçerli sekme", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Sekme içeriğini tekrar yükle", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "DOM araştırıcısını aç/kapat", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Açılır paneli aç/kapat", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin viki: Günlükçü", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Günlükçüyü temizle", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Günlükçüyü duraklat (tüm gelen veriyi yok say)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Günlükçüyü devam ettir", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Günlük filtrelemeyi aç/kapat", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "günlükçü içeriğini filtrele", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Günlükçü filtreleme seçenekleri", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Değil", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "olaylı", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "engelli", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "izinli", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "düzenlendi", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "1. taraf", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "3. taraf", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Ayrıntılar", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Filtre", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Filtre listesi", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Kural", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Bağlam", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Kök bağlam", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Taraf", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Tür", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL kuralı", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Bağlam:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Tür:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Statik filtre", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{url}} URL adresi ile eşleşen {{br}}ve kaynağı {{origin}} olan,{{br}}eşleşen bir istisna filtresi {{importance}} {{br}}{{type}} ağ isteklerini {{action}} {{br}}.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Engelle", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "İzin ver", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "“{{type}}” türündeki", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "her türdeki", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "“{{origin}}” adresi", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "her yerden", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "olmasa da", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "olsa da", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Statik filtrenin {{filter}} bulunduğu listeler:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Statik filtre, şu anda etkin olan filtre listelerinde bulunamadı", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Aşağıdaki üç koşulu sağlamayan günlükçü girdileri kendiliğinden yok sayılacaktır:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Son {{input}} dakikadaki girdileri sakla", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Her sekme için en çok {{input}} sayfa yüklemesi sakla", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Her sekme için en çok {{input}} girdi sakla", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Dikey genişletilmiş modda, her girdi için {{input}} satır kullan", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Sütunları gizle:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Tarih", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Filtre/kural", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Bağlam", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Taraf", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Liste", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Tablo", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Yalın", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Aç", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Yeni rapor oluştur", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Benzer raporları bul", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Belgeler", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "uBlock Origin'in özelliklerinin tamamı hakkında bilgi edinmek için uBlock/wiki adresindeki belgeri okuyun.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Sorular ve destek", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Sorulara cevaplar ve diğer türlü yardım desteği /r/uBlockOrigin subreddit'inde sunulmaktadır.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filtre sorunları/web sitesi bozuk", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Belirli web siteleriyle ilgili filtre sorunlarını uBlockOrigin/uAssets sorun izleyicisine bildirin. Github hesabı gerektirir.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Önemli: uBlock Origin'le birlikte, belirli web sitelerinde filtre sorunlarına neden olabileceği için, diğer benzer amaçlı engelleyicileri kullanmaktan kaçının.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "İpuçları: Filtre listenizin güncelliğinden emin olun. Günlükçü filtre bağlantılı sorunları tanılamada temel araçtır.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Hata raporu", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "uBlock Origin'in kendisiyle ilgili sorunları uBlockOrigin/uBlock-issue sorun izleyicisine bildirin. Github hesabı gerektirir.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Hata Giderme Bilgisi", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Aşağıdaki, gönüllüler size bir sorunu çözmede yardım etmeye çalışırken, faydalı olabilecek teknik bilgidir.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Önemli: Olası gizli ve hassas bilgiler öntanımlı olarak kısaltılır. Kısaltılmış bilgiler bir sorunu çözmeyi zorlaştırabilir.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Bir filtre sorunu bildirin", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Gönüllülere aynı raporlarla sıkıntı vermemek için, lütfen sorunun daha önce bildirilmediğinden emin olun.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Filtre listeleri günlük olarak güncellenir. Sorununuzun en son filtre listelerinde zaten ele alınıp alınmadığından emin olun.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Sorunlu web sayfasını yeniden yükleyerek sorunun devam ettiğini doğrulayın.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Web sayfasının adresi:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Web sayfası…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Bir girdi seçin --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Reklam veya reklam artıkları gösteriyor", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Kaplamaları veya diğer sıkıntıları var", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "uBlock Origin’i algılıyor", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Gizlilikle ilgili sorunları var", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "uBlock Origin etkinken bozuluyor", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "İstenmeyen sekme veya pencereler açıyor", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Web sayfasını uygunsuz (“NSFW”) olarak etiketle (“Not Safe For Work”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Kısalt", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Kısaltma", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Gizlilik ilkesi", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Değişiklik günlüğü", + "description": "" + }, + "aboutCode": { + "message": "Kaynak kodu (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Katkıda bulunanlar", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Kaynak kodu", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Çeviriler", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filtre listeleri", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Dış bağımlılıklar (GPLv3-uyumlu):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO'nun kendi filtre listeleri ücretsiz olarak şu CDN'lerde barındırılır:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Bir filtre listesinin güncellenmesi gerektiğinde rastgele seçilen bir CDN kullanılır", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Dosyaya yedekle…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-yedeğim_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Dosyadan geri yükle…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Varsayılan ayarlara sıfırla…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Tüm ayarlarınız {{time}} tarihinde yedeklenmiş veriler kullanarak değiştirilecek ve uBlock₀ yeniden başlayacak. \n\nYedeklenmiş verileriniz kullanılarak var olan tüm ayarlarınız değiştirilsin mi?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Veri okunamadı veya geçersiz", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Tüm ayarlarınızı silinecek, ve uBlock₀ yeniden başlayacak.\n\nuBlock₀ fabrika ayarlarına sıfırlansın mı?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Ağ hatası: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Bu URL, özel filtre listenize eklensin mi?\n\nBaşlık: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Abone ol", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "bir dakika önce", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} dakika önce", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "bir saat önce", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} saat önce", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "bir gün önce", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} gün önce", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Kontrol Panelini Göster", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Günlükçüyü Göster", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "kapalı", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Sayfa engellendi", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin aşağıdaki sayfanın yüklenmesini engelledi:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Bu filtre nedeniyle:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "değişkensiz", + "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": "Bulunduğu liste:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Geri git", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Bu pencereyi kapat", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Bu site için beni bir daha uyarma", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "{{hostname}} için katı engellemeyi devre dışı bırak", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Geçici olarak", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Kalıcı olarak", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Devam et", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Bulut depolamaya aktar", + "description": "tooltip" + }, + "cloudPull": { + "message": "Bulut depolamadan içe aktar", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Bulut depolamadan içe aktar ve şu anki ayarlarla birleştir", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Bu aygıtın adı:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Uyarı! Bu gelişmiş ayarları değiştirmenin sorumluluğu size aittir.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Gönder", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Değişiklikleri uygula", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Geri al", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Çerçevedeki ögeyi engelle…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Filtre listesine abone ol…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Geçici olarak büyük medya ögelerine izin ver", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Kaynağı görüntüle…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Bir kısayol girin", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Kilitli kaydırmayı aç/kapat", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Panoya kopyala", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Tümünü seç", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Kozmetik filtrelemeyi aç/kapat", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Engelleme modunu gevşet", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Kullanılan depolama: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Yüklemek için tıkla", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Hata sayısı: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Tarayıcı açılışında düzgün filtreleme yapılamadı.\nDüzgün filtreleme için sayfayı yenileyin.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Bu girdi en sonda olmalıdır", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json new file mode 100644 index 0000000..6145210 --- /dev/null +++ b/src/_locales/uk/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Ефективний блокувальник реклами таки з’явився. Не навантажує процесор та пам'ять.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "µBlock — Панель керування", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "Увага! Є незбережені зміни", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Залишитись", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ігнорувати", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Налаштування", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Списки фільтрів", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Власні фільтри", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Мої правила", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Білий список", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Комбінації клавіш", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Журнал мережевих запитів", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Про програму", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Підтримка", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ – Переглядач ресурсів", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Розширені налаштування", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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\nНатисніть з Ctrl для вимкнення uBlock₀ лише для цієї сторінки.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Натисніть, щоб увімкнути uBlock₀ для цього сайту.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "запитів заблоковано", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "на цій сторінці", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} або {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "від моменту встановлення", + "description": "English: since install" + }, + "popupOr": { + "message": "або", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Заблоковано на цій сторінці", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Заблоковано з моменту встановлення", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Доменів під'єднано", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Перейти до панелі керування", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Перейти в режим блокування елементів", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Перейти у режим вибору елементів", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Перейти до журналу запитів", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Повідомити про помилку на цьому вебсайті", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Увімкнути блокування всіх виринаючих вікон цього сайту", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Натисніть, щоб заблокувати всі спливні вікна на цьому сайті", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Натисніть для скасування блокування всіх спливних вікон на цьому сайті", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Увімк/Вимк блокування великих медіа елементів на цьому сайті", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Натисніть для блокування великих медіаелементів на цьому сайті", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Натисніть для скасування блокування великих медіаелементів на цьому сайті", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Переключити косметичний фільтр для цього сайту", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Натисніть для вимкнення косметичних фільтрів на цьому сайті", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Натисніть для увімкнення косметичних фільтрів на цьому сайті", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Перемкнути блокування віддалених шрифтів для цього сайту", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Натисніть для блокування віддалених шрифтів на цьому сайті", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Натисніть для скасування блокування віддалених шрифтів на цьому сайті", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Натисніть, щоб повністю вимкнути JavaScript на цьому сайті", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Натисніть, щоб скасувати вимкнення JavaScript на цьому сайті", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Спливні вікна", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Великі медіаелементи", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Косметичне фільтрування", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Віддалені шрифти", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavasScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Більше", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Менше", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Глобальні правила: цей стовпчик для правил, що застосовуються для всіх сайтів.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "Локальні правила: цей стовпчик для правил, що застосовуються лише для цього сайту.\nЛокальні правила замінюють глобальні.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Натисніть, щоб зробити ваші зміни постійними.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Натисніть, щоб відкинути ваші зміни.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "всі", + "description": "" + }, + "popupImageRulePrompt": { + "message": "зображення", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "сторонні", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "Сторонні CSS/зображення", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "вбудовані сценарії", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "Основні скрипти", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "Сторонні скрипти", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "Сторонні фрейми", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "доменів під’єднано", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} з {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Версія", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "скрипт", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "рамка", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Створити", + "description": "English: Create" + }, + "pickerPick": { + "message": "Вибрати", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Вийти", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Попередній перегляд", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Мережні фільтри", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Косметичні фільтри", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Клік, Ctrl-клік", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Заблокувати елемент", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ховати заповнювачі заблокованих елементів", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Показувати кількість заблокованих запитів на піктограмі", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Вимкнути підказки", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Використовувати контекстне меню там, де це можливо", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Підтримка дальтонізму", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Вигляд", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Тема", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Акцент кольору користувача", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Увімкнути підтримку хмарного сховища", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Я досвідчений користувач", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Вимкнути передзавантаження (щоб унеможливити будь-які з’єднання для заблокованих мережевих запитів)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Вимкнути перевірку гіперпосилань", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Унеможливити витік локальної IP-адреси через WebRTC", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Типові налаштування", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Усталені налаштування можуть бути перевизначеними для кожного сайту окремо", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Вимкнути косметичні фільтри", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Блокувати медіа елементи розміром від {{input:number}} кБ", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Блокувати сторонні шрифти", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Вимкнути JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Блокувати CSP-звіти", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Показати CNAME назви", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Додатково", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Функції, що потрібні лише технічним користувачам", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "розширені налаштування", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Востаннє відновлено:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Остання резервна копія:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} мережевих фільтрів + {{cosmeticFilterCount}} косметичних фільтрів з:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "використовується {{used}} з {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Автоматично оновити списки фільтрів.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Оновити зараз", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Очистити всі кеші", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Розбір та застосування фільтрів приховування елементів Adblock+.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Косметичні фільтри служать для приховування елементів на вебсторінці, які вважаються візуально неприємними та не можуть бути заблоковані мережевими механізмами фільтрації на основі запитів.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ігнорувати загальні косметичні фільтри", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Загальні косметичні фільтри — це ті косметичні фільтри, які призначені для застосування на всіх вебсайтах. Увімкнення цієї опції усуне навантаження на пам'ять і процесор, що додається до вебсторінок у результаті обробки загальних косметичних фільтрів.\n\nРадимо вмикати цю опцію на менш потужних пристроях.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Призупинити мережеві операції доки всі списки фільтрів не завантажаться", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Перелік заблокованих хостів", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Застосувати зміни", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Вбудовані", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Реклама", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Конфіденційність", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Домени шкідливих програм", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Надокучливості", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Універсальні", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Регіони, мови", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Користувацькі", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Імпорт...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Одне посилання на рядок. Невірні посилання будуть проігноровані без попередження.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Застарілий.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "переглянути вміст", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Останнє оновлення: {{ago}}\nКлацніть для примусового оновлення.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Оновлюється...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Оновлення не вдалося, у зв'язку з помилкою мережі.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Один фільтр на рядок. Фільтром може бути адреса сайту або фільтр у Adblock Plus-сумісному записі. Рядки, що починаються з ! будуть проігноровані.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Не додавати фільтри з невідомих джерел.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Імпортувати та додати", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Експортувати", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "ublock-custom-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Застосувати зміни", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Постійні правила", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Тимчасові правила", + "description": "header" + }, + "rulesRevert": { + "message": "Скасувати зміни", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Затвердити", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Редагувати", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Зберегти", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Відкинути", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Імпорт з файлу…", + "description": "" + }, + "rulesExport": { + "message": "Експорт до файлу...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Список правил динамічного фільтрування.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Синтаксис правил: джерело призначення тип дія (повна документація).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Сортування:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Тип правила", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Джерело", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Призначення", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Ваш список адрес сайтів, для яких µBlock буде неактивним. Додайте по одному запису на рядок. Невірні адреси будуть проігноровані без попереджень та закоментовані.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Імпортувати та додати", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Експортувати", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Застосувати зміни", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Тип", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Домен", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "Адреса", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Фільтр", + "description": "English: Filter" + }, + "logAll": { + "message": "Все", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "За лаштунками", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Поточна вкладка", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Перезавантажити вміст вкладки", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Перемкнути інспектор DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Перемкнути панель, що спливає", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: журнал", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Очистити журнал", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Поставити журнал на паузу (ігнорувати всі вхідні дані)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Увімкнути журнал", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Перемкнути фільтрування журналу", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "фільтр журналу записів", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Опції фільтрування журналу", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Ні", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "насичений", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "заблокований", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "дозволений", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "модифікований", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "основний", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "сторонній", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Деталі", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Фільтр", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Список фільтрів", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Правило", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Контекст", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Кореневий контекст", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Членство", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Тип", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL-адреса", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL правило", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Контекст:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Тип:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Статичний фільтр", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} мережеві запити {{type}}, {{br}}посилання яких збігаються з {{url}} {{br}}та які {{origin}},{{br}}{{importance}} є відповідний фільтр-виняток.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Блокувати", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Дозволити", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "типу „{{type}}“", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "будь-якого типу", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "походять із „{{origin}}“", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "мають будь-яке походження", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "крім випадків, коли", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "навіть якщо", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Статичний фільтр {{filter}} знайден у:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Статичний фільтр не знайдений в жодному списку увімкнених у цей момент фільтрів", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Записи журналу, що не відповідають всім трьом нижченаведеним умовам, будуть автоматично відхилені:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Зберегти записи за останні {{input}} хв", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Зберегти щонайбільше {{input}} завантажень сторінки у вкладці", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Зберегти щонайбільше {{input}} елементів у вкладці", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Використовувати {{input}} рядків на елемент у вертикальному режимі", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Приховати стовпці:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} час", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} фільтр/правило", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} контекст", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} членство", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Список", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Таблиця", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Простий", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Відкрити", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Створити новий звіт", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Знайти подібні звіти", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Документація", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Прочитайте документацію на uBlock/вікі, щоб дізнатися про всі функції uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Запитання та підтримка", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Відповіді на запитання та інші види підтримки довідки надаються на /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Проблеми з фільтрами/сайт не працює", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Повідомити про проблеми фільтра на певних вебсайтах до відстежувача проблем uBlockOrigin/uAssets. Потрібен обліковий запис GitHub.", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Важливо: Уникайте використання інших блокувальників аналогічного призначення разом із uBlock Origin, оскільки це може спричинити проблеми з фільтрами на певних вебсайтах.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Поради: Переконайтеся, що списки фільтрів оновлено. Журнал — основний засіб визначення проблем пов'язаних з фільтром.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Звіт про ваду", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Повідомити про проблеми самого uBlock Origin відстежувач проблем uBlockOrigin/uBlock-issue. Потрібен обліковий запис GitHub.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Інформація про усунення несправностей", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Внизу наведено технічні дані, які можуть бути корисними, коли волонтери намагатимуться допомогти вам розв'язати проблему.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Важливо: Потенційно приватні або конфіденційні дані типово редаговані. Редаговані дані можуть ускладнити розв'язання проблеми.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Повідомити про ваду фільтра", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Щоб не обтяжувати волонтерів повторюваними звітами, переконайтеся, що про проблему ще не повідомлялося.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Списки фільтрів оновлюються щоденно. Переконайтесь, що ваша проблема все ще не виправлена в найсвіжішому списку фільтрів", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Переконайтесь, що проблема все ще присутня після перезавантаження проблемної сторінки", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Адреса вебсторінки:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Вебсторінка...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Указати проблему --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "З'являється реклама або залишки оголошень", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Накладання або інші прикрощі", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Виявляє uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Пов'язані з приватністю проблеми", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Щось не працює, якщо увімкнено uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Відкриває небажані вкладки або вікна", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Позначити цю сторінку «NSFW» («Небезпечно для роботи»)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Редагувати", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Скасувати редагування", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Політика конфіденційності", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Журнал змін", + "description": "" + }, + "aboutCode": { + "message": "Джерельний код (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Учасники", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Вихідний код", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Переклади", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Списки фільтрів", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Зовнішні залежності (сумісні з GPLv3):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "Списки власних фільтрів uBO вільно розміщуються на таких CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "Випадково вибраний CDN застосовуватиметься, коли список фільтрів потрібно оновити", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Зберегти резервну копію у файл...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Відновити з файлу…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Відновити початкові налаштування...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Всі ваші налаштування будуть перезаписані з резервної копії від {{time}} та µBlock буде перезапущено.\n\nПерезаписати всі налаштування використовуючи резервну копію?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Дані помилкові або не можуть бути прочитані", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Ваші налаштування буде видалено та µBlock буде перезапущено.\n\nПовернути µBlock до початкових налаштувань?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Помилка мережі: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "µBlock: Додати це посилання до списку ваших фільтрів?\n\nНазва: \"{{title}}\"\nПосилання: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Підписатись", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "хвилину тому", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} хвилин(и) тому", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "годину тому", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} годин(и) тому", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "день тому", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} дні(в) тому", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Показати панель керування", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Показати журнал мережевих запитів", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "Відключений", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Сторінка заблокована", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock запобіг завантаженню наступної сторінки:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Через наступний фільтр", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "Знайдено в:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Повернутись назад", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Зачинити це вікно", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Не нагадуйте мені про цей сайт", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Вимкнути повне блокування для {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Тимчасово", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Завжди", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Продовжити", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Експортувати до хмарного сховища", + "description": "tooltip" + }, + "cloudPull": { + "message": "Імпортувати із хмарного сховища", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Імпортувати з хмари та об'єднати з чинними налаштуваннями", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Назва цього пристрою:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Увага! Змінюйте ці розширені налаштування на власний ризик.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Надіслати", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Застосувати зміни", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Скасувати зміни", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "байтів", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Заблокувати елемент у фреймі", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Підписатися на список фільтрів...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Тимчасово дозволити великі медіа елементи", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Перегляд джерела...", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Уведіть комбінацію", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Перемкнути замкнуту прокрутку", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Скопіювати до буферу обміну", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Вибрати все", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Увімкнути/вимкнути косметичні фільтри", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Послаблений режим блокування", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Використано: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "КБ", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "МБ", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "ГБ", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Натисніть, щоб завантажити", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Помилки: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Неможливо правильно фільтрувати під час запуску браузера.\nПерезапустіть сторінку для гарантії правильного фільтрування", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Цей запис має бути останнім", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/ur/messages.json b/src/_locales/ur/messages.json new file mode 100644 index 0000000..1b62e56 --- /dev/null +++ b/src/_locales/ur/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "آخر کار، ایک مؤثر اشتہار کو روکنے والا، یہ کم cpu اور میموری لیتا ہے.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — کنٹرول پینل", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "خبردار! آپ نے محفوظ نہیں کیا", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "Stay here", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Ignore", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "ترتیبات", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "فلٹر کی فہرستیں", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "میرے فلٹر", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "میرے اصول", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "اِن کی اجازت ہے", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "شارٹ کٹ", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — ریکارڈ", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "متعلق", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Support", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — اثاثے", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "اعلیٰ ترتیبات", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "کلک: uBlock اس سائٹ کے لیے فعال/ غیرفعال کریں.\n\nکنٹرول + کلک: uBlock صرف اس صفحہ پر غیرفعال کریں.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "کلک کر کے uBlock اس سائٹ کے لیے غیرفعال کریں.\n\nکنٹرول + کلک: uBlock صرف اس صفحے کے لیے غیرفعال کریں.", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "کلک کر کے uBlock اس سائٹ کے لیے فعال کریں.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "درخواستیں بلاک ہیں", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "اس صفحے پر", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} یا {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "تنصیب سے لے کر اب تک", + "description": "English: since install" + }, + "popupOr": { + "message": "یا", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "اس صفحے سےختم کر دیا گیا ہے", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Blocked since install", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Domains connected", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "کنٹرول پینل کھولیں", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "عناصر تباہ کرنے کا موڈ", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "عناصر چننے کا موڈ", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "ریکارڈ کار کھولیں", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Report an issue on this website", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "اس سائٹ پر آنے والے تمام پاپ اپ کو روکیں یا آنے دیں", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "کلِک کر کے اس سائٹ کے تمام پاپ اپ کو روک کریں", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "کلِک کر کے اس سائٹ کے تمام پاپ اپ کی اجازت دیں", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "اس سائٹ پر بڑے میڈیا والی اشیاء کو روک دیں", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "کلک کر کے اس سائٹ پر بڑے میڈیا والی اشیاء کو روک دیں", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "کلک کر کے اس سائٹ پر بڑے میڈیا والی اشیاء کی اجازت د‌یں", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "اس سائٹ کے لئے کاسمیٹک فلٹر کو فعال یا غیر فعال کریں", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "اس سائٹ کے لئے کاسمیٹک فلٹر کو غیر فعال کریں", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "اس سائٹ کے لئے کاسمیٹک فلٹر کو فعال کریں", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "اس سائٹ پر آنے والے تمام remote فانٹ کو روکیں یا آنے دیں", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "کلِک کر کے اس سائٹ کے تمام remote فانٹ کو روک کریں", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "کلِک کر کے اس سائٹ کے تمام remote فانٹ کی اجازت دیں", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "کلک کر کے اس سائٹ پہ جاواسِکرپٹ غیرفعال کریں", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "کلک کر کے اس سائٹ پر جاوا سکرپٹ چلنے دیں", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Pop-up windows", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Large media elements", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Cosmetic filtering", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Remote fonts", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "مزید", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "کم", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "گلوبل اصول: اس کالم میں وہ اصول ہیں جو تمام ویب سائٹوں پر لاگو ہوں گے.", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "مقامی اصول: اس کالم میں وہ اصول ہیں جو صرف موجودہ سائٹ پر لاگو ہوں گے.\nمقامی اصول کو گلوبل اصولوں پر ترجیح دی جائے گی.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "اپنی تبدیلیوں کو مستقل کرنے کے لیے کلک کریں.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "اپنی تبدیلیوں کو کالعدم کرنے کے لیے کلک کریں.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "تمام", + "description": "" + }, + "popupImageRulePrompt": { + "message": "تصاویر", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "فریق ثالث", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "فریق ثالث کی Css/ تصاویر", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "ان لائن سکرپٹس", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "فریق اول کی سکرپٹس", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "فریق ثالث کی سکرپٹس", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "فریق ثالث کے فریم", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "domains connected", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} out of {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Version", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "script", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "frame", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "بنائیں", + "description": "English: Create" + }, + "pickerPick": { + "message": "چُنیں", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "بند کریں", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "دیکھیں", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "نیٹورک کے فلٹر", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "کاسمیٹک فلٹر", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "کلک، کنٹرول + کلک", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "عنصر کو روکیں", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "روکے ہوئے عناصر جس جگہ پے تھے اس جگہ کو غائب کر دیں", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "آئکن پر روکی ہوئی درخواستوں کی تعداد دکھائیں", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "مفید معلومات والے پیغامات مت دکھائیں", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Make use of context menu where appropriate", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Color-blind friendly", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Appearance", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Theme", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Custom accent color", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Enable cloud storage support", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "I am an advanced user", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Disable pre-fetching (to prevent any connection for blocked network requests)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Disable hyperlink auditing", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Prevent WebRTC from leaking local IP addresses", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Default behavior", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "These default behaviors can be overridden on a per-site basis", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Disable cosmetic filtering", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Block media elements larger than {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Block remote fonts", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "جاوا سکرپٹ بند کریں", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Block CSP reports", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Uncloak canonical names", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Advanced", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Features suitable only for technical users", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "اعلیٰ ترتیبات", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "آخری ریسٹور:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "آخری بیک اپ:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} used out of {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Auto-update filter lists", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "ابھی اپڈیٹ کریں", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Purge all caches", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Parse and enforce cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Ignore generic cosmetic filters", + "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.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Suspend network activity until all filter lists are loaded", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Lists of blocked hosts", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Built-in", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "اشتہارات", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "رازداری", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Malware protection, security", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Annoyances", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Multipurpose", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "علاقے، زبانیں", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "مخصوص", + "description": "Filter lists section name" + }, + "3pImport": { + "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.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Out of date.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "view content", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Last update: {{ago}}.\nClick to force an update.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "اپڈیٹ ہو رہا ہے", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "A network error prevented the resource from being updated.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "One filter per line. A filter can be a plain hostname, or an EasyList-compatible filter. Lines prefixed with ! will be ignored.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Do not add filters from untrusted sources.", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Import and append…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "برآمد کریں", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Apply changes", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "مستقل اصول", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "عارضی اصول", + "description": "header" + }, + "rulesRevert": { + "message": "Revert", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Commit", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "تدوین کریں", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "محفوظ کریں", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "مسترد کریں", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "فائل سے درآمد...", + "description": "" + }, + "rulesExport": { + "message": "فائل میں برآمد کریں", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "List of your dynamic filtering rules.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Rule syntax: source destination type action (full documentation).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sort:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Rule type", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Source", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Destination", + "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.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Import and append…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "برآمد کریں", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "تبدیلیاں لاگو کریں", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "نوعیت", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "ڈومین", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "پته", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "فلٹر", + "description": "English: Filter" + }, + "logAll": { + "message": "تمام", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "موجودہ ٹیب", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Reload the tab content", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Toggle the DOM inspector", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Toggle the popup panel", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: The logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Clear logger", + "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)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Unpause logger", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Toggle logger filtering", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "filter logger content", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Logger filtering options", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "نہیں", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "روکے ہوئے", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "اجازت والے", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "modified", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "فریق اول", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "فریق ثالث", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "تفصیلات", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "فلٹر", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "فلٹر کی فہرست", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "اصول", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "سیاق", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Root context", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Partyness", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "نوعیت", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "پته", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL rule", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "سیاق:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "نوعیت:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Static filter", + "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.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "روکیں", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "اجازت دیں", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "نوعیت \"{{type}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "کسی بھی نوعیت", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "\"{{origin}}\" سے", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "کہیں سے بھی", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "except when", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "even if", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Static filter {{filter}} found in:", + "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", + "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:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Preserve entries from the last {{input}} minutes", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Preserve at most {{input}} page loads per tab", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Preserve at most {{input}} entries per tab", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Use {{input}} lines per entry in vertically expanded mode", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "چھپائیں کالم:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} وقت", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} فلٹر / اصول", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Context", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "فہرست", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "ٹیبل", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Plain", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Open", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Create new report", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Find similar reports", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Documentation", + "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.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Questions and support", + "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.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Filter issues/website is broken", + "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.", + "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.", + "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.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Bug report", + "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.", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Troubleshooting Information", + "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.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Important: Potentially private or sensitive information is redacted by default. Redacted information may make it more difficult to solve a problem.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Report a filter issue", + "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.", + "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.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Verify that the issue still exists after reloading the problematic webpage.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Address of the web page:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "The web page…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- Pick an entry --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Shows ads or ad leftovers", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Has overlays or other nuisances", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Detects uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Has privacy-related issues", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Malfunctions when uBlock Origin is enabled", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Opens unwanted tabs or windows", + "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”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Redact", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Unredact", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Privacy policy", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Changelog", + "description": "" + }, + "aboutCode": { + "message": "Source code (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Contributors", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Source code", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Translations", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Filter lists", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "External dependencies (GPLv3-compatible):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO's own filter lists are freely hosted on the following CDNs:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "A randomly picked CDN is used when a filter list needs to be updated.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Back up to file…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Restore from file…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Reset to default settings…", + "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?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "The data could not be read or is invalid", + "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?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "نیٹورک مسئلہ: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "Add the following URL to your custom filter lists?\n\nTitle: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Subscribe", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "ایک منٹ پہلے", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} منٹ پہلے", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "ایک گھنٹہ پہلے", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} گھنٹے پہلے", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "ایک دن پہلے", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} دن پہلے", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "کنٹرول پینل دکھائیں", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Show Logger", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "بند", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Page blocked", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin has prevented the following page from loading:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Because of the following filter:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "without parameters", + "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": "Found in:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "واپس جائیں", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "اس ونڈو کو بند کریں", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Don't warn me again about this site", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Disable strict blocking for {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "عارضی طور پر", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "مستقل طور پر", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Proceed", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "کلاؤڈ سٹوریج میں برآمد کریں", + "description": "tooltip" + }, + "cloudPull": { + "message": "کلاؤڈ سٹوریج میں درآمد کریں", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "کلاؤڈ سٹوریج سے درآمد کر کے موجودہ ترتیبات کے ساتھ ضم کریں", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "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.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "جمع کرائیں", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "تبدیلیاں لاگو کریں", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "کالعدم کریں", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "bytes", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Block element in frame…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Subscribe to filter list…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Temporarily allow large media elements", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "View source code…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Type a shortcut", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Toggle locked scrolling", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "کلپ بورڈ پر نقل کریں", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Select all", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Toggle cosmetic filtering", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Relax blocking mode", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Storage used: {{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Errors: {{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.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "This entry must be the last one", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/vi/messages.json b/src/_locales/vi/messages.json new file mode 100644 index 0000000..b358554 --- /dev/null +++ b/src/_locales/vi/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "Cuối cùng, đã có một công cụ chặn quảng cáo hiệu quả, tiêu tốn ít CPU và bộ nhớ.", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — Bảng điều khiển", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "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": { + "message": "Ở lại", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "Bỏ qua", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "Cài đặt", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "Danh sách bộ lọc", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "Bộ lọc của tôi", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "Quy tắc của tôi", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "Trang tin cậy", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "Phím tắt", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — Nhật ký các yêu cầu", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "Giới thiệu", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "Hỗ trợ", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ - Trình xem nội dung", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "Cài đặt nâng cao", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "message": "Nhấp chuột: vô hiệu/kích hoạt uBlock₀ cho trang này.\nCtrl + nhấp chuột: chỉ vô hiệu uBlock₀ trên trang này.", + "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." + }, + "popupPowerSwitchInfo1": { + "message": "Nhấp chuột để tắt uBlock₀ đối với toàn bộ tên miền này (site). \n\nCtrl + nhấp chuột để tắt uBlock₀ chỉ tại trang này (page).", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "Nhấp để bật uBlock₀ trên trang này.", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "yêu cầu đã chặn", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "trên trang này", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} hoặc {{percent}}%", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "từ lúc cài đặt", + "description": "English: since install" + }, + "popupOr": { + "message": "hoặc", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "Đã chặn trên trang này", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "Đã chặn từ khi cài đặt", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "Tên miền đã kết nối", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "Mở bảng điều khiển", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "Chuyển sang chế độ chặn phần tử tạm thời", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "Chuyển sang chế độ chọn phần tử", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "Mở nhật ký", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "Báo cáo lỗi trên trang này", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "Bật/tắt chặn popup của trang này", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "Nhấp để chặn tất cả cửa sổ bật lên trên trang này", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "Nhấn để bỏ chặn tất cả cửa sổ bật lên trên trang này", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "Bật tắt chặn yếu tố đa phương tiện lớn trên trang này", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "Nhấp để chặn các thành phần đa phương tiện lớn trên trang này", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "Nhấp để ngừng chặn các thành phần đa phương tiện kích thước lớn trên trang này", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "Bật/tắt bộ lọc phần tử trên trang này", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "Nhấn để tắt bộ lọc phần tử ẩn trên trang này", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "Nhấn để bật bộ lọc phần tử ẩn trên trang này", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "Bật tắt chặn font từ xa trên trang này", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "Nhấp để chặn phông tải về trên trang này", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "Nhấp để không chặn phông tải về trên trang này", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "Nhấp để vô hiệu hóa JavaScript trên trang này", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "Nhấp để ngừng vô hiệu hóa JavaScript trên trang này", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "Cửa sổ bật lên", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "Thành phần đa phương tiện kích thước lớn", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "Lọc phần tử hiển thị", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "Phông tải về", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "Mở rộng", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "Ít hơn", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "Quy tắc chung: cột này dành cho quy tắc áp dụng cho mọi trang.", + "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.", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "Bấm để thay đổi vĩnh viễn.", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "Bấm để hoàn tác thay đổi.", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "tất cả", + "description": "" + }, + "popupImageRulePrompt": { + "message": "hình ảnh", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "bên thứ ba", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "CSS/hình ảnh từ bên thứ ba", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "script cùng dòng", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "script bên thứ nhất", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "script bên thứ ba", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "khung bên thứ ba", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "tên miền đã kết nối", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} trên tổng {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "Phiên bản", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "tập lệnh", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "khung", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "Tạo", + "description": "English: Create" + }, + "pickerPick": { + "message": "Chọn", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "Thoát", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "Xem trước", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "Các bộ lọc mạng", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "Bộ lọc phần tử ẩn", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "Nhấp chuột, Ctrl-nhấp chuột", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "Chặn phần tử...", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "Ẩn các phần giữ chỗ của những phần tử bị chặn", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "Hiển thị số lượng yêu cầu bị chặn trên biểu tượng", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "Vô hiệu mách nước", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "Dùng menu ngữ cảnh nơi thích hợp", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "Thân thiện với người mù màu", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "Diện mạo", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "Giao diện", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "Tùy chọn màu nền", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "Kích hoạt hỗ trợ lưu trữ trực tuyến", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "Tôi là một người dùng có kinh nghiệm (Yêu cầu đọc qua)", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "Vô hiệu tải trước (để chặn bất kỳ kết nối với những yêu cầu mạng đã chặn)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "Vô hiệu giám sát siêu liên kết", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "Ngặn WebRTC làm lộ địa chỉ IP nội bộ", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "Hành vi mặc định", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "Những hành vi này có thể thay thế tiêu chuẩn từng trang", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "Vô hiệu lọc phần tử ẩn", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "Chặn yếu tố đa phương tiện lớn hơn {{input}} KB", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "Chặn font từ xa", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "Vô hiệu hóa JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "Chặn các báo cáo CSP", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "Chặn tên miền theo dõi mạo danh từ bên thứ ba (CNAME Trackers)", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "Nâng cao", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "Những tính năng dành cho người dùng nâng cao", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "cài đặt nâng cao", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "Lần phục hồi trước:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "Lần sao lưu trước:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "{{netFilterCount}} bộ lọc mạng + {{cosmeticFilterCount}} bộ lọc phần tử ẩn từ:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "Đã dùng {{used}} trên {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "Các danh sách bộ lọc tự cập nhật.", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "Cập nhật ngay", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "Dọn tất cả bộ nhớ đệm", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "Phân tích và thi hành bộ lọc phần tử ẩn.", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "Bộ lọc phần tử dùng để ẩn các yếu tố trong một trang web mà gây khó chịu cho người dùng và những yếu tố không thể chặn bằng cách dùng bộ lọc mạng.", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "Bỏ qua bộ lọc phần tử ẩn chung", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "Bộ lọc phần tử chung là những bộ lọc phần tử được áp dụng cho cho mọi trang web. Kích hoạt tùy chọn này sẽ giảm bớt sức nặng lên cpu và bộ nhớ do không còn phải xử lí các bộ lọc phần tử chung.\n\nTùy chọn này được khuyến nghị kích hoạt trên thiết bị cấu hình thấp.", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "Ngắt kết nối mạng cho đến khi tất cả các bộ lọc đã được tải", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "Danh sách những máy chủ bị chặn", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "Áp dụng các thay đổi", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "Dựng sẵn", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "Quảng cáo", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "Riêng tư", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "Bảo mật, bảo vệ khỏi phần mềm nguy hiểm", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "Phiền toái", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "Đa chức năng", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "Khu vực, ngôn ngữ", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "Tuỳ chỉnh", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "Nhập...", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "Một URL cho mỗi dòng. URL không hợp lệ sẽ âm thầm bị bỏ qua.", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "Đã cũ.", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "xem nội dung", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "Cập nhật lần cuối: {{ago}}.\nBấm để buộc cập nhật.", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "Đang cập nhật...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "Lỗi mạng ngăn tài nguyên được cập nhật.", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "Một bộ lọc cho mỗi dòng. Bộ lọc có thể là tên máy chủ thuần hoặc bộ lọc tương thích với EasyList. Các dòng có tiền tố ! sẽ bị bỏ qua.", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "Không thêm các bộ lọc từ các nguồn không đáng tin cậy. ", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "Nhập và thêm vào", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "Xuất", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "Áp dụng các thay đổi", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "Quy tắc vĩnh viễn", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "Quy tắc tạm thời", + "description": "header" + }, + "rulesRevert": { + "message": "Phục hồi", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "Xác nhận", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "Chỉnh sửa", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "Lưu", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "Huỷ", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "Nhập từ tập tin…", + "description": "" + }, + "rulesExport": { + "message": "Xuất ra tập tin", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "Danh sách quy tắc lọc chủ động.", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "Quy tắc cú pháp: nguồn đích loại hành động (tài liệu đầy đủ).", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "Sắp xếp:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "Loại quy tắc", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "Nguồn", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "Đích", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "Các chỉ thị trang web đáng tin cậy ra lệnh trên đó các trang web uBlock Origin sẽ bị vô hiệu hóa. Một mục nhập cho mỗi dòng. Chỉ thị không hợp lệ sẽ được âm thầm bỏ qua và nhận xét ra.", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "Nhập và thêm vào", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "Xuất", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-whitelist_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "Áp dụng các thay đổi", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "Loại", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "Tên miền", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "Bộ lọc", + "description": "English: Filter" + }, + "logAll": { + "message": "Tất cả", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "Tabless", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "Thẻ hiện tại", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "Tải lại nội dung thẻ", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "Chuyển đổi trình kiểm tra DOM", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "Đóng/mở hộp thoại popup", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki: Các logger", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "Xoá nhật ký", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "Tạm dừng nhật ký (loại bỏ tất cả dữ liệu đang nhập vào)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "Tiếp tục tác vụ nhật ký", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "Đóng/mở lọc tác vụ log", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "lọc mục ghi nhận", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "Lựa chọn lọc tác vụ log", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "Không phải", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "eventful", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "bị chặn", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "được phép", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "đã sửa đổi", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "Bên thứ nhất", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "Bên thứ ba", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "Chi tiết", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "Bộ lọc", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "Danh sách bộ lọc", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "Quy tắc", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "Ngữ cảnh", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "Ngữ cảnh gốc", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "Nguồn khác bên thứ nhất", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "Kiểu", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "Quy tắc URL", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "Ngữ cảnh:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "Loại:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "Bộ lọc tĩnh", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "{{action}} yêu cầu mạng của {{type}} {{br}}có địa chỉ URL phù hợp {{url}} {{br}}và từ nguồn {{origin}},{{br}}{{importance}} có một bộ lọc loại trừ phù hợp.", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "Chặn", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "Cho phép", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "loại “{{type}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "mọi loại", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "từ “{{origin}}”", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "từ mọi nơi", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "loại trừ khi", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "loại trừ nếu", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "Đã phát hiện bộ lọc tĩnh {{filter}} trong:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "Không tìm thấy bộ lọc tĩnh trong bất kỳ danh sách bộ lọc hiện đang được bật", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "Các mục Logger mà không đáp ứng tất cả ba điều kiện dưới đây sẽ được tự động loại bỏ:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "Bảo tồn các mục từ {{input}} phút trước", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "Bảo tồn nhiều nhất {{input}} trang được tải trên mỗi thẻ", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "Giữ lại tối đa {{input}} mục trên mỗi thẻ", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "Sử dụng {{input}} dòng trên mỗi entry trong chế độ mở rộng theo chiều dọc", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "Ẩn cột:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} Thời gian", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} Bộ lọc/quy tắc", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} Ngữ cảnh", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} Partyness", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "Danh sách", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "Bảng", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "Không có định dạng", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Đánh dấu", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "Mở", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "Tạo báo cáo mới", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "Tìm các báo cáo tương tự", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "Tài liệu hướng dẫn", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "Đọc tài liệu tại uBlock/wiki để tìm hiểu về các tính năng của uBlock Origin.", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "Hỗ trợ trả lời thắc mắc", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "Bạn có thể tìm thấy câu trả lời cho các thắc mắc của mình hoặc sự trợ giúp cho các vấn đề khác tại subreddit /r/uBlockOrigin.", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "Lỗi bộ lọc/ Trang web lỗi", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "Cần tài khoản GitHub: Báo cáo lỗi bộ lọc với tên miền cụ thể cho uBlock Origin tại đây. ", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "Chú ý: Tránh sử dụng các bộ chặn có chức năng tương tự song song uBlock Origin vì có thể gây ra lỗi bộ lọc trên nhiều trang web.", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "Mẹo: Hãy đảm bảo các bộ lọc của bạn được cập nhật đầy đủ. Nhật ký là một công cụ hữu hiệu để chẩn đoán các lỗi bộ lọc.", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "Báo cáo lỗi", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "Cần tài khoản GitHub: Báo cáo lỗi bộ lọc với tên miền cụ thể cho uBlock Origin tại đây. ", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "Thông tin chẩn đoán lỗi", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "Đây là các thông tin kỹ thuật có thể giúp ích khi khắc phục lỗi.", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "Lưu ý: Mặc định, các luật và bộ lọc cá nhân được ẩn. Điều này có thể khiến việc khắc phục lỗi khó khăn hơn.", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "Báo cáo lỗi bộ lọc cụ thể", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "Để tránh tạo thêm gánh nặng cho các tình nguyện viên, hãy chắc chắn rằng chưa từng có vấn đề tương tự được báo cáo.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "Danh sách bộ lọc được cập nhật hàng ngày. Đảm bảo vấn đề của bạn chưa được giải quyết trong danh sách bộ lọc gần đây nhất.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "Xác nhận rằng sự cố vẫn tồn tại kể cả sau khi đã tải lại trong web có vấn đề.", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "Địa chỉ trang web:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "Trang web...", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "--Chọn một lỗi--", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "Vẫn hiện quảng cáo hoặc vùng chứa quảng cáo", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "Xuất hiện lớp phủ hoặc các phần tử phiền toái khác", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "Phát hiện uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "Có các cấn đề về quyền riêng tư", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "Trục trặc khi bật uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "Xuất hiện các tab và cửa sổ ngoài mong muốn", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "Đánh dấu \"NFSW\" - Not Safe For Work cho trang web. Tìm hiểu về \"Not Safe For Work\"", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "Ẩn bớt", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "Hiện thêm", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "Chính sách bảo mật", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "Nhật ký thay đổi", + "description": "" + }, + "aboutCode": { + "message": "Mã nguồn (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "Những người đóng góp", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "Mã nguồn", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "Bản dịch", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "Danh sách bộ lọc", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "Các phụ thuộc bên ngoài (tương thích GPLv3):", + "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:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "CDN được chọn ngẫu nhiên khi cần cập nhật danh sách bộ lọc.", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "Sao lưu vào tập tin...", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "Khôi phục từ tập tin...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "Đặt lại cấu hình mặc định...", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "Các thiết lập của bạn sẽ bị ghi đè bởi dữ liệu đã lưu vào lúc {{time}}, và uBlock₀ sẽ khởi động lại. \n\nGhi đè các thiết lập hiện tại bằng dữ liệu đã lưu?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "Không thể đọc dữ liệu hoặc dữ liệu không hợp lệ", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "Các thiết lập sẽ bị xóa và uBlock₀ sẽ khởi động lại. \n\nThiết lập uBlock₀ về cấu hình ban đầu?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "Lỗi kết nối: {{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "uBlock₀: Thêm URL dưới đây vào bộ lọc tuỳ biến của bạn?\n\nTên: \"{{title}}\"\nURL: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "Đăng ký", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "một phút trước", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} phút trước", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "một giờ trước", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} giờ trước", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "một ngày trước", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} ngày trước", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "Hiện bảng điều khiển", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "Hiện nhật ký", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "tắt", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "Trang bị chặn", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBloc Origin đã chặn tải trang sau:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "Vì bộ lọc sau", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "message": "không có thông số", + "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": "Tìm thấy trong:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "Trở lại", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "Đóng cửa sổ này", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "Đừng cảnh báo tôi lần nữa về trang web này", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "Vô hiệu chặn nghiêm ngặt cho {{hostname}}", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "Tạm thời", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "Vĩnh viễn", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "Tiếp tục", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "Xuất ra lưu trữ trực tuyến", + "description": "tooltip" + }, + "cloudPull": { + "message": "Nhập từ lưu trữ trực tuyến", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "Nhập từ bộ lưu trữ trực tuyến và ghép với các thiết lập hiện tại", + "description": "tooltip" + }, + "cloudNoData": { + "message": "...\n...", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "Tên thiết bị này:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "Cảnh báo! Bạn phải chịu trách nhiệm cho những nguy cơ khi thay đổi các cài đặt nâng cao này.", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "Gửi", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "Áp dụng các thay đổi", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "Phục hồi", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "byte", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "Chặn phần tử trong khung ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "Đăng ký danh sách bộ lọc ...", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "Tạm thời cho phép yếu tố đa phương tiện lớn", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "Xem mã nguồn", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "Nhập phím tắt", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "Đóng/mở khóa cuộn", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "Sao chép vào bảng tạm", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "Chọn tất cả", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "Bật/tắt lọc phần tử", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "Nới lỏng chế độ chặn", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "Bộ nhớ đã dùng: {{value}} byte", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "Bấm để tải", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "Lỗi: {{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "Không thể lọc đúng cách khi khởi chạy trình duyệt. Tải lại trang để đảm bảo lọc thích hợp.", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "Đây là mục cuối", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json new file mode 100644 index 0000000..76ff0e1 --- /dev/null +++ b/src/_locales/zh_CN/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "一款高效的网络请求过滤工具,占用极低的内存和 CPU。", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — 控制面板", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "警告!您有未保存的更改", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "留下", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "忽略", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "设置", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "规则列表", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "自定义静态规则", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "自定义动态规则", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "白名单", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "快捷键", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — 记录器", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "关于", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "支持", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — 资源查看器", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "高级设置", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ 。", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "单击:对此网站启用 uBlock₀ 。", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "已拦截请求", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "在此页面", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "自安装后", + "description": "English: since install" + }, + "popupOr": { + "message": "或", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "在此页面已拦截", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "自安装后已拦截", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "已连接的域名", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "打开控制面板", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "进入临时移除元素模式", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "进入元素选择器模式", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "打开记录器", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "报告此网站上的问题", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "是否禁止此网站的所有弹出窗口", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "单击屏蔽此网站所有弹窗", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "单击取消屏蔽此网站所有弹窗", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "是否屏蔽此网站上较大的媒体元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "单击以屏蔽此网站上较大的媒体元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "单击取消屏蔽此网站大型媒体元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "是否对此网站应用元素过滤规则", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "单击禁用此网站上的元素过滤", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "单击启用针对此网站的元素过滤规则", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "是否屏蔽此网站的第三方字体", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "单击屏蔽此网站上的远程字体", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "单击取消屏蔽此网站上的远程字体", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "单击禁用此网站的所有脚本", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "单击以取消禁用此网站的所有脚本", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "弹出窗口", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "大型媒体元素", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "页面元素过滤", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "远程字体", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "更多", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "更少", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "全局规则:此列的规则作用于所有网站。", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "本地规则:此列的规则仅作用于当前网站。\n本地规则优先于全局规则。", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "点击以使更改永久生效。", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "点击以撤销更改。", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "全部", + "description": "" + }, + "popupImageRulePrompt": { + "message": "图片", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "第三方", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "第三方 CSS/图像", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "内联脚本", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "第一方脚本", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "第三方脚本", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "第三方框架", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "已连接域名", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} / {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "版本", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "脚本", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "框架", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "创建", + "description": "English: Create" + }, + "pickerPick": { + "message": "选择", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "放弃", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "预览", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "URL 过滤规则", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "元素过滤规则", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "单击,Ctrl + 单击", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "屏蔽元素…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "隐藏已屏蔽元素的占位符", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "在图标上显示拦截请求数", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "不显示悬停提示", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "添加“屏蔽元素”到右键菜单", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "适合色盲人士", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "外观", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "主题", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "自定义强调色", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "启用云端储存", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "我是高级用户", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "禁止预读取(拦截对已屏蔽网络请求的任何连接)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "禁用超链接审计(hyperlink auditing)", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "防止 WebRTC 泄露本地 IP 地址", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "默认行为", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "这些默认行为可被针对各网站的设置取代", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "禁用元素过滤规则", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "屏蔽大于 {{input}} KB 的媒体元素", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "屏蔽远程字体", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "禁用 JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "屏蔽 CSP 报告", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "将代理域名映射至真实域名", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "高级", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "仅适合专家级用户的功能。", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "高级设置", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "上次恢复:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "上次备份:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "当前使用了 {{netFilterCount}} 个 URL 过滤规则和 {{cosmeticFilterCount}} 个元素过滤规则:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} / {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "自动更新过滤规则", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "立即更新", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "清除所有缓存", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "解析并应用元素过滤规则", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "元素过滤规则用于隐藏网页中碍眼,且不能被基于网络请求的过滤引擎屏蔽的元素。", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "忽略通用元素过滤规则", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "通用元素过滤规则是应用到所有网站的元素过滤规则。启用此选项将消除网站因处理通用元素过滤规则而增加的内存和 CPU 占用。\n\n推荐在低性能设备上启用此选项。", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "过滤规则列表全部加载完成前暂停网络连接", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "被屏蔽站点列表", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "应用更改", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "内置", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "广告", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "隐私", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "恶意软件防护、安全", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "骚扰", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "多用途", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "区域、语言", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "自定义", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "导入…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "一行一条网址。无效网址将被忽略。", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "过久未更新。", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "查看内容", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "上次更新:{{ago}}。\n点击此处要求更新。", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "正在更新...", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "资源更新因网络错误受阻。", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "一行一条过滤规则。每条规则可以是一个普通的主机名或者是一条与 EasyList 兼容的过滤规则。以 ! 开头的行将被忽略。", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "请勿添加未信任来源的过滤规则。", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "导入并添加…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "导出…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "应用更改", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "永久规则", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "临时规则", + "description": "header" + }, + "rulesRevert": { + "message": "恢复", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "提交", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "编辑", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "保存", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "取消", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "从文件导入…", + "description": "" + }, + "rulesExport": { + "message": "导出到文件...", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "您的动态过滤规则列表。", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "规则语法:来源主机名称 目标主机名称 连接请求类型 操作完整说明)。", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "排列:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "规则类型", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "来源", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "目标", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "白名单中的规则匹配的页面不会被 uBlock Origin 过滤或阻挡。每行一条规则。", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "导入并添加…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "导出…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "应用更改", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "类型", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "域名", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "URL", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "过滤规则", + "description": "English: Filter" + }, + "logAll": { + "message": "全部", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "后台网络请求", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "当前标签页", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "重新加载此标签页的内容", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "是否打开 DOM 探查器", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "是否打开弹出式面板", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki:记录器", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "清空记录", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "暂停记录(放弃所有传入数据)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "取消暂停记录", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "是否启用记录器筛选", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "筛选记录条目", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "记录器筛选设定", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "非", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "已应用规则", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "已拦截", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "已允许", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "已修改", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "第一方", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "第三方", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "详细资料", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "过滤规则", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "规则列表", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "规则", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "上下文", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "根上下文", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "第一方/第三方", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "类型", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "URL", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "URL 规则", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "上下文:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "类型:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "静态规则", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "当 URL 匹配 {{url}},{{br}}且来源于 {{origin}} 时,{{br}}{{action}} {{type}} 的网络请求,{{br}}{{importance}} 有一个匹配的例外规则。", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "拦截", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "允许", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "“{{type}}”类型", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "任何类型", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "来源于 \"{{origin}}\"", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "任何地方", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "除非", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "即使", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "静态规则 {{filter}} 被包含于:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "无法在当前启用的任何过滤规则列表中找到静态规则", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "不符合以下任一状况的记录将会被自动清除:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "最多保留 {{input}} 分钟以内的记录", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "每个分页最多保留 {{input}} 次内容加载产生的记录", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "每个分页最多保留 {{input}} 条记录", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "垂直扩展模式下每项使用 {{input}} 行", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "隐藏栏位:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} 时间", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} 过滤规则", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} 上下文", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} 第一方/第三方", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "列表", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "表格", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "纯文字", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "打开", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "创建新报告", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "查找类似报告", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "使用说明", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "请至 uBlock/wiki 参阅 uBlock Origin 的所有功用以及使用说明。", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "疑难解答", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "若想进行普通的咨询或是需要其他帮助,请至 Reddit 的 /r/uBlockOrigin 板块寻求解答。", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "过滤规则或者网页的问题", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "将有关特定网站的过滤规则问题反馈至 uBlockOrigin/uAssets 问题跟踪器需要 GitHub 账号。", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "重要:避免同时使用类似 uBlock Origin 的过滤软件,这可能导致在特定的网站上遇到过滤规则问题。", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "小提示:确保在使用最新的过滤规则列表。日志记录器是诊断过滤规则问题的首选工具。", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "错误报告", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "将 uBlock Origin 本身的问题反馈至 uBlockOrigin/uBlock-issue 问题跟踪器需要 GitHub 账号。", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "故障排查相关信息", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "以下生成的技术报告或有助于他人帮你解决问题。", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "注意:可能涉及隐私的内容已经过删改,需手动取消。删改部分有可能包括解决问题的关键信息。", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "报告过滤规则的问题", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "请确认该问题未有其他人上报过,避免重复提交报告给维护者带来额外负担。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "过滤规则列表每天都会更新。请确认您的问题无法用最新的过滤规则列表解决。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "请验证重新加载问题页面后问题依然存在。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "网址:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "该网页…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- 选择其中一项 --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "显示广告或广告残留", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "存在遮盖或类似问题", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "检测出 uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "存在隐私相关问题", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "启用 uBlock Origin 后出现异常", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "打开不需要的标签页或窗口", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "将该网页标记为 “NSFW”(“工作场所不宜”)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "自动删改", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "取消删改", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "隐私政策", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "变更日志", + "description": "" + }, + "aboutCode": { + "message": "源代码 (GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "贡献者", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "源代码", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "翻译", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "过滤规则列表", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "外部依赖(兼容 GPLv3 协议):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO 本身提供的过滤规则列表免费托管于下列 CDN:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "需要更新过滤规则列表时会随机选用一个 CDN。", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "备份到文件…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "从文件还原…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "重置为默认设置", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "您的所有设置将被备份于 {{time}} 的数据覆盖,并且 uBlock₀ 将重新启动。\n确定要用备份的数据覆盖全部现有设置吗?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "无法读取数据,或数据无效", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "您的设置将被清除,uBlock₀ 将重新启动。\n\n确定将 uBlock₀ 重置到初始状态?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "网络错误:{{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "添加下列网址到您的自定义规则列表吗?\n\n标题: “{{title}}”\n网址: {{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "订阅", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 分钟前", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} 分钟前", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "1 小时前", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} 小时前", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "1 天前", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} 天前", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "显示控制面板", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "显示记录器", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "关", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "页面已被屏蔽", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin 阻止了下列页面加载:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "因为下列过滤规则:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "被包含于:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "返回", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "关闭此窗口", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "不再针对此网站作出警告", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "不对 {{hostname}} 进行严格屏蔽", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "暂时", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "永久", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "继续加载", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "导出到云端储存", + "description": "tooltip" + }, + "cloudPull": { + "message": "从云端储存导入", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "从云存储导入并与当前设置合并", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "此设备名称:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "警告!更改这些高级设置可能造成问题,请自担风险。", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "提交", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "应用更改", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "还原", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "字节", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "屏蔽框架中的内容…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "订阅规则列表…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "临时允许较大媒体元素", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "查看源代码…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "键入快捷键", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "是否启用同步滚动", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "复制到剪贴板", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "全选", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "是否应用元素过滤规则", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "放宽拦截限制", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "已用存储:{{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "单击以加载", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "错误:{{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "无法在浏览器启动时正常过滤。请重新加载此页面以确保正常过滤。", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "此条目必须是最后一个", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json new file mode 100644 index 0000000..10f947b --- /dev/null +++ b/src/_locales/zh_TW/messages.json @@ -0,0 +1,1290 @@ +{ + "extName": { + "message": "uBlock Origin", + "description": "extension name." + }, + "extShortDesc": { + "message": "終於有套使用不多的 CPU 及記憶體資源的高效率阻擋器。", + "description": "this will be in the Chrome web store: must be 132 characters or less" + }, + "dashboardName": { + "message": "uBlock₀ — 控制台", + "description": "English: uBlock₀ — Dashboard" + }, + "dashboardUnsavedWarning": { + "message": "警告!您有尚未儲存的變更", + "description": "A warning in the dashboard when navigating away from unsaved changes" + }, + "dashboardUnsavedWarningStay": { + "message": "留下", + "description": "Label for button to prevent navigating away from unsaved changes" + }, + "dashboardUnsavedWarningIgnore": { + "message": "忽略", + "description": "Label for button to ignore unsaved changes" + }, + "settingsPageName": { + "message": "設定", + "description": "appears as tab name in dashboard" + }, + "3pPageName": { + "message": "過濾規則清單", + "description": "appears as tab name in dashboard" + }, + "1pPageName": { + "message": "自訂靜態過濾規則", + "description": "appears as tab name in dashboard" + }, + "rulesPageName": { + "message": "自訂動態過濾規則", + "description": "appears as tab name in dashboard" + }, + "whitelistPageName": { + "message": "受信任網站", + "description": "appears as tab name in dashboard" + }, + "shortcutsPageName": { + "message": "快速鍵", + "description": "appears as tab name in dashboard" + }, + "statsPageName": { + "message": "uBlock₀ — 記錄器", + "description": "Title for the logger window" + }, + "aboutPageName": { + "message": "關於", + "description": "appears as tab name in dashboard" + }, + "supportPageName": { + "message": "支援", + "description": "appears as tab name in dashboard" + }, + "assetViewerPageName": { + "message": "uBlock₀ — 資源檢視器", + "description": "Title for the asset viewer page" + }, + "advancedSettingsPageName": { + "message": "進階設定", + "description": "Title for the advanced settings page" + }, + "popupPowerSwitchInfo": { + "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₀ 。", + "description": "Message to be read by screen readers" + }, + "popupPowerSwitchInfo2": { + "message": "點擊以在此網站啟用 uBlock₀ 。", + "description": "Message to be read by screen readers" + }, + "popupBlockedRequestPrompt": { + "message": "已阻擋的連線請求", + "description": "English: requests blocked" + }, + "popupBlockedOnThisPagePrompt": { + "message": "在此頁面", + "description": "English: on this page" + }, + "popupBlockedStats": { + "message": "{{count}} ({{percent}}%)", + "description": "Example: 15 (13%)" + }, + "popupBlockedSinceInstallPrompt": { + "message": "自安裝後", + "description": "English: since install" + }, + "popupOr": { + "message": "或", + "description": "English: or" + }, + "popupBlockedOnThisPage_v2": { + "message": "此頁面已阻擋", + "description": "For the new mobile-friendly popup design" + }, + "popupBlockedSinceInstall_v2": { + "message": "安裝後已阻擋", + "description": "For the new mobile-friendly popup design" + }, + "popupDomainsConnected_v2": { + "message": "已連接的網域", + "description": "For the new mobile-friendly popup design" + }, + "popupTipDashboard": { + "message": "開啟控制台", + "description": "English: Click to open the dashboard" + }, + "popupTipZapper": { + "message": "進入元素臨時移除模式", + "description": "Tooltip for the element-zapper icon in the popup panel" + }, + "popupTipPicker": { + "message": "進入元素選擇器模式", + "description": "English: Enter element picker mode" + }, + "popupTipLog": { + "message": "開啟記錄器", + "description": "Tooltip used for the logger icon in the panel" + }, + "popupTipReport": { + "message": "回報此網站的問題", + "description": "Tooltip used for the 'chat' icon in the panel" + }, + "popupTipNoPopups": { + "message": "切換是否阻擋此網站的所有彈出型視窗", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups1": { + "message": "點擊以阻擋此網站的所有彈出式視窗", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoPopups2": { + "message": "點擊後將不再封鎖此網站的所有彈出式廣告", + "description": "Tooltip for the no-popups per-site switch" + }, + "popupTipNoLargeMedia": { + "message": "切換是否封鎖此網站的大型媒體元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia1": { + "message": "點擊以封鎖此網站的大型媒體元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoLargeMedia2": { + "message": "點擊以停止封鎖此網站的大型媒體元素", + "description": "Tooltip for the no-large-media per-site switch" + }, + "popupTipNoCosmeticFiltering": { + "message": "切換是否在此網站過濾網頁元素", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering1": { + "message": "點擊以停用此網站的網頁元素過濾", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoCosmeticFiltering2": { + "message": "點擊以啟用此網站的網頁元素過濾", + "description": "Tooltip for the no-cosmetic-filtering per-site switch" + }, + "popupTipNoRemoteFonts": { + "message": "切換是否封鎖此網站的遠端字體", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts1": { + "message": "點擊以封鎖此網站的遠端字型", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoRemoteFonts2": { + "message": "點擊以停止封鎖此網站的遠端字型", + "description": "Tooltip for the no-remote-fonts per-site switch" + }, + "popupTipNoScripting1": { + "message": "點擊以停用此網站的 JavaScript", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupTipNoScripting2": { + "message": "點擊以重新啟用此網站的 JavaScript ", + "description": "Tooltip for the no-scripting per-site switch" + }, + "popupNoPopups_v2": { + "message": "彈出式視窗", + "description": "Caption for the no-popups per-site switch" + }, + "popupNoLargeMedia_v2": { + "message": "大型媒體元素", + "description": "Caption for the no-large-media per-site switch" + }, + "popupNoCosmeticFiltering_v2": { + "message": "網頁元素過濾", + "description": "Caption for the no-cosmetic-filtering per-site switch" + }, + "popupNoRemoteFonts_v2": { + "message": "遠端字體", + "description": "Caption for the no-remote-fonts per-site switch" + }, + "popupNoScripting_v2": { + "message": "JavaScript", + "description": "Caption for the no-scripting per-site switch" + }, + "popupMoreButton_v2": { + "message": "更多", + "description": "Label to be used to show popup panel sections" + }, + "popupLessButton_v2": { + "message": "更少", + "description": "Label to be used to hide popup panel sections" + }, + "popupTipGlobalRules": { + "message": "全域規則:此欄位的規則會套用至所有網站。", + "description": "Tooltip when hovering the top-most cell of the global-rules column." + }, + "popupTipLocalRules": { + "message": "區域規則:此欄位的規則僅會套用至目前網站。\n區域規則會覆蓋過全域規則。", + "description": "Tooltip when hovering the top-most cell of the local-rules column." + }, + "popupTipSaveRules": { + "message": "點擊此處讓變更永久生效。", + "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." + }, + "popupTipRevertRules": { + "message": "點擊以撤銷變更。", + "description": "Tooltip when hovering over the eraser in the dynamic filtering pane." + }, + "popupAnyRulePrompt": { + "message": "全部", + "description": "" + }, + "popupImageRulePrompt": { + "message": "圖片", + "description": "" + }, + "popup3pAnyRulePrompt": { + "message": "第三方", + "description": "" + }, + "popup3pPassiveRulePrompt": { + "message": "第三方 CSS / 圖片", + "description": "" + }, + "popupInlineScriptRulePrompt": { + "message": "內聯腳本", + "description": "" + }, + "popup1pScriptRulePrompt": { + "message": "第一方腳本", + "description": "" + }, + "popup3pScriptRulePrompt": { + "message": "第三方腳本", + "description": "" + }, + "popup3pFrameRulePrompt": { + "message": "第三方框架", + "description": "" + }, + "popupHitDomainCountPrompt": { + "message": "已連結的網域", + "description": "appears in popup" + }, + "popupHitDomainCount": { + "message": "{{count}} / {{total}}", + "description": "appears in popup" + }, + "popupVersion": { + "message": "版本", + "description": "Example of use: Version 1.26.4" + }, + "popup3pScriptFilter": { + "message": "腳本", + "description": "Appears as an option to filter out firewall rows" + }, + "popup3pFrameFilter": { + "message": "框架", + "description": "Appears as an option to filter out firewall rows" + }, + "pickerCreate": { + "message": "建立", + "description": "English: Create" + }, + "pickerPick": { + "message": "選擇", + "description": "English: Pick" + }, + "pickerQuit": { + "message": "放棄", + "description": "English: Quit" + }, + "pickerPreview": { + "message": "預覽", + "description": "Element picker preview mode: will cause the elements matching the current filter to be removed from the page" + }, + "pickerNetFilters": { + "message": "網址過濾規則", + "description": "English: header for a type of filter in the element picker dialog" + }, + "pickerCosmeticFilters": { + "message": "元素隱藏過濾規則", + "description": "English: Cosmetic filters" + }, + "pickerCosmeticFiltersHint": { + "message": "點擊,按住 Ctrl 鍵點擊", + "description": "English: Click, Ctrl-click" + }, + "pickerContextMenuEntry": { + "message": "阻擋元素…", + "description": "An entry in the browser's contextual menu" + }, + "settingsCollapseBlockedPrompt": { + "message": "隱藏已阻擋元素的佔位元素", + "description": "English: Hide placeholders of blocked elements" + }, + "settingsIconBadgePrompt": { + "message": "在圖示上顯示被阻擋的連線請求的數量", + "description": "English: Show the number of blocked requests on the icon" + }, + "settingsTooltipsPrompt": { + "message": "關閉提示文字功能", + "description": "A checkbox in the Settings pane" + }, + "settingsContextMenuPrompt": { + "message": "將 uBlock Origin 加入右鍵選單", + "description": "English: Make use of context menu where appropriate" + }, + "settingsColorBlindPrompt": { + "message": "使用對色盲友善的色彩", + "description": "English: Color-blind friendly" + }, + "settingsAppearance": { + "message": "外觀", + "description": "Section for controlling user interface appearance" + }, + "settingsThemeLabel": { + "message": "佈景主題", + "description": "Label for checkbox to enable a custom dark theme" + }, + "settingsThemeAccent0Label": { + "message": "自訂強調顏色", + "description": "Label for checkbox to pick an accent color" + }, + "settingsCloudStorageEnabledPrompt": { + "message": "啟用雲端儲存空間的支援", + "description": "" + }, + "settingsAdvancedUserPrompt": { + "message": "我是進階使用者", + "description": "Checkbox to let user access advanced, technical features" + }, + "settingsPrefetchingDisabledPrompt": { + "message": "停用預先載入模式(避免連線至已阻擋的網路要求)", + "description": "English: " + }, + "settingsHyperlinkAuditingDisabledPrompt": { + "message": "停用超連結監測", + "description": "English: " + }, + "settingsWebRTCIPAddressHiddenPrompt": { + "message": "防止 WebRTC 洩漏本地 IP 位址", + "description": "English: " + }, + "settingPerSiteSwitchGroup": { + "message": "預設行為", + "description": "" + }, + "settingPerSiteSwitchGroupSynopsis": { + "message": "這些預設行為可再依各網站調整", + "description": "" + }, + "settingsNoCosmeticFilteringPrompt": { + "message": "停用元素隱藏過濾規則", + "description": "" + }, + "settingsNoLargeMediaPrompt": { + "message": "封鎖超過 {{input}} KB 的媒體元素", + "description": "" + }, + "settingsNoRemoteFontsPrompt": { + "message": "封鎖遠端字型", + "description": "" + }, + "settingsNoScriptingPrompt": { + "message": "停用 JavaScript", + "description": "The default state for the per-site no-scripting switch" + }, + "settingsNoCSPReportsPrompt": { + "message": "封鎖內容安全策略報告", + "description": "background information: https://github.com/gorhill/uBlock/issues/3150" + }, + "settingsUncloakCnamePrompt": { + "message": "揭露網域真實名稱", + "description": "background information: https://github.com/uBlockOrigin/uBlock-issues/issues/1513" + }, + "settingsAdvanced": { + "message": "進階", + "description": "Section for controlling advanced-user settings" + }, + "settingsAdvancedSynopsis": { + "message": "僅適合技術使用者的功能", + "description": "Description of section controlling advanced-user settings" + }, + "settingsAdvancedUserSettings": { + "message": "進階設定", + "description": "For the tooltip of a link which gives access to advanced settings" + }, + "settingsLastRestorePrompt": { + "message": "上次還原:", + "description": "English: Last restore:" + }, + "settingsLastBackupPrompt": { + "message": "上次備份:", + "description": "English: Last backup:" + }, + "3pListsOfBlockedHostsPrompt": { + "message": "目前已使用 {{netFilterCount}} 個網址過濾規則 + {{cosmeticFilterCount}} 個元素隱藏過濾規則:", + "description": "Appears at the top of the _3rd-party filters_ pane" + }, + "3pListsOfBlockedHostsPerListStats": { + "message": "{{used}} / {{total}}", + "description": "Appears aside each filter list in the _3rd-party filters_ pane" + }, + "3pAutoUpdatePrompt1": { + "message": "自動更新過濾規則", + "description": "A checkbox in the _3rd-party filters_ pane" + }, + "3pUpdateNow": { + "message": "立即更新", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pPurgeAll": { + "message": "清除所有快取", + "description": "A button in the in the _3rd-party filters_ pane" + }, + "3pParseAllABPHideFiltersPrompt1": { + "message": "解析並套用元素隱藏過濾規則", + "description": "English: Parse and enforce Adblock+ element hiding filters." + }, + "3pParseAllABPHideFiltersInfo": { + "message": "元素隱藏過濾規則 用於隱藏網頁中礙眼,且不能被基於網路請求的過濾引擎所阻擋的元素。", + "description": "Describes the purpose of the 'Parse and enforce cosmetic filters' feature." + }, + "3pIgnoreGenericCosmeticFilters": { + "message": "忽略一般元素隱藏過濾規則", + "description": "This will cause uBO to ignore all generic cosmetic filters." + }, + "3pIgnoreGenericCosmeticFiltersInfo": { + "message": "通用元素隱藏過濾規則 是會套用在所有網頁的元素隱藏過濾規則。啟用此選項會減少每個網頁,因處理一般元素隱藏過濾規則,而增加的記憶體與 CPU 使用量。\n\n建議在效能較差的裝置上啟用此選項。", + "description": "Describes the purpose of the 'Ignore generic cosmetic filters' feature." + }, + "3pSuspendUntilListsAreLoaded": { + "message": "在所有過濾器清單載入完成前暫停網路活動", + "description": "A checkbox in the 'Filter lists' pane" + }, + "3pListsOfBlockedHostsHeader": { + "message": "被阻擋網域的列表", + "description": "English: Lists of blocked hosts" + }, + "3pApplyChanges": { + "message": "套用變更", + "description": "English: Apply changes" + }, + "3pGroupDefault": { + "message": "內置", + "description": "Filter lists section name" + }, + "3pGroupAds": { + "message": "廣告", + "description": "Filter lists section name" + }, + "3pGroupPrivacy": { + "message": "隱私", + "description": "Filter lists section name" + }, + "3pGroupMalware": { + "message": "惡意軟體防護及安全性", + "description": "Filter lists section name" + }, + "3pGroupAnnoyances": { + "message": "嫌惡元素", + "description": "Filter lists section name" + }, + "3pGroupMultipurpose": { + "message": "多用途", + "description": "Filter lists section name" + }, + "3pGroupRegions": { + "message": "地區、語言", + "description": "Filter lists section name" + }, + "3pGroupCustom": { + "message": "自訂", + "description": "Filter lists section name" + }, + "3pImport": { + "message": "匯入…", + "description": "The label for the checkbox used to import external filter lists" + }, + "3pExternalListsHint": { + "message": "每行一個網址。無效的網址將被忽略。", + "description": "Short information about how to use the textarea to import external filter lists by URL" + }, + "3pExternalListObsolete": { + "message": "過久未更新。", + "description": "used as a tooltip for the out-of-date icon beside a list" + }, + "3pViewContent": { + "message": "查看內容", + "description": "used as a tooltip for eye icon beside a list" + }, + "3pLastUpdate": { + "message": "上次更新:{{ago}}。\n點擊此處以要求更新。", + "description": "used as a tooltip for the clock icon beside a list" + }, + "3pUpdating": { + "message": "更新中…", + "description": "used as a tooltip for the spinner icon beside a list" + }, + "3pNetworkError": { + "message": "因網路錯誤無法更新資源。", + "description": "used as a tooltip for error icon beside a list" + }, + "1pFormatHint": { + "message": "每行一個過濾規則。規則可以單純是主機名稱,或是與 EasyList 相容的過濾規則。以 ! 開頭的行將被忽略。", + "description": "Short information about how to create custom filters" + }, + "1pTrustWarning": { + "message": "請勿添加未信任來源的過濾規則。", + "description": "Warning against copy-pasting filters from random sources" + }, + "1pImport": { + "message": "匯入並加入…", + "description": "Button in the 'My filters' pane" + }, + "1pExport": { + "message": "匯出…", + "description": "Button in the 'My filters' pane" + }, + "1pExportFilename": { + "message": "my-ublock-static-filters_{{datetime}}.txt", + "description": "English: my-ublock-static-filters_{{datetime}}.txt" + }, + "1pApplyChanges": { + "message": "套用變更", + "description": "English: Apply changes" + }, + "rulesPermanentHeader": { + "message": "永久規則", + "description": "header" + }, + "rulesTemporaryHeader": { + "message": "臨時規則", + "description": "header" + }, + "rulesRevert": { + "message": "還原", + "description": "This will remove all temporary rules" + }, + "rulesCommit": { + "message": "提交", + "description": "This will persist temporary rules" + }, + "rulesEdit": { + "message": "編輯", + "description": "Will enable manual-edit mode (textarea)" + }, + "rulesEditSave": { + "message": "儲存", + "description": "Will save manually-edited content and exit manual-edit mode" + }, + "rulesEditDiscard": { + "message": "捨棄", + "description": "Will discard manually-edited content and exit manual-edit mode" + }, + "rulesImport": { + "message": "從檔案匯入…", + "description": "" + }, + "rulesExport": { + "message": "匯出至檔案…", + "description": "Button in the 'My rules' pane" + }, + "rulesDefaultFileName": { + "message": "my-ublock-dynamic-rules_{{datetime}}.txt", + "description": "default file name to use" + }, + "rulesHint": { + "message": "您的動態過濾規則清單。", + "description": "English: List of your dynamic filtering rules." + }, + "rulesFormatHint": { + "message": "規則語法:來源主機名稱 目標主機名稱 連線請求類型 操作完整說明)。", + "description": "English: dynamic rule syntax and full documentation." + }, + "rulesSort": { + "message": "排序:", + "description": "English: label for sort option." + }, + "rulesSortByType": { + "message": "規則類型", + "description": "English: a sort option for list of rules." + }, + "rulesSortBySource": { + "message": "來源", + "description": "English: a sort option for list of rules." + }, + "rulesSortByDestination": { + "message": "目標", + "description": "English: a sort option for list of rules." + }, + "whitelistPrompt": { + "message": "信任名單中的規則適用的頁面不會被 uBlock Origin 過濾或阻擋。每行一個規則。", + "description": "A concise description of the 'Trusted sites' pane." + }, + "whitelistImport": { + "message": "匯入並加入…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExport": { + "message": "匯出…", + "description": "Button in the 'Trusted sites' pane" + }, + "whitelistExportFilename": { + "message": "my-ublock-trusted-sites_{{datetime}}.txt", + "description": "The default filename to use for import/export purpose" + }, + "whitelistApply": { + "message": "套用變更", + "description": "English: Apply changes" + }, + "logRequestsHeaderType": { + "message": "類型", + "description": "English: Type" + }, + "logRequestsHeaderDomain": { + "message": "網域", + "description": "English: Domain" + }, + "logRequestsHeaderURL": { + "message": "網址", + "description": "English: URL" + }, + "logRequestsHeaderFilter": { + "message": "過濾規則", + "description": "English: Filter" + }, + "logAll": { + "message": "全部", + "description": "Appears in the logger's tab selector" + }, + "logBehindTheScene": { + "message": "背景網路連線請求", + "description": "Pretty name for behind-the-scene network requests" + }, + "loggerCurrentTab": { + "message": "目前分頁", + "description": "Appears in the logger's tab selector" + }, + "loggerReloadTip": { + "message": "重新載入分頁內容", + "description": "Tooltip for the reload button in the logger page" + }, + "loggerDomInspectorTip": { + "message": "切換是否啟用 DOM 檢視器", + "description": "Tooltip for the DOM inspector button in the logger page" + }, + "loggerPopupPanelTip": { + "message": "切換是否啟用彈出式面板", + "description": "Tooltip for the popup panel button in the logger page" + }, + "loggerInfoTip": { + "message": "uBlock Origin wiki:記錄器", + "description": "Tooltip for the top-right info label in the logger page" + }, + "loggerClearTip": { + "message": "清除記錄", + "description": "Tooltip for the eraser in the logger page; used to blank the content of the logger" + }, + "loggerPauseTip": { + "message": "暫停記錄(捨棄所有傳入資料)", + "description": "Tooltip for the pause button in the logger page" + }, + "loggerUnpauseTip": { + "message": "取消暫停記錄", + "description": "Tooltip for the play button in the logger page" + }, + "loggerRowFiltererButtonTip": { + "message": "切換是否啟用記錄篩選", + "description": "Tooltip for the row filterer button in the logger page" + }, + "logFilterPrompt": { + "message": "篩選記錄條目", + "description": "Placeholder string for logger output filtering input field" + }, + "loggerRowFiltererBuiltinTip": { + "message": "記錄器篩選設定", + "description": "Tooltip for the button to bring up logger output filtering options" + }, + "loggerRowFiltererBuiltinNot": { + "message": "非", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinEventful": { + "message": "已套用規則", + "description": "A keyword in the built-in row filtering expression: all items corresponding to uBO doing something (blocked, allowed, redirected, etc.)" + }, + "loggerRowFiltererBuiltinBlocked": { + "message": "已封鎖", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinAllowed": { + "message": "已允許", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltinModified": { + "message": "已修改", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin1p": { + "message": "第一方", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerRowFiltererBuiltin3p": { + "message": "第三方", + "description": "A keyword in the built-in row filtering expression" + }, + "loggerEntryDetailsHeader": { + "message": "詳細資料", + "description": "Small header to identify the 'Details' pane for a specific logger entry" + }, + "loggerEntryDetailsFilter": { + "message": "過濾規則", + "description": "Label to identify a filter field" + }, + "loggerEntryDetailsFilterList": { + "message": "過濾規則清單", + "description": "Label to identify a filter list field" + }, + "loggerEntryDetailsRule": { + "message": "規則", + "description": "Label to identify a rule field" + }, + "loggerEntryDetailsContext": { + "message": "上下文", + "description": "Label to identify a context field (typically a hostname)" + }, + "loggerEntryDetailsRootContext": { + "message": "根上下文", + "description": "Label to identify a root context field (typically a hostname)" + }, + "loggerEntryDetailsPartyness": { + "message": "所屬方", + "description": "Label to identify a field providing partyness information" + }, + "loggerEntryDetailsType": { + "message": "類型", + "description": "Label to identify the type of an entry" + }, + "loggerEntryDetailsURL": { + "message": "網址", + "description": "Label to identify the URL of an entry" + }, + "loggerURLFilteringHeader": { + "message": "網址規則", + "description": "Small header to identify the dynamic URL filtering section" + }, + "loggerURLFilteringContextLabel": { + "message": "上下文:", + "description": "Label for the context selector" + }, + "loggerURLFilteringTypeLabel": { + "message": "類型:", + "description": "Label for the type selector" + }, + "loggerStaticFilteringHeader": { + "message": "靜態過濾", + "description": "Small header to identify the static filtering section" + }, + "loggerStaticFilteringSentence": { + "message": "當網址符合 {{url}},{{br}}並且來自 {{origin}} 時,{{br}}{{action}} {{type}} 的網路請求,{{br}}{{importance}} 已有符合的過濾例外規則。", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartBlock": { + "message": "封鎖", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAllow": { + "message": "允許", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartType": { + "message": "{{type}} 類型", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyType": { + "message": "任何類型", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartOrigin": { + "message": "來自「{{origin}}」", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartAnyOrigin": { + "message": "來自任何地方", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartNotImportant": { + "message": "除非", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringSentencePartImportant": { + "message": "就算", + "description": "Used in the static filtering wizard" + }, + "loggerStaticFilteringFinderSentence1": { + "message": "在下列清單中找到靜態過濾規則 {{filter}}:", + "description": "Below this sentence, the filter list(s) in which the filter was found" + }, + "loggerStaticFilteringFinderSentence2": { + "message": "無法在任何目前已啟用的過濾規則清單中找到靜態過濾規則", + "description": "Message to show when a filter cannot be found in any filter lists" + }, + "loggerSettingDiscardPrompt": { + "message": "未符合以下所有條件的記錄將會被自動捨棄:", + "description": "Logger setting: A sentence to describe the purpose of the settings below" + }, + "loggerSettingPerEntryMaxAge": { + "message": "最多保留 {{input}} 分鐘以內的記錄", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxLoads": { + "message": "每個分頁最多保留 {{input}} 次重新載入該頁所產生的記錄", + "description": "A logger setting" + }, + "loggerSettingPerTabMaxEntries": { + "message": "每個分頁最多保留 {{input}} 條記錄", + "description": "A logger setting" + }, + "loggerSettingPerEntryLineCount": { + "message": "在垂直延展模式中每條記錄顯示 {{input}} 行", + "description": "A logger setting" + }, + "loggerSettingHideColumnsPrompt": { + "message": "隱藏欄位:", + "description": "Logger settings: a sentence to describe the purpose of the checkboxes below" + }, + "loggerSettingHideColumnTime": { + "message": "{{input}} 時間", + "description": "A label for the time column" + }, + "loggerSettingHideColumnFilter": { + "message": "{{input}} 過濾規則", + "description": "A label for the filter or rule column" + }, + "loggerSettingHideColumnContext": { + "message": "{{input}} 上下文", + "description": "A label for the context column" + }, + "loggerSettingHideColumnPartyness": { + "message": "{{input}} 所屬方", + "description": "A label for the partyness column" + }, + "loggerExportFormatList": { + "message": "清單", + "description": "Label for radio-button to pick export format" + }, + "loggerExportFormatTable": { + "message": "表格", + "description": "Label for radio-button to pick export format" + }, + "loggerExportEncodePlain": { + "message": "純文字", + "description": "Label for radio-button to pick export text format" + }, + "loggerExportEncodeMarkdown": { + "message": "Markdown", + "description": "Label for radio-button to pick export text format" + }, + "supportOpenButton": { + "message": "開啟", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportReportSpecificButton": { + "message": "發出新報告", + "description": "Text for button which open an external webpage in Support pane" + }, + "supportFindSpecificButton": { + "message": "尋找類似的報告", + "description": "A clickable link in the filter issue reporter section" + }, + "supportS1H": { + "message": "文件", + "description": "Header of 'Documentation' section in Support pane" + }, + "supportS1P1": { + "message": "欲了解 uBlock Origin 所有的功能,請閱讀 uBlock/wiki 中的文件。", + "description": "First paragraph of 'Documentation' section in Support pane" + }, + "supportS2H": { + "message": "問題與支援", + "description": "Header of 'Questions and support' section in Support pane" + }, + "supportS2P1": { + "message": "問題及其他類型的求助,可以在 /r/uBlockOrigin subreddit 獲得協助與解答。", + "description": "First paragraph of 'Questions and support' section in Support pane" + }, + "supportS3H": { + "message": "過濾器問題 / 網站被搞壞", + "description": "Header of 'Filter issues' section in Support pane" + }, + "supportS3P1": { + "message": "請到 uBlockOrigin/uAssets 議題追蹤系統回報特定網站的過濾器問題。需要 GitHub 帳號。", + "description": "First paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P2": { + "message": "特別注意:不要把其他同性質的阻擋工具跟 uBlock Origin 混用,否則可能會造成特定網站的過濾器問題。", + "description": "Second paragraph of 'Filter issues' section in Support pane" + }, + "supportS3P3": { + "message": "小提示:請確定您的過濾器清單已經更新至最新版本。我們主要用 記錄器 來分析過濾器相關問題。", + "description": "Third paragraph of 'Filter issues' section in Support pane" + }, + "supportS4H": { + "message": "錯誤報告", + "description": "Header of 'Bug report' section in Support pane" + }, + "supportS4P1": { + "message": "請到 uBlockOrigin/uBlock-issue 議題追蹤系統回報 uBlock Origin 本身的問題。需要 GitHub 帳號。", + "description": "First paragraph of 'Bug report' section in Support pane" + }, + "supportS5H": { + "message": "疑難排解資訊", + "description": "Header of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P1": { + "message": "以下是志願者嘗試幫您解決問題時,可能會用到的技術資訊:", + "description": "First paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS5P2": { + "message": "特別注意:預設情況下,潛在隱私或敏感資料會被替換掉。替換過的資訊可能會加大問題解決的難度。", + "description": "Second paragraph of 'Troubleshooting Information' section in Support pane" + }, + "supportS6H": { + "message": "回報過濾規則的問題", + "description": "Header of 'Report a filter issue' section in Support pane" + }, + "supportS6P1S1": { + "message": "請先確認是否已經有人回報過此問題,以免重複回報造成維護者的而外負擔。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S1": { + "message": "過濾器清單每天更新。請確認您的問題無法用最新的過濾器清單解決。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6P2S2": { + "message": "重新載入有問題的網頁後,驗證問題是否仍然存在。", + "description": "A paragraph in the filter issue reporter section" + }, + "supportS6URL": { + "message": "網址:", + "description": "Label for the URL of the page" + }, + "supportS6Select1": { + "message": "這個網頁…", + "description": "Label for widget to select type of issue" + }, + "supportS6Select1Option0": { + "message": "-- 挑選一種情況 --", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option1": { + "message": "顯示廣告或廣告移除後留下的天窗", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option2": { + "message": "會覆蓋內容或有其他煩人的內容", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option3": { + "message": "偵測到 uBlock Origin", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option4": { + "message": "有隱私權相關問題", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option5": { + "message": "開啟 uBlock Origin 的時候網頁運作不正常", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Select1Option6": { + "message": "開啟不想出現的分頁或視窗", + "description": "An entry in the widget used to select the type of issue" + }, + "supportS6Checkbox1": { + "message": "將網頁標記為「NSFW」(工作場所不宜)", + "description": "A checkbox to use for NSFW sites" + }, + "supportRedact": { + "message": "替換", + "description": "Text for 'Redact' button" + }, + "supportUnredact": { + "message": "不要替換", + "description": "Text for 'Unredact' button" + }, + "aboutPrivacyPolicy": { + "message": "隱私權條款", + "description": "Link to privacy policy on GitHub (English)" + }, + "aboutChangelog": { + "message": "更新日誌", + "description": "" + }, + "aboutCode": { + "message": "原始碼(GPLv3)", + "description": "English: Source code (GPLv3)" + }, + "aboutContributors": { + "message": "貢獻者", + "description": "English: Contributors" + }, + "aboutSourceCode": { + "message": "原始碼", + "description": "Link text to source code repo" + }, + "aboutTranslations": { + "message": "翻譯", + "description": "Link text to translations repo" + }, + "aboutFilterLists": { + "message": "過濾規則清單", + "description": "Link text to uBO's own filter lists repo" + }, + "aboutDependencies": { + "message": "外部相依套件(與 GPLv3 相容):", + "description": "Shown in the About pane" + }, + "aboutCDNs": { + "message": "uBO 自家的過濾規則清單由下列 CDN 免費代管:", + "description": "Shown in the About pane" + }, + "aboutCDNsInfo": { + "message": "當過濾清單需要更新時,將隨機選擇一組 CDN 連線下載", + "description": "Shown in the About pane" + }, + "aboutBackupDataButton": { + "message": "備份至檔案…", + "description": "Text for button to create a backup of all settings" + }, + "aboutBackupFilename": { + "message": "my-ublock-backup_{{datetime}}.txt", + "description": "English: my-ublock-backup_{{datetime}}.txt" + }, + "aboutRestoreDataButton": { + "message": "從檔案還原…", + "description": "English: Restore from file..." + }, + "aboutResetDataButton": { + "message": "重設為預設設定…", + "description": "English: Reset to default settings..." + }, + "aboutRestoreDataConfirm": { + "message": "您所有的設定將會被 {{time}} 的備份資料覆蓋,並將重新啟動 uBlock₀。\n\n您確定要用備份資料蓋過目前的所有設定嗎?", + "description": "Message asking user to confirm restore" + }, + "aboutRestoreDataError": { + "message": "無法讀取資料,或資料無效", + "description": "Message to display when an error occurred during restore" + }, + "aboutResetDataConfirm": { + "message": "您所有的設定都將被移除,並將重新啟動 uBlock₀。\n\n您確定要將 uBlock₀ 回復為原廠設定?", + "description": "Message asking user to confirm reset" + }, + "errorCantConnectTo": { + "message": "網路錯誤:{{msg}}", + "description": "English: Network error: {{msg}}" + }, + "subscriberConfirm": { + "message": "確定要新增下列網址至自訂過濾規則清單?\n\n標題:「{{title}}」\n網址:{{url}}", + "description": "No longer used" + }, + "subscribeButton": { + "message": "訂閱", + "description": "For the button used to subscribe to a filter list" + }, + "elapsedOneMinuteAgo": { + "message": "1 分鐘前", + "description": "English: a minute ago" + }, + "elapsedManyMinutesAgo": { + "message": "{{value}} 分鐘前", + "description": "English: {{value}} minutes ago" + }, + "elapsedOneHourAgo": { + "message": "1 小時前", + "description": "English: an hour ago" + }, + "elapsedManyHoursAgo": { + "message": "{{value}} 小時前", + "description": "English: {{value}} hours ago" + }, + "elapsedOneDayAgo": { + "message": "1 天前", + "description": "English: a day ago" + }, + "elapsedManyDaysAgo": { + "message": "{{value}} 天前", + "description": "English: {{value}} days ago" + }, + "showDashboardButton": { + "message": "顯示控制台", + "description": "Firefox/Fennec-specific: Show Dashboard" + }, + "showNetworkLogButton": { + "message": "顯示記錄器", + "description": "Firefox/Fennec-specific: Show Logger" + }, + "fennecMenuItemBlockingOff": { + "message": "關閉", + "description": "Firefox-specific: appears as 'uBlock₀ (off)'" + }, + "docblockedTitle": { + "message": "頁面已阻擋", + "description": "Used as a title for the document-blocked page" + }, + "docblockedPrompt1": { + "message": "uBlock Origin 已防止下列頁面載入:", + "description": "Used in the strict-blocking page" + }, + "docblockedPrompt2": { + "message": "因為下列過濾規則:", + "description": "Used in the strict-blocking page" + }, + "docblockedNoParamsPrompt": { + "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": "在下列清單找到:", + "description": "English: List of filter list names follows" + }, + "docblockedBack": { + "message": "返回", + "description": "English: Go back" + }, + "docblockedClose": { + "message": "關閉此視窗", + "description": "English: Close this window" + }, + "docblockedDontWarn": { + "message": "不再針對此網站作出警告", + "description": "Label for checkbox in document-blocked page" + }, + "docblockedProceed": { + "message": "停止針對 {{hostname}} 的嚴格封鎖", + "description": "English: Disable strict blocking for {{hostname}} ..." + }, + "docblockedDisableTemporary": { + "message": "暫時", + "description": "English: Temporarily" + }, + "docblockedDisablePermanent": { + "message": "永久", + "description": "English: Permanently" + }, + "docblockedDisable": { + "message": "繼續載入", + "description": "Button text to navigate to the blocked page" + }, + "cloudPush": { + "message": "匯出至雲端儲存空間", + "description": "tooltip" + }, + "cloudPull": { + "message": "從雲端儲存空間匯入", + "description": "tooltip" + }, + "cloudPullAndMerge": { + "message": "自雲端匯入,並與目前設定合併", + "description": "tooltip" + }, + "cloudNoData": { + "message": "…\n…", + "description": "" + }, + "cloudDeviceNamePrompt": { + "message": "此裝置的名稱:", + "description": "used as a prompt for the user to provide a custom device name" + }, + "advancedSettingsWarning": { + "message": "警告!修改進階設定時請自負風險。", + "description": "A warning to users at the top of 'Advanced settings' page" + }, + "genericSubmit": { + "message": "送出", + "description": "for generic 'Submit' buttons" + }, + "genericApplyChanges": { + "message": "套用變更", + "description": "for generic 'Apply changes' buttons" + }, + "genericRevert": { + "message": "還原", + "description": "for generic 'Revert' buttons" + }, + "genericBytes": { + "message": "位元組", + "description": "" + }, + "contextMenuBlockElementInFrame": { + "message": "阻擋框架中的內容…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuSubscribeToList": { + "message": "訂閱過濾規則清單…", + "description": "An entry in the browser's contextual menu" + }, + "contextMenuTemporarilyAllowLargeMediaElements": { + "message": "暫時允許大型媒體元素", + "description": "A context menu entry, present when large media elements have been blocked on the current site" + }, + "contextMenuViewSource": { + "message": "檢視原始碼…", + "description": "A context menu entry, to view the source code of the target resource" + }, + "shortcutCapturePlaceholder": { + "message": "輸入快捷鍵", + "description": "Placeholder string for input field used to capture a keyboard shortcut" + }, + "genericMergeViewScrollLock": { + "message": "切換是否啟用同步捲動", + "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" + }, + "genericCopyToClipboard": { + "message": "複製到剪貼簿", + "description": "Label for buttons used to copy something to the clipboard" + }, + "genericSelectAll": { + "message": "全選", + "description": "Label for buttons used to select all text in editor" + }, + "toggleCosmeticFiltering": { + "message": "切換是否啟用元素隱藏過濾規則", + "description": "Label for keyboard shortcut used to toggle cosmetic filtering" + }, + "relaxBlockingMode": { + "message": "放寬封鎖量模式", + "description": "Label for keyboard shortcut used to relax blocking mode" + }, + "storageUsed": { + "message": "儲存空間用量:{{value}} {{unit}}", + "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" + }, + "KB": { + "message": "KB", + "description": "short for 'kilobytes'" + }, + "MB": { + "message": "MB", + "description": "short for 'megabytes'" + }, + "GB": { + "message": "GB", + "description": "short for 'gigabytes'" + }, + "clickToLoad": { + "message": "點擊以載入", + "description": "Message used in frame placeholders" + }, + "linterMainReport": { + "message": "錯誤:{{count}}", + "description": "Summary of number of errors as reported by the linter " + }, + "unprocessedRequestTooltip": { + "message": "無法在瀏覽器啟動的時候正確過濾。請重新載入頁面來確保過濾正確。", + "description": "A warning which will appear in the popup panel if needed" + }, + "dummy": { + "message": "此條目須為最後一個", + "description": "so we dont need to deal with comma for last entry" + } +} diff --git a/src/about.html b/src/about.html new file mode 100644 index 0000000..fc98984 --- /dev/null +++ b/src/about.html @@ -0,0 +1,63 @@ + + + + + +uBlock — About + + + + + + + + +

+ + + + + + + + + + + + + diff --git a/src/advanced-settings.html b/src/advanced-settings.html new file mode 100644 index 0000000..22bee72 --- /dev/null +++ b/src/advanced-settings.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + +
+

info-circle +

+   +

+ +
+ + + + + + + + + + + + + + + + diff --git a/src/asset-viewer.html b/src/asset-viewer.html new file mode 100644 index 0000000..b30320f --- /dev/null +++ b/src/asset-viewer.html @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + +
+ + + spinner + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/background.html b/src/background.html new file mode 100644 index 0000000..63e27aa --- /dev/null +++ b/src/background.html @@ -0,0 +1,12 @@ + + + + +uBlock Origin Background Page + + + + + + + diff --git a/src/cloud-ui.html b/src/cloud-ui.html new file mode 100644 index 0000000..366cf72 --- /dev/null +++ b/src/cloud-ui.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+ + + + +
+
cog
+
+   +
+
+
+
+ + diff --git a/src/code-viewer.html b/src/code-viewer.html new file mode 100644 index 0000000..4b699fe --- /dev/null +++ b/src/code-viewer.html @@ -0,0 +1,53 @@ + + + + + +Code viewer + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/css/1p-filters.css b/src/css/1p-filters.css new file mode 100644 index 0000000..679e4b8 --- /dev/null +++ b/src/css/1p-filters.css @@ -0,0 +1,26 @@ +html { + height: 100vh; + overflow: hidden; + width: 100vw; + } +body { + display: flex; + flex-direction: column; + height: 100%; + justify-content: stretch; + overflow: hidden; + width: 100%; + } +.body { + flex-shrink: 0; + } +[data-i18n="1pTrustWarning"] { + font-weight: bold; + } +.codeMirrorContainer { + flex-grow: 1; + } +#userFilters { + text-align: left; + word-wrap: normal; + } diff --git a/src/css/3p-filters.css b/src/css/3p-filters.css new file mode 100644 index 0000000..014dd20 --- /dev/null +++ b/src/css/3p-filters.css @@ -0,0 +1,250 @@ +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } +body { + margin-bottom: 6rem; + } +#actions { + background-color: var(--surface-1); + padding: var(--default-gap-small) 0 var(--default-gap-xsmall) 0; + position: sticky; + top: 0; + z-index: 10; + } +#buttonUpdate.active { + pointer-events: none; + } +#buttonUpdate.active .fa-icon svg { + animation: spin 1s linear infinite; + transform-origin: 50%; + } + +body.updating #actions, +body.working #actions { + cursor: progress; + } +body.updating #actions button, +body.working #actions button { + pointer-events: none; + } + +.listExpander { + font-size: 18px; + padding: 0; + } +.listExpander:first-child { + justify-content: flex-start; + min-width: 20px; + } +.listExpander:not(:first-child) { + color: var(--checkbox-checked-ink); + fill: var(--checkbox-checked-ink); + } +.listExpander svg { + transform: rotate(90deg); + transform-origin: 50%; + } + +#lists .fa-icon:hover { + transform: scale(1.25); + } + +#lists .rootstats.expanded .listExpander svg { + transform: rotate(180deg); + } + +#lists .searchbar { + align-items: center; + column-gap: var(--default-gap-xxsmall); + display: inline-flex; + margin-block-start: calc(var(--font-size) * 0.75); + margin-inline-start: var(--checkbox-size); + position: relative; + } +#lists .searchbar input { + padding-inline-start: var(--default-gap-large); + } +#lists .searchbar .fa-icon { + color: var(--ink-4); + fill: var(--ink-4); + left: 4px; + position: absolute; + transform: none; + } +#lists.searchMode > .listEntries .listEntries, +#lists.searchMode > .listEntries .listEntry.searchMatch { + display: flex !important; + } +#lists.searchMode > .listEntries .listEntry { + display: none; + } +#lists.searchMode > .listEntries .listExpander { + visibility: hidden; + } + +#listsOfBlockedHostsPrompt { + cursor: pointer; + } + +#lists .listEntries { + display: flex; + flex-direction: column; + margin-inline-start: var(--checkbox-size); + } +#lists > .listEntries { + margin-inline-start: 0; + } +#lists .listEntry { + align-items: flex-start; + flex-direction: column; + margin-bottom: 0; + margin-inline-start: 0; + white-space: nowrap; + } +#lists .listEntry[data-key="user"] { + margin-top: 0; + } +#lists .listEntry > .detailbar { + column-gap: calc(var(--default-gap-xxsmall) + 2px); + display: inline-flex; + } +#lists .listEntry[data-key="user"] > .detailbar { + display: none; + } +#lists .listEntry[data-role="node"].expanded > .detailbar .listExpander svg { + transform: rotate(180deg); + } +#lists .listEntry[data-parent="root"]:not(.expanded) > .listEntries > .listEntry:not(.checked):not(.isDefault):not(.stickied) { + display: none; + } +#lists .listEntry:not([data-parent="root"]):not(.expanded) > .listEntries > .listEntry { + display: none; + } +#lists .nodestats { + align-self: flex-end; + color: var(--info0-ink); + fill: var(--info0-ink); + cursor: default; + font-size: var(--font-size-smaller); +} +#lists .iconbar { + column-gap: var(--default-gap-xxsmall); + color: var(--info0-ink); + fill: var(--info0-ink); + display: inline-flex; + flex-direction: row; + font-size: 120%; + } +#lists .iconbar a { + color: var(--info0-ink); + fill: var(--info0-ink); + } +#lists .iconbar .fa-icon { + display: none; + } +#lists .iconbar .content { + display: inline-flex; + } +#lists .iconbar a.towiki { + display: inline-flex; + } +#lists .listEntry > .detailbar .iconbar a.support { + display: inline-flex; + } +#lists .listEntry > .detailbar .iconbar a.support[href="#"] { + display: none; + } +#lists .iconbar .remove, +#lists .iconbar .unsecure, +#lists .iconbar .failed { + color: var(--info3-ink); + fill: var(--info3-ink); + cursor: pointer; + } +#lists .listEntry.external > .detailbar .iconbar .remove { + display: inline-flex; + } +#lists .listEntry > .detailbar .iconbar a.mustread { + color: var(--info1-ink); + fill: var(--info1-ink); + display: inline-flex; + } +#lists .listEntry > .detailbar .iconbar a.mustread[href="#"] { + display: none; + } +#lists .listEntry .leafstats { + align-items: flex-end; + color: var(--info0-ink); + fill: var(--info0-ink); + display: none; + font-size: var(--font-size-xsmall); + margin-inline-start: calc(var(--checkbox-size) + var(--checkbox-margin-end)); +} +#lists .listEntry > .detailbar .leafstats { + margin-inline-start: 0; + } +#lists .listEntry.checked > .leafstats, +#lists .listEntry.checked > .detailbar .leafstats { + display: inline-flex; +} +#lists .iconbar .status { + cursor: default; + display: none; +} +#lists .listEntry.checked.unsecure > .detailbar .iconbar .unsecure { + display: inline-flex; + } +#lists .listEntry.failed > .detailbar .iconbar .failed { + display: inline-flex; + } +#lists .iconbar .cache { + cursor: pointer; + } +#lists .listEntry.checked.cached:not(.obsolete) > .detailbar .iconbar .cache { + display: inline-flex; + } +#lists .listEntry.cached.recent:not(.obsolete) > .detailbar .iconbar .cache { + color: var(--dashboard-happy-green); + fill: var(--dashboard-happy-green); + } +#lists .iconbar .obsolete { + color: var(--info2-ink); + fill: var(--info2-ink); + } +body:not(.updating) #lists .listEntry.checked.obsolete > .detailbar .iconbar .obsolete { + display: inline-flex; + } +#lists .iconbar .updating { + transform-origin: 50%; + } +body.updating #lists .listEntry.checked.obsolete > .detailbar .iconbar .updating { + animation: spin 1s steps(8) infinite; + display: inline-flex; + } + +#lists .listEntry.toRemove .checkbox { + visibility: hidden; + } +#lists .listEntry.toRemove .listname { + text-decoration: line-through; + } + +#lists .listEntry[data-role="import"].expanded .listExpander svg { + transform: rotate(180deg); + } +#lists .listEntry[data-role="import"].expanded textarea { + visibility: visible; + } +#lists .listEntry[data-role="import"] textarea { + border: 1px solid #ccc; + box-sizing: border-box; + display: block; + font-size: smaller; + height: 6em; + margin: 0; + resize: vertical; + visibility: hidden; + white-space: pre; + width: 100%; + } diff --git a/src/css/about.css b/src/css/about.css new file mode 100644 index 0000000..8c3afcd --- /dev/null +++ b/src/css/about.css @@ -0,0 +1,3 @@ +body { + margin-bottom: 6rem; + } diff --git a/src/css/advanced-settings.css b/src/css/advanced-settings.css new file mode 100644 index 0000000..c67e750 --- /dev/null +++ b/src/css/advanced-settings.css @@ -0,0 +1,26 @@ +html { + height: 100vh; + overflow: hidden; + width: 100vw; + } +body { + display: flex; + flex-direction: column; + height: 100%; + justify-content: stretch; + overflow: hidden; + width: 100%; + } +.body { + flex-shrink: 0; + } +.codeMirrorContainer { + flex-grow: 1; + } +#advancedSettings { + border: var(--default-gap-xxsmall) solid var(--surface-2); + text-align: left; + } +.CodeMirror-wrap pre { + word-break: break-all; + } diff --git a/src/css/asset-viewer.css b/src/css/asset-viewer.css new file mode 100644 index 0000000..8b6f1da --- /dev/null +++ b/src/css/asset-viewer.css @@ -0,0 +1,79 @@ +/** + uBlock Origin - a browser extension to block requests. + 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 +*/ + +body { + border: 0; + display: flex; + flex-direction: column; + height: 100vh; + margin: 0; + overflow: hidden; + padding: 0; + width: 100vw; + } +#subscribe { + display: flex; + flex-shrink: 0; + justify-content: space-between; + max-height: 6em; + padding-inline-end: 0.5em; + } +#subscribe.hide { + display: none; + } +.logo { + background-color: #fffa; + flex-shrink: 0; + width: 2em; + } +#subscribePrompt { + display: inline-flex; + flex-direction: column; + padding: 0.5em; + } +#subscribePrompt > span { + font-weight: bold; + } +#subscribePrompt > a { + font-size: 14px; + word-break: break-all; + } +#subscribe > button { + align-self: center; + } +#subscribe > .fa-icon { + color: var(--accent-ink-1); + fill: var(--accent-ink-1); + font-size: 20px; + } +body.loading #subscribe > button, +body:not(.loading) #subscribe > .fa-icon { + display: none; + } +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } +body.loading #subscribe > .fa-icon > svg { + animation: spin 1s steps(8) infinite; + } +#content { + flex-grow: 1; + } diff --git a/src/css/click2load.css b/src/css/click2load.css new file mode 100644 index 0000000..b6d3924 --- /dev/null +++ b/src/css/click2load.css @@ -0,0 +1,53 @@ +/** + uBlock Origin - a browser extension to block requests. + 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 +*/ + +body { + align-items: center; + border: 1px solid var(--ubo-red); + box-sizing: border-box; + display: flex; + flex-direction: column; + height: 100vh; + padding: 0 2px; + position: relative; + width: 100vw; + } + +.logo { + left: 0; + padding: 2px 1px; + position: absolute; + top: 0; + } + +#frameURL { + font-family: monospace; + font-size: 90%; + overflow-y: auto; + word-break: break-all; + } +#frameURL > a { + font-size: 1rem; + } + +#clickToLoad { + cursor: default; + margin-bottom: 1em; + } diff --git a/src/css/cloud-ui.css b/src/css/cloud-ui.css new file mode 100644 index 0000000..1891a1d --- /dev/null +++ b/src/css/cloud-ui.css @@ -0,0 +1,104 @@ +#cloudWidget { + background-color: var(--surface-2); + margin: 0.5em 0; + min-width: max-content; + position: relative; + } +#cloudWidget.hide { + display: none; + } +#cloudWidget div { + display: flex; + } +#cloudToolbar { + align-items: flex-start; + flex-wrap: nowrap; + justify-content: space-between; + } +#cloudToolbar > div:first-of-type { + margin: 0.5em; + } +#cloudToolbar button { + padding: 0 0.25em; + position: relative; + } +#cloudToolbar button .fa-icon { + font-size: 180%; + } +#cloudToolbar button[disabled] { + visibility: hidden; + } +#cloudToolbar button.error { + color: var(--info3-ink); + } +#cloudPullAndMerge { + margin-left: 0.25em; + } +#cloudPullAndMerge > span:nth-of-type(2) { + font-size: 90%; + position: absolute; + right: 0; + top: 0; + } +#cloudInfo { + flex-shrink: 0; + font-size: 90%; + margin: 0 1em; + overflow: hidden; + padding: 0; + white-space: pre-line; + } +#cloudCapacity { + background-color: var(--surface-3); + height: 4px; + } +#cloudCapacity > div { + background-color: var(--cloud-total-used-surface); + } +#cloudCapacity > div > div { + background-color: var(--cloud-used-surface); + } +#cloudError { + color: var(--info3-ink); + flex-grow: 1; + flex-shrink: 2; + font-size: small; + margin: 0 0.5em 0.5em 0.5em; + } +#cloudError:empty { + display: none; + } +#cloudCog { + color: var(--ink-3); + fill: var(--ink-3); + cursor: pointer; + font-size: 110%; + justify-content: flex-end; + padding: 0.4em; + } +#cloudCog:hover { + color: inherit; + fill: inherit; + } +#cloudWidget #cloudOptions { + align-items: center; + background-color: var(--surface-1); + bottom: 2px; + display: none; + font-size: small; + padding: 0.5em; + position: absolute; + right: 2px; + text-align: center; + top: 2px; + z-index: 10; + } +#cloudWidget #cloudOptions label { + display: inline-flex; + flex-direction: column; + align-items: flex-start; + } +#cloudWidget #cloudOptions.show { + display: flex; + white-space: nowrap; + } diff --git a/src/css/code-viewer.css b/src/css/code-viewer.css new file mode 100644 index 0000000..774fa69 --- /dev/null +++ b/src/css/code-viewer.css @@ -0,0 +1,67 @@ +body { + border: 0; + display: flex; + flex-direction: column; + height: 100vh; + margin: 0; + overflow: hidden; + padding: 0; + width: 100vw; + } +#header { + background-color: var(--cm-gutter-surface); + border-bottom: 1px solid var(--surface-1); + padding: var(--default-gap-xsmall); + position: relative; + z-index: 1000000; + } +#header input[type="url"] { + box-sizing: border-box; + font-size: var(--font-size-smaller); + width: 100%; + } +#header:focus-within #pastURLs { + display: flex; + } +#currentURL { + display: flex; + gap: 0.5rem; + } +#currentURL > .fa-icon { + padding: 0 0.5rem; + } +#currentURL > .fa-icon:hover { + background-color: var(--surface-3); + } +#pastURLs { + background-color: var(--surface-0); + border: 1px solid var(--border-1); + display: none; + flex-direction: column; + font-size: var(--font-size-smaller); + position: absolute; + } +#pastURLs > span { + cursor: pointer; + overflow: hidden; + padding: 2px 4px; + text-overflow: ellipsis; + white-space: nowrap; + width: 75vw; + } +#pastURLs > span.selected { + font-weight: bold; + } +#pastURLs > span:hover { + background-color: var(--surface-1); + } +#content { + flex-grow: 1; + } + +.cm-href { + cursor: pointer; + } +.cm-href:hover { + text-decoration: underline; + } diff --git a/src/css/codemirror.css b/src/css/codemirror.css new file mode 100644 index 0000000..2d15bf8 --- /dev/null +++ b/src/css/codemirror.css @@ -0,0 +1,327 @@ +.codeMirrorContainer { + line-height: 1.25; + overflow: hidden; + position: relative; + } +.CodeMirror { + background-color: var(--surface-0); + box-sizing: border-box; + color: var(--ink-1); + flex-grow: 1; + font-size: var(--monospace-size); + height: 100%; + width: 100%; + } +.CodeMirror-cursor { + border-color: var(--cm-cursor); + } +.CodeMirror-selected { + background-color: var(--cm-selection-surface); + } +.CodeMirror-focused .CodeMirror-selected { + background-color: var(--cm-selection-focused-surface); + } +.CodeMirror-foldmarker { + color: var(--cm-foldmarker-ink); + cursor: pointer; + font-family: sans-serif; + font-weight: bold; + } +.CodeMirror-foldgutter-folded::after { + content: '\25B6'; + } +.CodeMirror-foldgutter-open::after { + content: '\25BC'; + } +.CodeMirror-gutters { + background-color: var(--cm-gutter-surface); + border-color: var(--cm-gutter-border); + } +.CodeMirror-line::selection, +.CodeMirror-line > span::selection, +.CodeMirror-line > span > span::selection { + background-color: var(--cm-selection-focused-surface); + } +.CodeMirror-linenumber { + color: var(--cm-gutter-ink); + } +.CodeMirror-lines { + padding-bottom: 6rem; + } +.CodeMirror-matchingbracket { + color: unset; + } +.CodeMirror-matchingbracket { + background-color: var(--cm-matchingbracket) !important; + color: inherit !important; + font-weight: bold; + } + +.CodeMirror-search-match { + background: none; + background-color: var(--cm-search-match-surface); + border: 0; + opacity: 1; + } + +/* For when panels are used */ +.codeMirrorContainer > div:not([class^="CodeMirror"]) { + display: flex; + flex-direction: column; + height: 100%; + } + +.codeMirrorContainer.codeMirrorBreakAll .CodeMirror-wrap pre { + word-break: break-all; + } + +.cm-theme-override .cm-s-default .cm-comment { + color: var(--sf-comment-ink); + } +.cm-theme-override .cm-s-default .cm-def { + color: var(--sf-def-ink); + } +.cm-theme-override .cm-s-default .cm-directive { + color: var(--sf-directive-ink); + font-weight: bold; + } +.cm-theme-override .cm-s-default .cm-error { + color: inherit; + } +.cm-theme-override .cm-s-default .cm-error, +.CodeMirror-linebackground.error { + background-color: var(--sf-error-surface); + text-decoration: var(--sf-error-ink) dashed underline; + } +.cm-theme-override .cm-s-default .cm-link { + text-decoration: none; + } +.cm-theme-override .cm-s-default .cm-link:hover { + color: var(--link-ink); + } +.cm-theme-override .cm-s-default .cm-keyword { + color: var(--sf-keyword-ink); + } +.cm-theme-override .cm-s-default .cm-negative { + color: var(--cm-negative); + } +.cm-theme-override .cm-s-default .cm-positive { + color: var(--cm-positive); + } +.cm-theme-override .cm-s-default .cm-notice { + text-decoration-color: var(--sf-notice-ink); + text-decoration-style: solid; + text-decoration-line: underline; + } +.cm-theme-override .cm-s-default .cm-unicode { + text-decoration-color: var(--sf-unicode-ink); + text-decoration-style: dashed; + text-decoration-line: underline; + } +.cm-theme-override .cm-s-default .cm-tag { + color: var(--sf-tag-ink); + } +.cm-theme-override .cm-s-default .cm-value { + color: var(--sf-value-ink); + } +.cm-theme-override .cm-s-default .cm-variable { + color: var(--sf-variable-ink); + } +.cm-theme-override .cm-s-default .cm-warning { + background-color: var(--sf-warning-surface); + text-decoration: underline var(--sf-warning-ink); + } +.cm-theme-override .cm-s-default .cm-readonly { + color: var(--sf-readonly-ink); + } + +/* Rules */ +.cm-s-default .cm-allowrule { + color: var(--df-allow-ink); + font-weight: bold; + } +.cm-s-default .cm-blockrule { + color: var(--df-block-ink); + font-weight: bold; + } +.cm-s-default .cm-nooprule { + color: var(--df-noop-ink); + font-weight: bold; + } +.cm-s-default .cm-sortkey { + color: var(--sf-keyword-ink); + } + +.cm-search-widget { + align-items: center; + background-color: var(--cm-gutter-surface); + border-bottom: 1px solid var(--cm-gutter-border); + cursor: default; + direction: ltr; + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + justify-content: space-between; + padding: var(--default-gap-xsmall); + row-gap: var(--default-gap-xsmall); + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + z-index: 1000; + } +.cm-search-widget > * { + flex-grow: 1; + } +.cm-search-widget > :last-child { + text-align: end; + } + +.cm-search-widget-input { + display: inline-flex; + flex-grow: 1; + } +.cm-search-widget .fa-icon { + fill: var(--cm-gutter-ink); + font-size: 140%; + } +.cm-search-widget .fa-icon:not(.fa-icon-ro):hover { + fill: var(--ink-1); + } +.cm-search-widget-input input { + border: 1px solid var(--cm-gutter-ink); + display: inline-flex; + flex-grow: 1; + max-width: 16em; + } +.cm-search-widget-count { + align-items: center; + display: inline-flex; + flex-grow: 0; + font-size: var(--font-size-smaller); + min-width: 6em; + visibility: hidden; + } +.cm-search-widget[data-query] .cm-search-widget-count { + visibility: visible; + } +.cm-search-widget[data-query] .cm-search-widget-count:empty { + visibility: hidden; + } +.cm-search-widget .cm-search-widget-button:hover { + color: #000; + } +.cm-search-widget .sourceURL[href=""] { + visibility: hidden; + } +:root.mobile .cm-search-widget .sourceURL[href=""] { + display: none; + } + +.cm-linter-widget { + align-items: center; + display: none; + flex-grow: 1; + } +.cm-linter-widget:not([data-lint="0"]) { + display: inline-flex; + } +.cm-linter-widget .cm-linter-widget-count { + color: var(--accent-surface-1); + fill: var(--accent-surface-1); + font-size: var(--font-size-smaller); + } + +.cm-searching.cm-overlay { + background-color: var(--cm-searching-surface) !important; + border: 0; + color: var(--cm-searching-ink) !important; + } + +.CodeMirror-merge { + border-color: var(--cm-gutter-border); + } +.CodeMirror-merge-copy, +.CodeMirror-merge-copy-reverse { + color: var(--cm-merge-copy-ink); + } +.CodeMirror-merge-l-chunk { + background-color: var(--cm-merge-chunk-surface); + } +.CodeMirror-merge-l-chunk-start, +.CodeMirror-merge-l-chunk-end { + border-color: var(--cm-merge-chunk-border); + } +.CodeMirror-merge-l-deleted { + background-image: none; + } +.CodeMirror-merge-l-inserted { + background-image: none; + } +/* This probably needs to be added to CodeMirror repo */ +.CodeMirror-merge-gap { + background-color: var(--cm-gutter-surface); + border-color: var(--cm-gutter-border); + vertical-align: top; + } +.CodeMirror-merge-scrolllock { + color: var(--cm-merge-copy-ink); + } +.CodeMirror-merge-spacer { + background-color: var(--cm-merge-chunk-surface); + } + +.CodeMirror-hints { + z-index: 10000; + } + +/* Must appear after other background color declarations to be sure it + * overrides them + * */ +.CodeMirror-activeline-background { + background-color: var(--cm-active-line); + } + +.CodeMirror-lintmarker { + height: calc(var(--font-size) - 2px); + margin-top: 1px; + position: relative; + } +.CodeMirror-lintmarker > * { + position: absolute; + } +.CodeMirror-lintmarker[data-error="y"] { + background-color: var(--sf-error-ink); + } +.CodeMirror-lintmarker .msg { + background-color: var(--surface-0); + border: 1px solid var(--sf-error-ink); + color: var(--ink-1); + display: none; + filter: drop-shadow(2px 2px 4px #0008); + left: 100%; + padding: var(--default-gap-xsmall); + top: -2px; + white-space: pre; + } +.CodeMirror-lintmarker svg { + height: 70%; + left: 15%; + top: 15%; + width: 70%; + } +.CodeMirror-lintmarker[data-error="y"] svg { + display: none; + } +.CodeMirror-lintmarker[data-fold="start"] { + fill: var(--cm-foldmarker-ink); + } +.CodeMirror-lintmarker[data-fold="start"].folded svg { + transform: rotate(-90deg); + } +.CodeMirror-lintmarker[data-fold="end"] { + fill: var(--border-2); + } +.CodeMirror-lintmarker[data-error="y"]:hover > span, +.CodeMirror-lintmarker[data-error="y"] > span:hover { + display: initial; + } diff --git a/src/css/common.css b/src/css/common.css new file mode 100644 index 0000000..1a8ba0b --- /dev/null +++ b/src/css/common.css @@ -0,0 +1,347 @@ +@charset "UTF-8"; +/* https://protocol.mozilla.org/assets/docs/css/protocol.css */ +@font-face { + font-family: Inter; + font-style: normal; + font-weight: normal; + src: url('fonts/Inter/Inter-Regular.woff2') format('woff2'); +} +@font-face { + font-family: Inter; + font-style: normal; + font-weight: 600; + src: url('fonts/Inter/Inter-SemiBold.woff2') format('woff2'); +} +@font-face { + font-family: Metropolis; + font-style: normal; + font-weight: normal; + src: url('fonts/Metropolis/Metropolis-Regular.woff2') format('woff2'); +} +@font-face { + font-family: Metropolis; + font-style: normal; + font-weight: 600; + src: url('fonts/Metropolis/Metropolis-SemiBold.woff2') format('woff2'); +} + +/** + Common uBO spacing. + Ref: https://github.com/uBlockOrigin/uBlock-issues/issues/1005 +*/ +:root { + --default-gap-xxlarge: 40px; + --default-gap-xlarge: 32px; + --default-gap-large: 24px; + --default-gap: 16px; + --default-gap-small: 12px; + --default-gap-xsmall: 8px; + --default-gap-xxsmall: 4px; + } + +/* Common uBO styles */ +body { + background-color: var(--surface-1); + border: 0; + box-sizing: border-box; + color: var(--ink-1); + fill: var(--ink-1); + font-family: var(--font-family); + font-size: var(--font-size); + line-height: 1.5; + margin: 0; + padding: 0; + } +a { + color: var(--link-ink); + fill: var(--link-ink); + } +a:hover { + color: var(--link-hover-ink); + fill: var(--link-hover-ink); + } +code, .code { + background-color: var(--surface-2); + font-family: monospace; + font-size: var(--monospace-size); + padding: 2px 4px; + } +hr { + border: 0; + border-top: 1px solid var(--surface-2); + margin: 1em 0; + } +textarea { + font-size: 90%; + } +button { + align-items: center; + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + border: 0; + border-radius: var(--button-border-radius); + background-color: var(--button-surface); + color: var(--button-ink); + display: inline-flex; + fill: var(--button-ink); + font-size: max(calc(var(--font-size) * 0.875), 14px); + justify-content: center; + min-height: 36px; + padding: 0 var(--font-size); + position: relative; + vertical-align: middle; + } +button.vflex { + height: 100%; + min-height: unset; + padding-bottom: 0; + padding-top: 0; + } +button > .hover { + background-color: var(--elevation-up-surface); + border-radius: var(--button-border-radius); + height: 100%; + left: 0; + opacity: 0; + pointer-events: none; + position: absolute; + top: 0; + width: 100%; + z-index: 100; + } +button:not(.disabled):not([disabled]):hover > .hover { + opacity: var(--elevation-up1-opacity); + } +button.notext:not(.disabled):not([disabled]):hover > .hover { + opacity: var(--elevation-up2-opacity); + } +button.active { + } +button.disabled, +button[disabled] { + background-color: var(--button-disabled-surface); + color: var(--button-ink); + fill: var(--button-ink); + filter: var(--button-disabled-filter); + pointer-events: none; + } +button.preferred:not(.disabled):not([disabled]) { + background-color: var(--button-preferred-surface); + color: var(--button-preferred-ink); + fill: var(--button-preferred-ink); + } +button.preferred:not(.disabled):not([disabled]):hover > .hover { + background-color: var(--elevation-down-surface); + opacity: var(--elevation-down1-opacity); + } +button.iconified.notext { + background-color: transparent; + } +button.iconified > .fa-icon { + font-size: 120%; + padding-left: 0; + padding-right: 0; + } +button.iconified > .fa-icon + [data-i18n] { + padding-right: 0; + padding-left: 0.4em; + } +body[dir="rtl"] button.iconified > .fa-icon + [data-i18n] { + padding-right: 0.4em; + padding-left: 0; + } +label { + align-items: center; + display: inline-flex; + position: relative; + } +section.notice { + background-color: var(--notice-surface); + box-shadow: var(--notice-surface-shadow); + color: var(--notice-ink); + } +:root:not(.classic) section.notice a { + color: var(--surface-2); + } + +/** + Checkbox design borrowed from: + - https://material.io/components/selection-controls + Motivation: + - To comply with design suggestions to make uBO comply with + Firefox Preview design guidelines. + - To have a single checkbox design across all platforms. +*/ +.checkbox { + box-sizing: border-box; + display: inline-flex; + flex-shrink: 0; + height: var(--checkbox-size); + margin: 0; + margin-inline-end: var(--checkbox-margin-end); + -webkit-margin-end: var(--checkbox-margin-end); + position: relative; + width: var(--checkbox-size); + } +label:hover .checkbox:not([disabled]) { + background-color: var(--surface-2); + } +.checkbox > input[type="checkbox"] { + box-sizing: border-box; + height: 100%; + margin: 0; + min-width: var(--checkbox-size); + opacity: 0; + position: absolute; + width: 100%; + } +.checkbox > input[type="checkbox"] + svg { + background-color: transparent; + border: 2px solid var(--checkbox-ink); + border-radius: 2px; + box-sizing: border-box; + fill: none; + height: 100%; + pointer-events: none; + position: absolute; + stroke: none; + stroke-width: 3.12px; + width: 100%; + } +.checkbox > input[type="checkbox"]:checked + svg { + background-color: var(--checkbox-checked-ink); + border-color: var(--checkbox-checked-ink); + stroke: var(--surface-1); + } +.checkbox[disabled], +.checkbox[disabled] ~ span { + filter: var(--checkbox-disabled-filter); + } +.checkbox.partial > input[type="checkbox"]:checked + svg { + background-color: var(--surface-1); + border-color: var(--checkbox-checked-ink); + stroke: var(--checkbox-checked-ink); + } + +.radio { + --margin-end: calc(var(--font-size) * 0.75); + box-sizing: border-box; + display: inline-flex; + flex-shrink: 0; + height: calc(var(--checkbox-size) + 2px); + margin: 0; + margin-inline-end: var(--margin-end); + -webkit-margin-end: var(--margin-end); + position: relative; + width: calc(var(--checkbox-size) + 2px); + } +.radio > input[type="radio"] { + box-sizing: border-box; + height: 100%; + margin: 0; + min-width: var(--checkbox-size); + opacity: 0; + position: absolute; + width: 100%; + } +.radio > input[type="radio"] + svg { + background-color: transparent; + box-sizing: border-box; + height: 100%; + pointer-events: none; + position: absolute; + width: 100%; + } +.radio > input[type="radio"] + svg > path { + fill: var(--checkbox-ink); + } +.radio > input[type="radio"] + svg > circle { + fill: transparent; + } +label:hover .radio > input[type="radio"]:not(:checked) + svg > circle { + fill: var(--surface-3); + } +.radio > input[type="radio"]:checked + svg > path, +.radio > input[type="radio"]:checked + svg > circle { + fill: var(--checkbox-checked-ink); + } + +select { + padding: 2px; + } + +.hidden { + display: none; + height: 0; + visibility: hidden; + width: 0; + } +.subtil { + color: var(--subtil-ink); + cursor: default; + opacity: 66%; + } +.fieldset { + margin: var(--font-size); + } +.fieldset-header { + color: var(--fieldset-header-ink); + font-size: 14px; + font-weight: 600; + letter-spacing: 0.5px; + } +.ul { + margin: 1em 0; + } +.li { + align-items: center; + display: flex; + margin: calc(var(--font-size) * 0.75) 0; + } +.liul { + margin: 0.5em 0; + margin-inline-start: 2em; + -webkit-margin-start: 2em; + } +@media (max-width: 640px) { + button.iconified > .fa-icon { + font-size: 1.2rem; + padding: 0; + } + button.iconified > [data-i18n] { + display: none; + } + } + +.countryFlag { + height: var(--font-size); + position: relative; + top: calc(var(--font-size) / 7); + max-width: calc(var(--font-size) * 1.5); + } + +.logo { + align-items: center; + display: inline-flex; + padding: 0 0.5em; + width: 1.25em; + } +.logo > img { + width: 100%; + } + +/* high dpi devices */ +:root.hidpi button { + font-family: Metropolis, sans-serif; + font-weight: 600; + letter-spacing: 0.5px; + } +:root.hidpi .fieldset-header { + font-family: Metropolis, sans-serif; + } + +/* touch-screen devices */ +:root.mobile label { + flex-grow: 1 + } diff --git a/src/css/dashboard-common.css b/src/css/dashboard-common.css new file mode 100644 index 0000000..261aa9a --- /dev/null +++ b/src/css/dashboard-common.css @@ -0,0 +1,55 @@ +body > div.body { + padding: 0 0.5em; + } +h2, h3 { + margin: 1em 0; + } +h2 { + font-size: 18px; + } +h3 { + font-size: 16px; + } +a { + text-decoration: none; + } +.fa-icon.info { + color: var(--info0-ink); + fill: var(--info0-ink); + font-size: 115%; + } +.fa-icon.info:hover { + transform: scale(1.25); + } +.fa-icon.info.important { + color: var(--info2-ink); + fill: var(--info2-ink); + } +.info.very-important { + color: var(--info3-ink); + fill: var(--info3-ink); + } +input[type="number"] { + width: 5em; + } +@media (max-height: 640px), (max-height: 800px) and (max-width: 480px) { + .body > p, + .body > ul { + margin: 0.5em 0; + } + .vverbose { + display: none !important; + } + } +/** + On mobile device, the on-screen keyboard may take up + so much space that it overlaps the content being edited. + The rule below makes it possible to scroll the edited + content within view. +*/ +:root.mobile { + overflow: auto; + } +:root.mobile body { + min-height: 600px; + } diff --git a/src/css/dashboard.css b/src/css/dashboard.css new file mode 100644 index 0000000..ba02d97 --- /dev/null +++ b/src/css/dashboard.css @@ -0,0 +1,115 @@ +html, body { + display: flex; + flex-direction: column; + height: 100vh; + justify-content: stretch; + overflow: hidden; + position: relative; + width: 100vw; + } +body.notReady { + display: none; + } +#dashboard-nav { + border: 0; + border-bottom: 1px solid var(--border-1); + display: flex; + flex-shrink: 0; + flex-wrap: wrap; + overflow-x: hidden; + padding: 0; + position: sticky; + top: 0; + width: 100%; + z-index: 10; + } +.tabButton { + background-color: transparent; + border: 0; + border-bottom: 3px solid transparent; + border-radius: 0; + color: var(--dashboard-tab-ink); + fill: var(--dashboard-tab-ink); + font-family: var(--font-family); + font-size: var(--font-size); + padding: 0.7em 1.4em calc(0.7em - 3px); + text-decoration: none; + white-space: nowrap; + } +.tabButton:focus { + outline: 0; + } +/* + * TODO: support keyboard-driven navigation + * +.tabButton:not(:active):focus { + background-color: var(--dashboard-tab-focus-surface); + } + */ +.tabButton.selected { + background-color: var(--dashboard-tab-active-surface); + border-bottom: 3px solid var(--dashboard-tab-active-ink); + color: var(--dashboard-tab-active-ink); + fill: var(--dashboard-tab-active-ink); + } +iframe { + background-color: transparent; + border: 0; + flex-grow: 1; + margin: 0; + padding: 0; + width: 100%; + } +#unsavedWarning { + display: none; + left: 0; + position: absolute; + width: 100%; + z-index: 20; + } +#unsavedWarning.on { + display: initial; + } +#unsavedWarning > div:first-of-type { + padding: 0.5em; + } +#unsavedWarning > div:last-of-type { + height: 100vh; + position: absolute; + width: 100vw; + } + +body .tabButton[data-pane="no-dashboard.html"] { + display: none; + } +body.noDashboard #dashboard-nav { + display: none; + } + +/* high dpi devices */ +:root.hidpi .tabButton { + font-family: Metropolis, sans-serif; + font-weight: 600; + letter-spacing: 0.5px; + } + +/* hover-able devices */ +:root.desktop .tabButton { + cursor: default; + } +:root.desktop .tabButton:not(.selected) { + cursor: pointer; + } +:root.desktop .tabButton:not(.selected):hover { + background-color: var(--dashboard-tab-hover-surface); + border-bottom-color: var(--dashboard-tab-hover-border); + } + +/* touch-screen devices */ +:root.mobile #dashboard-nav { + flex-wrap: nowrap; + overflow-x: auto; + } +:root.mobile #dashboard-nav .logo { + display: none; + } diff --git a/src/css/devtools.css b/src/css/devtools.css new file mode 100644 index 0000000..425aac4 --- /dev/null +++ b/src/css/devtools.css @@ -0,0 +1,22 @@ +html { + height: 100vh; + overflow: hidden; + width: 100vw; + } +body { + display: flex; + flex-direction: column; + height: 100%; + justify-content: stretch; + overflow: hidden; + width: 100%; + } +.body { + flex-shrink: 0; + } +.codeMirrorContainer { + flex-grow: 1; + } +#console { + text-align: left; + } diff --git a/src/css/document-blocked.css b/src/css/document-blocked.css new file mode 100644 index 0000000..25dd204 --- /dev/null +++ b/src/css/document-blocked.css @@ -0,0 +1,146 @@ +/** + uBlock Origin - a browser extension to block requests. + Copyright (C) 2018-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 +*/ + +body { + display: flex; + padding: var(--default-gap-xxlarge) var(--default-gap-small); + justify-content: center; + } +:root.mobile body { + padding: var(--default-gap-small); + } + +#rootContainer { + width: min(100vw, 640px); + } +#rootContainer > * { + margin: 0 0 var(--default-gap-xxlarge) 0; + } + +a { + text-decoration: none; + } +.code { + font-size: 13px; + word-break: break-all; + } +#warningSign { + width: 100%; + } +#warningSign > a { + font-size: 96px; + } +#theURL { + color: var(--ink-2); + padding: 0; + } +#theURL > * { + margin: 0; + } +#theURL > p { + position: relative; + z-index: 10; + } +#theURL #toggleParse { + background-color: transparent; + top: 100%; + box-sizing: border-box; + color: var(--ink-3); + fill: var(--ink-3); + cursor: pointer; + font-size: 1.2rem; + padding: var(--default-gap-xxsmall); + position: absolute; + transform: translate(0, -50%); + } +#theURL:not(.collapsed) #toggleParse > span:first-of-type { + display: none; + } +#theURL.collapsed #toggleParse > span:last-of-type { + display: none; + } +body[dir="ltr"] #toggleParse { + right: 0; + } +body[dir="rtl"] #toggleParse { + left: 0; + } +#theURL > p:hover #toggleParse { + transform: translate(0, -50%) scale(1.15); + } +#parsed { + background-color: var(--surface-1); + border: 4px solid var(--surface-2); + font-size: small; + overflow-x: auto; + padding: var(--default-gap-xxsmall); + text-align: initial; + text-overflow: ellipsis; + } +#theURL.collapsed > #parsed { + display: none; + } +#parsed ul, #parsed li { + list-style-type: none; + } +#parsed li { + white-space: nowrap; + } +#parsed span { + display: inline-block; + } +#parsed span:first-of-type { + font-weight: bold; + } + +#whyex a { + white-space: nowrap; +} +#whyex ul { + display: flex; + flex-direction: column; + margin: 0; + padding-inline-start: var(--default-gap-xsmall); + } + +#actionContainer { + display: flex; + justify-content: space-between; + } +:root.mobile #actionContainer { + justify-content: center; + display: flex; + flex-direction: column; + } +#actionContainer > button { + margin-bottom: 2rem + } + +.filterList { + display: flex; +} +.filterList .filterListSupport[href=""] { + display: none; + } + +/* Small-screen devices */ +:root.mobile button { + width: 100%; + } diff --git a/src/css/dom-inspector.css b/src/css/dom-inspector.css new file mode 100644 index 0000000..71ba348 --- /dev/null +++ b/src/css/dom-inspector.css @@ -0,0 +1,40 @@ +html#ublock0-inspector, +#ublock0-inspector body { + background: transparent; + box-sizing: border-box; + height: 100vh; + margin: 0; + overflow: hidden; + width: 100vw; +} +#ublock0-inspector :focus { + outline: none; +} +#ublock0-inspector svg { + box-sizing: border-box; + height: 100%; + left: 0; + pointer-events: none; + position: fixed; + top: 0; + width: 100%; +} +#ublock0-inspector svg > path { + stroke-width: 1px; + } +#ublock0-inspector svg > path:nth-of-type(1) { + fill: rgba(255,0,0,0.2); + stroke: #F00; +} +#ublock0-inspector svg > path:nth-of-type(2) { + fill: rgba(0,255,0,0.2); + stroke: #0F0; +} +#ublock0-inspector svg > path:nth-of-type(3) { + fill: rgba(255,0,0,0.2); + stroke: #F00; +} +#ublock0-inspector svg > path:nth-of-type(4) { + fill: rgba(0,0,255,0.1); + stroke: #00F; +} diff --git a/src/css/dyna-rules.css b/src/css/dyna-rules.css new file mode 100644 index 0000000..35e0f8c --- /dev/null +++ b/src/css/dyna-rules.css @@ -0,0 +1,79 @@ +html { + height: 100vh; + overflow: hidden; + width: 100vw; + } +body { + display: flex; + flex-direction: column; + height: 100%; + justify-content: stretch; + overflow: hidden; + width: 100%; + } +.body { + flex-shrink: 0; + } +#diff { + border: 0; + white-space: nowrap; +} +#diff .tools > * { + margin-bottom: 1em; + } +#diff .ruleActions { + border: 0; + box-sizing: border-box; + display: inline-block; + padding: 0; + text-align: center; + vertical-align: top; + width: 50%; + white-space: nowrap; + } +#diff .ruleActions .fieldset-header { + margin: 0.5em 0; + } + +#ruleFilter { + align-items: center; + background-color: var(--surface-2); + direction: ltr; + display: flex; + justify-content: center; + padding: 0.5em 0; + } +#ruleFilter #diffCollapse { + padding: 0 0.5em; + font-size: 150%; + } +#ruleFilter #diffCollapse.active { + transform: scale(1, -1); + } + +.codeMirrorContainer { + flex-grow: 1; + } +.codeMirrorContainer .CodeMirror { + background-color: var(--surface-1); + } +.CodeMirror-merge, .CodeMirror-merge-pane, .CodeMirror-merge .CodeMirror { + box-sizing: border-box; + height: 100%; + } +body.editing .CodeMirror-merge-copy, +body.editing .CodeMirror-merge-copy-reverse { + display: none; + } +body.editing .CodeMirror-merge-editor .CodeMirror { + background-color: var(--surface-0); + } +body[dir="rtl"] .CodeMirror-merge-pane-rightmost { + right: unset; + left: 0; +} + +/* mobile devices */ +:root.mobile #diff .tools { + overflow: auto; + } diff --git a/src/css/epicker-ui.css b/src/css/epicker-ui.css new file mode 100644 index 0000000..d09e1ef --- /dev/null +++ b/src/css/epicker-ui.css @@ -0,0 +1,270 @@ +html#ublock0-epicker, +#ublock0-epicker body { + background: transparent; + cursor: not-allowed; + height: 100vh; + margin: 0; + overflow: hidden; + width: 100vw; +} +#ublock0-epicker :focus { + outline: none; +} +#ublock0-epicker aside { + background-color: var(--surface-1); + border: 1px solid var(--border-2); + bottom: 2px; + box-sizing: border-box; + cursor: default; + display: none; + max-height: calc(100vh - 4px); + max-width: 36rem; + min-width: 24rem; + overflow-y: auto; + padding: 4px; + position: fixed; + right: 2px; + width: calc(40% - 2px); +} +/* https://github.com/uBlockOrigin/uBlock-issues/discussions/2114 */ +#ublock0-epicker aside { + min-width: min(24rem, 100vw - 4px); +} +#ublock0-epicker.paused:not(.zap) aside { + display: block; +} +#ublock0-epicker #toolbar { + display: flex; +} +#ublock0-epicker ul { + margin: 0.25em 0 0 0; +} +#ublock0-epicker.preview #preview { + background-color: var(--button-preferred-surface); + color: var(--button-preferred-ink); +} +#ublock0-epicker #move { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAFElEQVQI12NgwAfKy8v/M5ANYLoBshgEyQo6H9UAAAAASUVORK5CYII='); + cursor: grab; + flex-grow: 1; + margin: 2px 4px; + opacity: 0.8; + } +#ublock0-epicker aside.moving #move { + cursor: grabbing; +} +#ublock0-epicker section { + border: 0; + box-sizing: border-box; + display: inline-block; + width: 100%; +} +#ublock0-epicker section > div:first-child { + border: 1px solid var(--surface-3); + margin: 0; + position: relative; +} +#ublock0-epicker section.invalidFilter > div:first-child { + border-color: var(--error-surface); +} +#ublock0-epicker section .codeMirrorContainer { + border: none; + box-sizing: border-box; + height: 8em; + max-height: 50vh; + min-height: 1em; + padding: 2px; + width: 100%; + } +.CodeMirror-lines, +.CodeMirror pre { + padding: 0; + } + +#ublock0-epicker section .resultsetWidgets { + display: flex; + font-size: var(--font-size-smaller); + } +#resultsetModifiers { + align-items: flex-end; + display: inline-flex; + flex-grow: 1; + justify-content: space-evenly; + } +#resultsetModifiers.hide > * { + visibility: hidden; + } +.resultsetModifier { + border: 0; + pointer-events: auto; + position: relative; + width: 40%; + } +.resultsetModifier > span { + align-items: flex-end; + display: flex; + height: 100%; + pointer-events: none; + width: 100%; + } +.resultsetModifier > span > span { + margin: 2px 0; + } +.resultsetModifier > span > span:nth-of-type(1) { + background-color: var(--checkbox-checked-ink); + border-inline-end: 1px solid var(--surface-3); + display: inline-block; + flex-shrink: 0; + height: 6px; + } +.resultsetModifier > span > span:nth-of-type(2) { + background-color: var(--checkbox-checked-ink); + clip-path: polygon( + calc(50% - 2px) 0%, + 0% calc(100% - 6px), + 0% 100%, + 100% 100%, + 100% calc(100% - 6px), + calc(50% + 2px) 0% + ); + display: inline-block; + flex-shrink: 0; + height: 16px; + width: 16px; + } +.resultsetModifier > span > span:nth-of-type(3) { + background-color: var(--surface-3); + border-inline-start: 1px solid var(--surface-3); + display: inline-block; + flex-grow: 1; + height: 6px; + } +.resultsetModifier input { + border: 0; + height: 100%; + left: 0; + margin: 0; + opacity: 0; + padding: 0; + position: absolute; + top: 0; + width: 100%; + } +#resultsetCount { + align-items: center; + background-color: var(--surface-3); + color: var(--ink-1); + display: inline-flex; + justify-content: center; + min-width: 2.2em; + } +#ublock0-epicker section.invalidFilter #resultsetCount { + background-color: var(--error-surface); + color: var(--ink-100); +} +#ublock0-epicker section > div:first-child + div { + direction: ltr; + margin: 2px 0; + text-align: right; +} +#ublock0-epicker ul { + padding: 0; + list-style-type: none; + text-align: left; + overflow: hidden; +} +#ublock0-epicker #candidateFilters { + max-height: 14em; + overflow-y: auto; +} +#ublock0-epicker #candidateFilters > li:first-of-type { + margin-bottom: 0.5em; +} +#ublock0-epicker .changeFilter > li > span:nth-of-type(1) { + font-weight: bold; +} +#ublock0-epicker .changeFilter > li > span:nth-of-type(2) { + font-size: smaller; + color: gray; +} +#ublock0-epicker #candidateFilters .changeFilter { + list-style-type: none; + margin: 0 0 0 1em; + overflow: hidden; + text-align: left; +} +#ublock0-epicker #candidateFilters .changeFilter li { + border: 1px solid transparent; + cursor: pointer; + direction: ltr; + font: 12px monospace; + white-space: nowrap; +} +#ublock0-epicker #candidateFilters .changeFilter li.active { + border: 1px dotted rgb(var(--blue-50)); + } +#ublock0-epicker #candidateFilters .changeFilter li:hover { + background-color: var(--surface-2); +} + +/** + https://github.com/gorhill/uBlock/issues/3449 + https://github.com/uBlockOrigin/uBlock-issues/issues/55 +**/ +@keyframes startDialog { + 0% { opacity: 1.0; } + 60% { opacity: 1.0; } + 100% { opacity: 0.1; } +} +#ublock0-epicker.paused aside { + opacity: 0.1; + visibility: visible; + z-index: 100; +} +#ublock0-epicker.paused:not(.show):not(.hide) aside:not(:hover) { + animation-duration: 1.6s; + animation-name: startDialog; + animation-timing-function: linear; +} +#ublock0-epicker.paused aside:hover { + opacity: 1; +} +#ublock0-epicker.paused.show aside { + opacity: 1; +} +#ublock0-epicker.paused.hide aside { + opacity: 0.1; +} + +#ublock0-epicker svg { + cursor: crosshair; + box-sizing: border-box; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; +} +#ublock0-epicker.paused svg { + cursor: not-allowed; +} +#ublock0-epicker svg > path:first-child { + fill: rgba(0,0,0,0.5); + fill-rule: evenodd; +} +#ublock0-epicker svg > path + path { + stroke: #F00; + stroke-width: 0.5px; + fill: rgba(255,63,63,0.20); +} +#ublock0-epicker.zap svg > path + path { + stroke: #FF0; + stroke-width: 0.5px; + fill: rgba(255,255,63,0.20); +} +#ublock0-epicker.preview svg > path { + fill: rgba(0,0,0,0.10); +} +#ublock0-epicker.preview svg > path + path { + stroke: none; +} diff --git a/src/css/fa-icons.css b/src/css/fa-icons.css new file mode 100644 index 0000000..f6d517d --- /dev/null +++ b/src/css/fa-icons.css @@ -0,0 +1,149 @@ +.fa-icon { + align-items: center; + background-color: transparent; + border: 0; + display: inline-flex; + justify-content: center; + margin: 0; + padding: 0 0.1em; + position: relative; + user-select: none; + vertical-align: text-bottom; + -webkit-user-select: none; + } +.fa-icon > * { + pointer-events: none; + } +/* +.fa-icon.disabled, +.fa-icon[disabled] { + color: var(--button-disabled-ink); + fill: var(--button-disabled-ink); + filter: var(--button-disabled-filter); + stroke: var(--button-disabled-ink); + pointer-events: none; + } +*/ +.fa-icon > .fa-icon-badge, +.fa-icon.disabled > .fa-icon-badge { + visibility: hidden; + } +.fa-icon.fa-icon-badged > .fa-icon-badge { + bottom: -20%; + display: inline-block; + font: 60% sans-serif; + left: calc(100% - 0.2em); + position: absolute; + visibility: visible; + } +.fa-icon.fa-icon-hflipped > svg { + transform: scale(-1, 1); + transform-origin: 50%; + } +.fa-icon.fa-icon-vflipped > svg { + transform: scale(1, -1); + transform-origin: 50%; + } +.fa-icon.fa-icon-rotright > svg { + transform: rotate(90deg); + transform-origin: 50%; + } +.fa-icon.fa-icon-rotleft > svg { + transform: rotate(-90deg); + transform-origin: 50%; + } + +.fa-icon > svg { + height: 1em; + overflow: visible; + width: 1em; + } + +.fa-icon > .fa-icon_bar-chart { + width: calc(1em * 2048 / 1792); + } +.fa-icon > .fa-icon_cloud-download, +.fa-icon > .fa-icon_cloud-upload, +.fa-icon > .fa-icon_cogs, +.fa-icon > .fa-icon_eraser, +.fa-icon > .fa-icon_film { + width: calc(1em * 1920 / 1792); + } +.fa-icon > .fa-icon_code { + width: calc(1em * 1830 / 1792); + } +.fa-icon > .fa-icon_exclamation-triangle { + width: calc(1em * 1794 / 1792); + } +.fa-icon > .fa-icon_clipboard, +.fa-icon > .fa-icon_comment-alt, +.fa-icon > .fa-icon_external-link, +.fa-icon > .fa-icon_eye-dropper, +.fa-icon > .fa-icon_eye-open, +.fa-icon > .fa-icon_eye-slash, +.fa-icon > .fa-icon_files-o, +.fa-icon > .fa-icon_list-alt { + width: calc(1em * 1792 / 1792); + } +.fa-icon > .fa-icon_sun, +.fa-icon > .fa-icon_sun-o { + width: calc(1em * 1708 / 1792); + } +.fa-icon > .fa-icon_download-alt, +.fa-icon > .fa-icon_font, +.fa-icon > .fa-icon_search, +.fa-icon > .fa-icon_spinner, +.fa-icon > .fa-icon_unlink, +.fa-icon > .fa-icon_upload-alt, +.fa-icon > .fa-icon_zoom-in, +.fa-icon > .fa-icon_zoom-out { + width: calc(1em * 1664 / 1792); + } +.fa-icon > .fa-icon_magic { + width: calc(1em * 1637 / 1792); + } +.fa-icon > .fa-icon_home { + width: calc(1em * 1612 / 1792); + } +.fa-icon > .fa-icon_check { + width: calc(1em * 1550 / 1792); + } +.fa-icon > .fa-icon_cog, +.fa-icon > .fa-icon_clock-o, +.fa-icon > .fa-icon_floppy-o, +.fa-icon > .fa-icon_info-circle, +.fa-icon > .fa-icon_pause-circle-o, +.fa-icon > .fa-icon_play-circle-o, +.fa-icon > .fa-icon_power-off, +.fa-icon > .fa-icon_question-circle, +.fa-icon > .fa-icon_refresh, +.fa-icon > .fa-icon_save, +.fa-icon > .fa-icon_sliders, +.fa-icon > .fa-icon_undo { + width: calc(1em * 1536 / 1792); + } +.fa-icon > .fa-icon_arrow-right { + width: calc(1em * 1472 / 1792); + } +.fa-icon > .fa-icon_filter { + width: calc(1em * 1410 / 1792); + } +.fa-icon > .fa-icon_plus, +.fa-icon > .fa-icon_trash-o { + width: calc(1em * 1408 / 1792); + } +.fa-icon > .fa-icon_times { + width: calc(1em * 1188 / 1792); + } +.fa-icon > .fa-icon_angle-up, +.fa-icon > .fa-icon_double-angle-up, +.fa-icon > .fa-icon_lock, +.fa-icon > .fa-icon_unlock-alt { + width: calc(1em * 1152 / 1792); + } +.fa-icon > .fa-icon_double-angle-left { + width: calc(1em * 966 / 1792); + } +.fa-icon > .fa-icon_bolt { + width: calc(1em * 896 / 1792); + } diff --git a/src/css/fonts/Inter/Inter-Regular.woff2 b/src/css/fonts/Inter/Inter-Regular.woff2 new file mode 100644 index 0000000..d5ffd2a Binary files /dev/null and b/src/css/fonts/Inter/Inter-Regular.woff2 differ diff --git a/src/css/fonts/Inter/Inter-SemiBold.woff2 b/src/css/fonts/Inter/Inter-SemiBold.woff2 new file mode 100644 index 0000000..df746af Binary files /dev/null and b/src/css/fonts/Inter/Inter-SemiBold.woff2 differ diff --git a/src/css/fonts/Inter/LICENSE.txt b/src/css/fonts/Inter/LICENSE.txt new file mode 100644 index 0000000..d688280 --- /dev/null +++ b/src/css/fonts/Inter/LICENSE.txt @@ -0,0 +1,93 @@ +Copyright (c) 2016-2020 The Inter Project Authors +https://github.com/rsms/inter + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/css/fonts/Metropolis/Metropolis-Regular.woff2 b/src/css/fonts/Metropolis/Metropolis-Regular.woff2 new file mode 100644 index 0000000..f50bf34 Binary files /dev/null and b/src/css/fonts/Metropolis/Metropolis-Regular.woff2 differ diff --git a/src/css/fonts/Metropolis/Metropolis-SemiBold.woff2 b/src/css/fonts/Metropolis/Metropolis-SemiBold.woff2 new file mode 100644 index 0000000..fad6dfd Binary files /dev/null and b/src/css/fonts/Metropolis/Metropolis-SemiBold.woff2 differ diff --git a/src/css/fonts/Metropolis/README.md b/src/css/fonts/Metropolis/README.md new file mode 100644 index 0000000..ce01464 --- /dev/null +++ b/src/css/fonts/Metropolis/README.md @@ -0,0 +1,25 @@ +# Metropolis + +A modern, geometric typeface. Influenced by other popular geometric, minimalist sans-serif typefaces of the new millennium. Designed for optimal readability at small point sizes while beautiful at large point sizes. + +![Metropolis](./Specimens/Metro-1.png) + +--- + +![Metropolis](./Specimens/Metro-2.png) + +### Where am I? + +See [Documentation](./Documentation/Documentation.md). + +### The Unlicense + +Contributions welcome. + +### Contact + +Reachable via chris.m.simpson [at] icloud.com or tweet @ChrisMSimpson. + +### Support + +There is none. Oh, you meant support me? I dare you to click the sponsor button above. diff --git a/src/css/fonts/Metropolis/UNLICENSE b/src/css/fonts/Metropolis/UNLICENSE new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/src/css/fonts/Metropolis/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/src/css/logger-ui-inspector.css b/src/css/logger-ui-inspector.css new file mode 100644 index 0000000..975d90b --- /dev/null +++ b/src/css/logger-ui-inspector.css @@ -0,0 +1,122 @@ +#domInspector { + display: none; + } +#inspectors.dom #domInspector { + display: flex; + } +#domInspector .permatoolbar .highlightMode.invert { + transform: rotate(180deg); + } +#domInspector button.vExpandToggler > .fa-icon { + transform: scaleY(-1) + } +#domInspector button.vCompactToggler > .fa-icon { + transform: scaleY(1) + } +#domInspector .vscrollable { + overflow-x: auto; + } +#domInspector > ul:first-of-type { + padding-left: 0.5em; + } +#domInspector ul { + background-color: var(--surface-1); + margin: 0; + padding-left: 1em; + } +#domInspector li { + list-style-type: none; + white-space: nowrap; + } +#domInspector li.isCosmeticHide, +#domInspector li.isCosmeticHide ul, +#domInspector li.isCosmeticHide li { + background-color: var(--surface-2); + } +#domInspector li > * { + display: inline-block; + line-height: 1.2; + margin-right: 1em; + vertical-align: middle; + } +#domInspector li > span { + color: #aaa; + } +#domInspector li > span:first-child { + color: var(--ink-1); + cursor: default; + font-size: 1rem; + margin-right: 0; + opacity: 0.5; + padding: 0 4px 0 1px; + visibility: hidden; + } +#domInspector li > span:first-child:hover { + opacity: 1; + } +#domInspector li > *:last-child { + margin-right: 0; + } +#domInspector li > span:first-child:before { + content: '\a0'; + } +#domInspector li.branch > span:first-child:before { + content: '\25b8'; + visibility: visible; + } +#domInspector li.branch.show > span:first-child:before { + content: '\25be'; + } +#domInspector li.branch.hasCosmeticHide > span:first-child:before { + color: red; + } +#domInspector li > code { + cursor: pointer; + font-family: monospace; + overflow: hidden; + text-overflow: ellipsis; + } +#domInspector li > code.off { + text-decoration: line-through; + } +#domInspector li > code.filter { + color: var(--cm-negative); + } + +#domInspector li > ul { + display: block; + } +#domInspector li:not(.hasCosmeticHide):not(.isCosmeticHide):not(.show) > ul { + display: none; + } + +#domInspector li:not(.hasCosmeticHide):not(.isCosmeticHide):not(.show) { + display: none; + } +#domInspector #domTree > li { + display: block; + } +#domInspector:not(.vExpanded) ul { + display: block; + } +#domInspector li > ul > li:not(.hasCosmeticHide):not(.isCosmeticHide) { + display: none; + } +#domInspector li.show > ul > li:not(.hasCosmeticHide):not(.isCosmeticHide) { + display: block; + } +#domInspector li:not(.hasCosmeticHide):not(.isCosmeticHide) { + display: block; + } +#domInspector.hCompact li > code:first-of-type { + max-width: 12em; + } + +#cosmeticFilteringDialog .dialog { + text-align: center; + } +#cosmeticFilteringDialog .dialog textarea { + height: 40vh; + white-space: pre; + word-wrap: normal; + } diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css new file mode 100644 index 0000000..8e5065c --- /dev/null +++ b/src/css/logger-ui.css @@ -0,0 +1,985 @@ +body { + display: flex; + flex-direction: column; + height: 100vh; + overflow: hidden; + width: 100vw; + } +textarea { + box-sizing: border-box; + direction: ltr; + min-height: 6rem; + resize: vertical; + width: 100%; + } +.permatoolbar { + background-color: var(--surface-1); + border: 0; + box-sizing: border-box; + display: flex; + flex-shrink: 0; + font-size: 120%; + justify-content: space-between; + margin: 0; + padding: 0.25em; + } +.permatoolbar > div { + display: flex; + } +.permatoolbar button.iconified { + padding-left: var(--default-gap-xsmall); + padding-right: var(--default-gap-xsmall); + } +.permatoolbar button.active { + fill: rgb(var(--primary-50)); + } +.permatoolbar button > .fa-icon { + font-size: 180%; + } +#pageSelector { + min-width: 10em; + padding: 0.25em 0; + width: 50vw; + } +#showpopup { + display: inline-flex; + align-items: center; + } +#showpopup img { + filter: grayscale(100%); + height: auto; + width: 1em; + } +#info { + fill: #ccc; + } +#info:hover { + fill: #000; + } + +/* + https://github.com/gorhill/uBlock/issues/3293 + => https://devhints.io/css-system-font-stack +*/ +#inspectors { + flex-grow: 1; + font-family: "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + position: relative; + } +.inspector { + border-top: 1px solid #ccc; + display: flex; + flex-direction: column; + } +.vscrollable { + direction: ltr; + flex-grow: 1; + font-size: var(--font-size-smaller); + overflow-x: hidden; + overflow-y: auto; +} + +#domInspector button.vExpandToggler > .fa-icon { + transform: scaleY(1) + } +.inspector:not(.vExpanded) button.vCompactToggler > .fa-icon { + transform: scaleY(-1) + } +.hCompact button.hCompactToggler > .fa-icon { + transform: scaleX(-1) + } + +#inspectors.dom #netInspector { + display: none; + } + +#netInspector #pause > .fa-icon[data-i18n-title="loggerUnpauseTip"] { + display: none; +} +#netInspector.paused #pause > .fa-icon[data-i18n-title="loggerPauseTip"] { + display: none; +} +#netInspector.paused #pause > .fa-icon[data-i18n-title="loggerUnpauseTip"] { + display: inline-flex; + fill: #5F9EA0; +} +#netInspector #filterExprGroup { + display: flex; + margin: 0 1em; + position: relative; + } +#netInspector #filterButton { + opacity: 0.25; + } +#netInspector.f #filterButton { + opacity: 1; + } +#netInspector #filterInput { + border: 1px solid gray; + display: inline-flex; + } +#netInspector #filterInput > input { + border: 0; + min-width: 16em; + } +#netInspector #filterExprButton { + transform: scaleY(-1); + } +#netInspector #filterExprButton:hover { + background-color: transparent; + } +#netInspector #filterExprButton.expanded { + transform: scaleY(1); + } +#netInspector #filterExprPicker { + background-color: var(--surface-0); + border: 1px solid gray; + display: none; + position: absolute; + flex-direction: column; + font-size: small; + top: 100%; + z-index: 100; + } +body[dir="ltr"] #netInspector #filterExprPicker { + right: 0; + } +body[dir="rtl"] #netInspector #filterExprPicker { + left: 0; + } + +#netInspector #filterExprGroup:hover #filterExprButton.expanded ~ #filterExprPicker { + display: flex; + } +#netInspector #filterExprPicker > div { + border: 1px dotted #ddd; + border-left: 0; + border-right: 0; + display: flex; + padding: 0.5em; + } +#netInspector #filterExprPicker > div:first-of-type { + border-top: 0; + } +#netInspector #filterExprPicker > div:last-of-type { + border-bottom: 0; + } +#netInspector #filterExprPicker div { + display: flex; + } +#netInspector #filterExprPicker span[data-filtex] { + align-items: center; + border: 1px solid transparent; + cursor: pointer; + display: inline-flex; + margin: 0 0.5em 0 0; + padding: 0.25em; + white-space: nowrap; + } +#netInspector #filterExprPicker span[data-filtex]:last-of-type { + margin: 0; + } +#netInspector #filterExprPicker span[data-filtex]:hover { + background-color: rgb(var(--primary-70) / 25%); + border: 1px solid rgb(var(--primary-70)); + } +#netInspector #filterExprPicker span.on[data-filtex], +#filterExprButton.active { + background-color: rgb(var(--primary-70) / 40%); + } +#netInspector #filterExprPicker span.on[data-filtex] { + border: 1px solid rgb(var(--primary-70)); + } + +#netInspector .vscrollable { + overflow: hidden; + } +#vwRenderer { + box-sizing: border-box; + height: 100%; + overflow: hidden; + position: relative; + width: 100%; + } +#vwRenderer #vwScroller { + height: 100%; + overflow-x: hidden; + overflow-y: auto; + position: absolute; + width: 100%; + } +#vwRenderer #vwScroller #vwVirtualContent { + overflow: hidden; + } +#vwRenderer #vwContent { + left: 0; + overflow: hidden; + position: absolute; + width: 100%; + } +#vwRenderer .logEntry { + display: block; + left: 0; + overflow: hidden; + position: absolute; + width: 100%; + } +#vwRenderer .logEntry:empty { + display: none; + } +#vwRenderer .logEntry > div { + height: 100%; + white-space: nowrap; + } +#vwRenderer .logEntry > div[data-status="1"], +.netFilteringDialog > .panes > .details > div[data-status="1"] { + background-color: rgb(var(--popup-cell-block-surface-rgb) / 50%); + } +#vwRenderer .logEntry > div[data-status="1"][data-modifier], +.netFilteringDialog > .panes > .details > div[data-status="1"][data-modifier] { + background-color: var(--logger-modified-surface); + } +#vwRenderer .logEntry > div[data-status="3"] { + background-color: rgba(108, 108, 108, 0.1); + } +:root.colorBlind #vwRenderer .logEntry > div[data-status="3"] { + background-color: rgba(96, 96, 96, 0.1); + } +#vwRenderer .logEntry > div[data-status="2"], +.netFilteringDialog > .panes > .details > div[data-status="2"] { + background-color: rgb(var(--popup-cell-allow-surface-rgb) / 50%); + } +#vwRenderer .logEntry > div[data-tabid="-1"] { + text-shadow: 0 0.2em 0.4em #aaa; + } +#vwRenderer .logEntry > div.extendedRealm, +#vwRenderer .logEntry > div.redirect { + background-color: var(--logger-redirected-surface); + } +#vwRenderer .logEntry > div.extendedRealm.scriptlet { + background-color: var(--logger-scriptlet-surface); + } +:root.colorBlind #vwRenderer .logEntry > div.extendedRealm, +:root.colorBlind #vwRenderer .logEntry > div.redirect { + background-color: rgba(0, 19, 110, 0.1); + } +#vwRenderer .logEntry > div[data-aliasid] { + color: var(--popup-cell-cname-ink); + } +#vwRenderer .logEntry > div[data-type="tabLoad"] { + background-color: #666; + color: white; + } +#vwRenderer .logEntry > div[data-type="error"] { + color: var(--sf-error-ink); + } +#vwRenderer .logEntry > div[data-type="info"] { + color: var(--sf-def-ink); + } +#vwRenderer .logEntry > div.voided { + opacity: 0.5; + } +#vwRenderer .logEntry > div.voided:hover { + opacity: 0.7; + } + +#vwRenderer .logEntry > div > span { + border: 1px dotted var(--border-1); + border-top: 0; + border-right: 0; + box-sizing: border-box; + display: inline-block; + height: 100%; + overflow: hidden; + padding: 0.2em; + vertical-align: middle; + white-space: nowrap; + word-break: break-all; + } +#vwRenderer .logEntry > div.canDetails:hover > span { + background-color: rgba(0,0,0,0.04); + } +body[dir="ltr"] #vwRenderer .logEntry > div > span:first-child { + border-left: 0; + } +body[dir="rtl"] #vwRenderer .logEntry > div > span:first-child { + border-right: 0; + } +#vwRenderer .logEntry > div > span:nth-of-type(1) { + } +#vwRenderer .logEntry > div > span:nth-of-type(2) { + } +#vwRenderer .logEntry > div > span:nth-of-type(2) { + text-overflow: ellipsis; + } +#vwRenderer .logEntry > div.messageRealm > span:nth-of-type(2) ~ span { + display: none; + } +.vExpanded #vwRenderer #vwContent .logEntry > div > span:nth-of-type(2) { + overflow-y: auto; + white-space: pre-line; + } +#vwRenderer .logEntry > div.messageRealm[data-type="tabLoad"] > span:nth-of-type(2) { + text-align: center; + } +#vwRenderer .logEntry > div.extendedRealm > span:nth-of-type(2) > span:first-of-type { + display: none; + } +#vwRenderer .logEntry > div.extendedRealm > span:nth-of-type(2) > span:last-of-type { + pointer-events: none; + } +#vwRenderer .logEntry > div.extendedRealm.isException > span:nth-of-type(2) > span:last-of-type { + text-decoration: line-through rgba(0,0,255,0.7); + } +#vwRenderer .logEntry > div > span:nth-of-type(3) { + font-family: monospace; + padding-left: 0.3em; + padding-right: 0.3em; + text-align: center; + } +#vwRenderer .logEntry > div.canDetails:hover > span:not(:nth-of-type(4)):not(:nth-of-type(8)) { + background: rgba(0, 0, 255, 0.1); + cursor: zoom-in; + } +#netInspector:not(.vExpanded) #vwRenderer .logEntry > div > span:nth-of-type(4) { + direction: rtl; + text-align: right; + unicode-bidi: plaintext; + } +#vwRenderer #vwContent .logEntry > div > span:nth-of-type(4) { + text-overflow: ellipsis; + } +.vExpanded #vwRenderer #vwContent .logEntry > div > span:nth-of-type(4) { + overflow-y: auto; + text-overflow: clip; + white-space: pre-line; + } +#vwRenderer .logEntry > div > span:nth-of-type(5) { + text-align: center; + } +/* visual for tabless network requests */ +#vwRenderer .logEntry > div > span:nth-of-type(5) { + position: relative; + } +#vwRenderer .logEntry > div > span:nth-of-type(7) { + } +#vwRenderer #vwContent .logEntry > div > span:nth-of-type(7) { + } +#vwRenderer .logEntry > div > span:nth-of-type(8) { + position: relative; + } +#vwRenderer #vwContent .logEntry > div > span:nth-of-type(8) { + text-overflow: ellipsis; + } +.vExpanded #vwRenderer #vwContent .logEntry > div > span:nth-of-type(8) { + overflow-y: auto; + white-space: pre-line; + } +#vwRenderer .logEntry > div > span:nth-of-type(8) b { + font-weight: bold; + } +#vwRenderer .logEntry > div[data-status="1"] > span:nth-of-type(8) b, +.netFilteringDialog > .panes > .details > div[data-status="1"] b { + background-color: rgb(var(--popup-cell-block-surface-rgb) / 100%); + } +#vwRenderer .logEntry > div[data-status="1"][data-modifier] > span:nth-of-type(8) b, +.netFilteringDialog > .panes > .details > div[data-status="1"][data-modifier] b { + background-color: var(--logger-modified-em-surface); + } +#vwRenderer .logEntry > div[data-status="3"] > span:nth-of-type(8) b { + background-color: rgba(108, 108, 108, 0.2); + } +:root.colorBlind #vwRenderer .logEntry > div[data-status="3"] > span:nth-of-type(8) b { + background-color: rgba(96, 96, 96, 0.2); + } +#vwRenderer .logEntry > div[data-status="2"] > span:nth-of-type(8) b, +.netFilteringDialog > .panes > .details > div[data-status="2"] b { + background-color: rgb(var(--popup-cell-allow-surface-rgb) / 100%); + } +#vwRenderer .logEntry > div > span:nth-of-type(8) a { + align-items: center; + background-color: dimgray; + color: white; + display: none; + height: 100%; + justify-content: center; + padding: 0 0.25em; + opacity: 0.4; + position: absolute; + right: 0; + text-decoration: none; + top: 0; + width: 2rem; + } +#netInspector.vExpanded #vwRenderer .logEntry > div > span:nth-of-type(8) a { + bottom: 0px; + height: unset; + padding: 0.25em; + top: unset; + } +#vwRenderer .logEntry > div > span:nth-of-type(8) a::after { + content: '\2197'; + } +#vwRenderer .logEntry > div.networkRealm > span:nth-of-type(8):hover a { + display: inline-flex; + } +#vwRenderer .logEntry > div > span:nth-of-type(8) a:hover { + opacity: 1; + } + +#vwRenderer #vwBottom { + background-color: #00F; + height: 0; + overflow: hidden; + width: 100%; + } +#vwRenderer #vwLineSizer { + left: 0; + pointer-events: none; + position: absolute; + top: 0; + visibility: hidden; + width: 100%; + } + +#netInspector .entryTools { + background-color: var(--surface-0); + filter: drop-shadow(2px 4px 6px black); + max-width: 640px; + min-width: min(100%, 640px); + position: absolute; + } +#netInspector .entryTools:empty { + display: none; + } +#netInspector .entryTools .dialogControls { + display: flex; + justify-content: stretch; + } + +.closeButton { + stroke: var(--ink-1); + stroke-width: 3px; + width: 1.6em; + height: 1.6em; + bottom: calc(100% + 2px); + } +body[dir="ltr"] .closeButton { + right: 0; + } +body[dir="rtl"] .closeButton { + left: 0; + } +.closeButton:hover { + background-color: var(--surface-2) !important; + } +.closeButton > * { + pointer-events: none; + } +.moveBand { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAFElEQVQI12NgwAfKy8v/M5ANYLoBshgEyQo6H9UAAAAASUVORK5CYII='); + cursor: grab; + flex-grow: 1; + opacity: 0.5; + } +.moving .moveBand { + cursor: grabbing; +} + +#popupContainer { + background-color: var(--surface-1); + border: 1px solid gray; + bottom: 0; + display: none; + max-height: min(800px, calc(100vh - 2rem)); + min-width: 360px; + overflow: hidden; + position: fixed; + right: 0; + z-index: 200; + } +#inspectors.popupOn #popupContainer { + display: block; + } + +#modalOverlay { + align-items: center; + background-color: rgba(0, 0, 0, 0.5); + border: 0; + bottom: 0; + display: none; + justify-content: center; + left: 0; + margin: 0; + position: fixed; + right: 0; + top: 0; + z-index: 400; + } +#modalOverlay.on { + display: flex; + } +#modalOverlay > div { + position: relative; + } +#modalOverlay .closeButton { + background-color: var(--surface-1); + position: absolute; + } + +#modalOverlayContainer { + background-color: var(--surface-1); + border: 0; + box-sizing: border-box; + padding: 1em; + max-height: 90vh; + overflow-y: auto; + width: 90vw; + } + +.netFilteringDialog { + font-size: var(--font-size-smaller); + } +.netFilteringDialog a { + text-decoration: none; + } +.netFilteringDialog select { + max-width: 50vw; + outline: none; + text-overflow: ellipsis; +} +.netFilteringDialog > .preview { + align-items: center; + /* http://lea.verou.me/css3patterns/ */ + background-color: #aaa; + background-image: + linear-gradient( + 45deg, + #666 25%, + transparent 25%, + transparent 75%, + #666 75%, + #666 + ), + linear-gradient( + 45deg, + #666 25%, + transparent 25%, + transparent 75%, + #666 75%, + #666 + ); + background-position:0 0, 9px 9px; + background-size: 18px 18px; + display: flex; + justify-content: center; + margin-bottom: 1em; + padding: 0.5em; + text-align: center; + } +.netFilteringDialog > .preview > * { + max-width: 100%; + max-height: 20vh; + } +.netFilteringDialog > .preview > span { + background-color: var(--surface-3); + cursor: pointer; + padding: 1em; + } + +.netFilteringDialog > .headers { + align-items: center; + border-bottom: 1px solid var(--border-4); + display: flex; + line-height: 2; + } +.netFilteringDialog > .headers > .header { + border: 1px solid var(--border-2); + border-bottom: 1px solid var(--border-4); + border-top-left-radius: 4px; + border-top-right-radius: 4px; + color: var(--border-2); + cursor: pointer; + display: inline-block; + margin-inline-end: 4px; + padding: 0 1em; + position: relative; + top: 1px; + } +.netFilteringDialog[data-pane="details"] > .headers > [data-pane="details"], +.netFilteringDialog[data-pane="dynamic"] > .headers > [data-pane="dynamic"], +.netFilteringDialog[data-pane="static"] > .headers > [data-pane="static"] { + background-color: var(--surface-0); + border-color: var(--border-4); + border-bottom: 1px solid transparent; + color: var(--ink-1); + } +.netFilteringDialog > .headers > .tools { + bottom: 0; + display: flex; + height: 100%; + margin-inline-start: 2rem; + } +.netFilteringDialog > .headers > .tools > span { + color: var(--ink-3); + fill: var(--ink-3); + cursor: pointer; + font-size: 1.5em; + padding: 0 0.25em; + text-align: center; + } +.netFilteringDialog > .headers > .tools > span:hover { + color: var(--ink-1); + fill: var(--ink-1); + } +.netFilteringDialog.extendedRealm > .headers > .dynamic, +.netFilteringDialog.extendedRealm > .panes > .dynamic { + display: none; + } +.netFilteringDialog.extendedRealm > .headers > .static, +.netFilteringDialog.extendedRealm > .panes > .static { + display: none; + } +.netFilteringDialog > div.panes { + overflow: hidden; + overflow-y: auto; + padding-top: 1em; + } +.netFilteringDialog > div.panes > div { + display: none; + } +.netFilteringDialog[data-pane="details"] > .panes > [data-pane="details"], +.netFilteringDialog[data-pane="dynamic"] > .panes > [data-pane="dynamic"], +.netFilteringDialog[data-pane="static"] > .panes > [data-pane="static"] { + display: flex; + flex-direction: column; + padding: 0 var(--default-gap-xsmall) var(--default-gap-xsmall) var(--default-gap-xsmall); + } +.netFilteringDialog > .panes > .details > div { + align-items: stretch; + background-color: var(--surface-2); + border: 0; + border-bottom: 1px solid var(--surface-0); + display: flex; + } +.netFilteringDialog > .panes > .details > div > span { + padding: 0.5em; + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(1) { + border: 0; + flex-grow: 0; + flex-shrink: 0; + text-align: right; + width: 8em; + } +body[dir="ltr"] .netFilteringDialog > .panes > .details > div > span:nth-of-type(1) { + border-right: 1px solid var(--surface-0); + } +body[dir="rtl"] .netFilteringDialog > .panes > .details > div > span:nth-of-type(1) { + border-left: 1px solid var(--surface-0); + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(2) { + flex-grow: 1; + max-height: 10vh; + overflow: hidden auto; + white-space: pre-line + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(2):not(.prose) { + word-break: break-all; + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(2) .listEntry { + display: inline-flex; + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(2) .fa-icon { + font-size: 110%; + opacity: 0.5; + } +.netFilteringDialog > .panes > .details > div > span:nth-of-type(2) .fa-icon:hover { + opacity: 1; + } +.netFilteringDialog > .panes > .details .exceptor { + align-items: center; + border-left: 1px solid var(--surface-0); + cursor: pointer; + display: inline-flex; + font-family: monospace; + opacity: 0.8; + } +.netFilteringDialog > .panes > .details .exceptor:hover { + opacity: 1; + } +.netFilteringDialog > .panes > .details .exceptored .filter { + text-decoration: line-through; + } +.netFilteringDialog > .panes > .details .exceptored .exceptor { + background-color: rgb(var(--primary-50) / 50%); + } +.netFilteringDialog > .panes > .details .exceptor::before { + content: '@@'; + } +.netFilteringDialog.extendedRealm > .panes > .details .exceptor::before { + content: '#@#'; + } +.netFilteringDialog > div.panes > .dynamic > .toolbar { + padding-bottom: 1em; + } +.netFilteringDialog > div.panes > .dynamic .row { + display: flex; + min-height: 2.2em; + } +.netFilteringDialog > div.panes > .dynamic .row > span:nth-of-type(1) { + align-self: stretch; + border: 0; + display: inline-flex; + flex-grow: 0; + flex-shrink: 0; + text-align: center; + width: 4.5em; + } +body[dir="ltr"] .netFilteringDialog > div.panes > .dynamic .row > span:nth-of-type(1) { + border-right: 1px solid var(--surface-0); + } +body[dir="rtl"] .netFilteringDialog > div.panes > .dynamic .row > span:nth-of-type(1) { + border-left: 1px solid var(--surface-0); + } +.netFilteringDialog > div.panes > .dynamic .row > span:nth-of-type(2) { + align-self: center; + padding: 0 0.5em; + } +.netFilteringDialog > div.panes > .dynamic > .toolbar #saveRules { + background-color: #ffe; + border: 1px solid #ddc; + border-radius: 4px; + fill: #888; + cursor: pointer; + font-size: 2em; + visibility: hidden; + width: 100%; + } +body.dirty .netFilteringDialog > div.panes > .dynamic > .toolbar #saveRules { + visibility: visible; + } +.netFilteringDialog > div.panes > .dynamic > .toolbar #saveRules:hover { + fill: black; + } +.netFilteringDialog > div.panes > .dynamic > .toolbar .entry { + display: none; + } +.netFilteringDialog > div.panes > .dynamic .entry { + background-color: var(--surface-2); + border: 0; + border-bottom: 1px solid var(--surface-0); + } +.netFilteringDialog > div.panes > .dynamic .entry:hover { + background-color: var(--surface-3); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action { + background-color: transparent; + border: 0; + cursor: pointer; + } +.netFilteringDialog > div.panes > .dynamic .entry > .action > span { + background-color: transparent; + border: 0; + display: inline-block; + height: 100%; + opacity: 0.2; + visibility: hidden; + width: 33.33%; + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.allow { + background-color: rgba(0, 160, 0, 0.3); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.allow { + background-color: rgba(255, 194, 57, 0.4); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.noop { + background-color: rgba(108, 108, 108, 0.3); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.noop { + background-color: rgba(96, 96, 96, 0.4); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.block { + background-color: rgba(192, 0, 0, 0.3); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.block { + background-color: rgba(0, 19, 110, 0.4); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.own.allow { + background-color: rgba(0, 160, 0, 1); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.own.allow { + background-color: rgba(255, 194, 57, 1); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.own.noop, +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.own.noop { + background-color: rgba(108, 108, 108, 1); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action.own.block { + background-color: rgba(192, 0, 0, 1); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action.own.block { + background-color: rgba(0, 19, 110, 1); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action:not(.own):hover > span { + opacity: 0.2; + visibility: visible; + } +.netFilteringDialog > div.panes > .dynamic .entry > .action:not(.own):hover > span:hover { + opacity: 0.75; + } +.netFilteringDialog > div.panes > .dynamic .entry > .action > .allow { + background-color: rgb(0, 160, 0); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action > .allow { + background-color: rgb(255, 194, 57); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action > .noop { + background-color: rgb(108, 108, 108); + } +.netFilteringDialog > div.panes > .dynamic .entry > .action > .block { + background-color: rgb(192, 0, 0); + } +:root.colorBlind .netFilteringDialog > div.panes > .dynamic .entry > .action > .block { + background-color: rgb(0, 19, 110); + } +.netFilteringDialog > div.panes > .dynamic .entry > .url { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +.netFilteringDialog > div.panes > div.static > div { + line-height: 2; + } +.netFilteringDialog > div.panes > div.static textarea { + height: 6em; + max-height: 20vh; + min-height: 10vh; + word-break: break-all; + } +.netFilteringDialog > div.panes > div.static > div:nth-of-type(2) { + text-align: center; + } + +#filterFinderDialog { + word-break: break-all; + } +#filterFinderDialog code { + background: #eee; + font-size: 85%; + padding: 3px; + unicode-bidi: plaintext; + white-space: pre-wrap; + } +#filterFinderDialog ul { + font-size: larger; + } +#filterFinderDialog .filterFinderListEntry { + align-items: flex-end; + display: flex; + } +#filterFinderDialog .filterFinderListEntry a { + text-decoration: none; + } +#filterFinderDialog .filterFinderListEntry a.fa-icon { + margin: 0 0.5em; + opacity: 0.6; + } +#filterFinderDialog .filterFinderListEntry a.fa-icon:hover { + opacity: 1; + } +#filterFinderDialog .filterFinderListEntry a.fa-icon[href=""] { + display: none; + } +#filterFinderDialog > *:first-child { + margin-top: 0; + } +#filterFinderDialog > *:last-child { + margin-bottom: 0; + } + +#loggerStatsDialog .sortedEntries { + display: flex; + flex-direction: column; + font-size: smaller; + } +#loggerStatsDialog .sortedEntries > div { + display: flex; + } +#loggerStatsDialog .sortedEntries > div > span:first-of-type { + flex-grow: 0; + flex-shrink: 0; + padding: 0 2em 0 0; + text-align: right; + width: 3em; + } +#loggerStatsDialog .sortedEntries > div > span:last-of-type { + flex-grow: 1; + flex-shrink: 1; + white-space: pre; + } + +#loggerExportDialog { + display: flex; + flex-direction: column; + } +#loggerExportDialog .options { + display: flex; + justify-content: space-between; + margin-bottom: 1em; + } +#loggerExportDialog .options > div { + display: inline-flex; + } +#loggerExportDialog .options span[data-i18n] { + border: 1px solid rgb(var(--primary-70)); + cursor: pointer; + font-size: 90%; + margin: 0; + padding: 0.5em; + white-space: nowrap; + } +#loggerExportDialog .options span[data-i18n]:hover { + background-color: rgb(var(--primary-70) / 40%); + } +#loggerExportDialog .options span.on[data-i18n], +#loggerExportDialog .options span.pushbutton:active { + background-color: rgb(var(--primary-70) / 40%); + } +#loggerExportDialog .output { + font: smaller mono; + height: 60vh; + padding: 0.5em; + white-space: pre; + } + +#loggerSettingsDialog { + display: flex; + flex-direction: column; + } +#loggerSettingsDialog > div { + padding-bottom: 1em; + } +#loggerSettingsDialog > div:last-of-type { + padding-bottom: 0; + } +#loggerSettingsDialog ul { + padding: 0; + } +body[dir="ltr"] #loggerSettingsDialog ul { + padding-left: 2em; + } +body[dir="rtl"] #loggerSettingsDialog ul { + padding-right: 2em; + } +#loggerSettingsDialog li { + list-style-type: none; + margin: 0.5em 0 0 0; + } +#loggerSettingsDialog input { + max-width: 6em; + } + +.hide { + display: none !important; + } diff --git a/src/css/popup-fenix.css b/src/css/popup-fenix.css new file mode 100644 index 0000000..252e371 --- /dev/null +++ b/src/css/popup-fenix.css @@ -0,0 +1,778 @@ + /* External CSS values override */ +.fa-icon.fa-icon-badged > .fa-icon-badge { + bottom: auto; + top: -20%; + } + +/* Internal CSS values */ +:root body { + overflow: hidden; + } +:root body, +:root.mobile body { + --font-size: 14px; + --popup-gap: var(--font-size); + --popup-gap-thin: calc(0.5 * var(--popup-gap)); + --popup-gap-extra-thin: calc(0.25 * var(--popup-gap)); + --popup-main-min-width: 18em; + --popup-firewall-min-width: 30em; + --popup-rule-cell-width: 5em; + font-size: var(--font-size); + line-height: 20px; + } +:root body.loading { + opacity: 0; + } +a { + color: var(--ink-1); + fill: var(--ink-1); + text-decoration: none; + } +:focus { + outline: 0; + } + +#panes { + align-items: stretch; + display: flex; + flex-direction: row-reverse; + padding: 0; + position: relative; + } +#main { + align-self: flex-start; + max-width: 340px; + min-width: var(--popup-main-min-width); + } +:root.portrait #main { + align-self: inherit; + } +hr { + border: 0; + border-top: 1px solid var(--hr-ink); + margin: 0; + padding: 0; + } + +#sticky { + background-color: var(--surface-1); + position: sticky; + top: 0; + z-index: 100; + } +#stickyTools { + align-items: stretch; + display: flex; + justify-content: space-between; + margin: var(--popup-gap-extra-thin) 0; + } +#switch { + color: var(--popup-power-ink); + cursor: pointer; + display: flex; + fill: var(--popup-power-ink); + flex-grow: 1; + font-size: 96px; + justify-content: center; + margin: var(--popup-gap) 0; + padding: 0; + stroke: none; + stroke-width: 64; + } +body.off #switch { + fill: var(--surface-1); + stroke: var(--checkbox-ink); + } +.rulesetTools { + background-color: transparent; + border: 0; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: space-between; + width: 25%; + } +.rulesetTools [id] { + background-color: var(--popup-ruleset-tool-surface); + border-radius: 4px; + cursor: pointer; + fill: var(--popup-ruleset-tool-ink); + flex-grow: 1; + font-size: 2.2em; + padding: 0; + visibility: hidden; + } +.rulesetTools [id]:not(:first-of-type) { + margin-block-start: 1px; + } +.rulesetTools [id] > svg { + fill: var(--ink-4); + } +body.needReload #refresh, +body.needSave #saveRules, +body.needSave #revertRules { + visibility: visible; + } +#hostname { + background-color: var(--popup-toolbar-surface); + margin: 0; + padding: var(--popup-gap-thin) 0; + text-align: center; + white-space: normal; + + } +#hostname > span { + word-break: break-all; + } +#hostname > span + span { + font-weight: 600; + } + +#basicStats { + column-gap: var(--popup-gap); + display: grid; + grid-template: auto / auto; + margin: var(--popup-gap) var(--popup-gap) var(--popup-gap-thin) var(--popup-gap); + } +#basicStats > span { + justify-self: center; + white-space: nowrap; + } +#basicStats > [data-i18n] { + font-size: 95%; + } +#basicStats > [data-i18n] + span { + font-size: 105%; + margin-bottom: var(--popup-gap-thin); + } +:root.portrait #basicStats { + grid-template: auto / auto auto; + margin-bottom: 0; + } +:root.portrait #basicStats > span { + font-size: inherit; + justify-self: stretch; + margin-bottom: var(--popup-gap); + white-space: unset; + } +:root.portrait #basicStats > [data-i18n] { + } +:root.portrait #basicStats > [data-i18n] + span { + text-align: end; + } + +.itemRibbon { + column-gap: var(--popup-gap); + display: grid; + grid-auto-columns: 1fr; + grid-auto-flow: column; + grid-template: auto / 1fr 1fr; + margin: var(--popup-gap); + } +.itemRibbon > span + span { + text-align: end; + } + +.toolRibbon { + align-items: start; + background-color: var(--popup-toolbar-surface); + display: grid; + grid-auto-columns: 1fr; + grid-auto-flow: column; + grid-template: auto / repeat(4, 1fr); + justify-items: center; + margin: 0; + white-space: normal; + } +.toolRibbon .tool { + cursor: pointer; + display: flex; + flex-direction: column; + font-size: 1.4em; + min-width: 32px; + padding: var(--popup-gap) + var(--popup-gap-thin); + unicode-bidi: embed; + visibility: hidden; + } +.toolRibbon .tool:hover { + color: var(--ink-1); + fill: var(--ink-1); + } +.toolRibbon .tool.enabled { + visibility: visible; + } +.toolRibbon .tool .caption { + font: 10px/12px sans-serif; + margin-top: 6px; + text-align: center; + } +:root.mobile.no-tooltips .toolRibbon .tool { + font-size: 1.6em; + } + +#basicTools:not(.canPick) .needPick { + visibility: hidden; + } + +#extraTools .fa-icon { + align-self: center; + position: relative; + } +#extraTools .fa-icon > .nope { + height: 1.1em; + left: 50%; + position: absolute; + stroke: var(--popup-icon-x-ink); + stroke-width: 2; + transform: translateX(-50%); + visibility: hidden; + width: 1.1em; + } +#extraTools > span.on .fa-icon >.nope { + visibility: visible; + } + +#unprocessedRequestWarning { + align-items: center; + background-color: #fc0; + color: rgb(var(--ink-80)); + stroke: rgb(var(--ink-80)); + display: none; + font-size: var(--font-size-smaller); + padding: var(--popup-gap-thin); + } +:root.warn #unprocessedRequestWarning { + display: flex; + } +#unprocessedRequestWarning > .dismiss { + flex-shrink: 0; + width: calc(var(--font-size) - 2px); + } +#unprocessedRequestWarning > .dismiss > svg { + width: 100%; + } + +#moreOrLess { + column-gap: 0; + display: grid; + grid-template: auto / 1fr 1fr; + justify-items: stretch; + margin: 1px 0 0 0; + } +#moreOrLess > span { + cursor: pointer; + margin: 0; + padding: var(--popup-gap-thin) var(--popup-gap); + user-select: none; + white-space: nowrap; + } +:root.mobile #moreOrLess > span { + padding: var(--popup-gap); + } +#moreButton .fa-icon { + transform: rotate(180deg); + } +#lessButton { + border-inline-start: 1px solid var(--surface-1); + text-align: end; + } +#moreButton.disabled, +#lessButton.disabled { + pointer-events: none; + visibility: hidden; + } + +#firewall { + border: 0; + flex-shrink: 1; + font-size: 90%; + margin: 0; + max-height: 600px; + max-width: 460px; + min-width: var(--popup-firewall-min-width); + padding: 0; + position: relative; + overflow-y: auto; + } +:root.desktop #firewall { + margin-inline-start: 1px; + } +:root.desktop body.vMin #firewall { + max-height: 100vh; + } +#firewall > * { + direction: ltr; + } +#firewall > section { + align-items: flex-start; + display: flex; + left: 0; + position: absolute; + z-index: 50; + } +#firewall > section .fa-icon { + color: var(--ink-4); + fill: var(--ink-4); + font-size: 150%; + padding: var(--popup-gap-thin); + } +#firewall > section:hover .fa-icon { + color: var(--ink-1); + fill: var(--ink-1); + } +#firewall.showBlocked > section .fa-icon, +#firewall.showAllowed > section .fa-icon, +#firewall.hideBlocked > section .fa-icon, +#firewall.hideAllowed > section .fa-icon, +#firewall.show3pScript > section .fa-icon, +#firewall.show3pFrame > section .fa-icon, +#firewall.hide3pScript > section .fa-icon, +#firewall.hide3pFrame > section .fa-icon { + color: rgb(var(--primary-70)); + fill: rgb(var(--primary-70)); + } +#firewall > section .filterExpressions { + background-color: var(--surface-0); + border: 1px solid var(--border-4); + display: none; + } +#firewall > section:hover .filterExpressions { + display: flex; + flex-direction: column; + } +#firewall > section .filterExpressions div { + border-bottom: 1px dotted #ddd; + padding: 0.25em; + } +#firewall > section .filterExpressions div:last-of-type { + border-bottom: 0; + } +#firewall > section .filterExpressions span { + cursor: default; + display: inline-flex; + margin: 0 0.25em 0 0; + padding: 0.5em; + white-space: nowrap; + border: 1px solid var(--surface-0); + } +#firewall > section .filterExpressions span:last-of-type { + margin: 0; + } +:root:not(.mobile) #firewall > section .filterExpressions span:not(.on):hover { + background-color: rgb(var(--primary-70) / 15%); + border: 1px solid rgb(var(--primary-70)); + } +#firewall > section .filterExpressions span.on { + background-color: rgb(var(--primary-70) / 40%); + border: 1px solid rgb(var(--primary-70)); + } +#firewall > div { + border: 0; + display: flex; + margin: 0; + margin-top: 1px; + padding: 0; + } +#firewall > div:first-of-type { + margin-top: 0; + } +#firewall > div:first-of-type ~ div[data-des="*"] { + display: none; + } +#firewall:not(.expanded) > div.isSubdomain:not(.expandException):not(.isRootContext), +#firewall.expanded > div.isSubdomain.expandException:not(.isRootContext) { + display: none; + } +#firewall > div > span, +#actionSelector > #dynaCounts { + background-color: var(--popup-cell-surface); + border: none; + box-sizing: border-box; + display: inline-flex; + padding: 0.4em 0; + position: relative; + } +#firewall > div:first-of-type span[data-i18n] { + cursor: pointer; + flex-direction: unset; + flex-grow: 1; + } +#firewall > div:first-of-type span[data-i18n]::before { + color: var(--ink-3); + content: '+'; + padding-right: 0.25em; + } +#firewall.expanded > div:first-of-type span[data-i18n]::before { + content: '\2012'; + } +#firewall > div > span:first-of-type { + flex-direction: column; + flex-grow: 1; + justify-content: flex-end; + padding-right: 2px; + text-align: right; + white-space: normal; + width: calc(100% - var(--popup-rule-cell-width)); + word-break: break-word; + } +#firewall > div[data-des="*"] > span:first-of-type { + flex-direction: row; + } +#firewall.show3pScript:not(.show3pFrame) > div:not([data-des="*"]).is3p:not(.hasScript), +#firewall.show3pFrame:not(.show3pScript) > div:not([data-des="*"]).is3p:not(.hasFrame), +#firewall.show3pScript.show3pFrame > div:not([data-des="*"]).is3p:not(.hasScript):not(.hasFrame), +#firewall.hide3pScript > div:not([data-des="*"]).is3p.hasScript, +#firewall.hide3pFrame > div:not([data-des="*"]).is3p.hasFrame, +#firewall.showBlocked > div:not([data-des="*"]).is3p:not(.totalBlocked):not(.blocked), +#firewall.showAllowed > div:not([data-des="*"]).is3p:not(.totalAllowed):not(.allowed), +#firewall.hideBlocked > div:not([data-des="*"]).is3p.totalBlocked, +#firewall.hideBlocked > div:not([data-des="*"]).is3p.blocked, +#firewall.hideAllowed > div:not([data-des="*"]).is3p.totalAllowed, +#firewall.hideAllowed > div:not([data-des="*"]).is3p.allowed { + max-height: 4px; + overflow-y: hidden; + pointer-events: none; + user-select: none; + } +#firewall.show3pScript:not(.show3pFrame) > div:not([data-des="*"]).is3p:not(.hasScript) *, +#firewall.show3pFrame:not(.show3pScript) > div:not([data-des="*"]).is3p:not(.hasFrame) *, +#firewall.show3pScript.show3pFrame > div:not([data-des="*"]).is3p:not(.hasScript):not(.hasFrame) *, +#firewall.hide3pScript > div:not([data-des="*"]).is3p.hasScript *, +#firewall.hide3pFrame > div:not([data-des="*"]).is3p.hasFrame *, +#firewall.showBlocked > div:not([data-des="*"]).is3p:not(.totalBlocked):not(.blocked) *, +#firewall.showAllowed > div:not([data-des="*"]).is3p:not(.totalAllowed):not(.allowed) *, +#firewall.hideBlocked > div:not([data-des="*"]).is3p.totalBlocked *, +#firewall.hideBlocked > div:not([data-des="*"]).is3p.blocked *, +#firewall.hideAllowed > div:not([data-des="*"]).is3p.totalAllowed *, +#firewall.hideAllowed > div:not([data-des="*"]).is3p.allowed * { + color: transparent !important; + } +#firewall > div.isCname > span:first-of-type { + color: var(--popup-cell-cname-ink); + } +#firewall > div > span:first-of-type > sub { + display: inline-block; + font-size: 85%; + font-weight: normal; + padding: 0.25em 0 0 0; + } +#firewall > div > span:first-of-type > sub:empty { + display: none; + } +#firewall > div > span:first-of-type ~ span { + flex-shrink: 0; + margin-left: 1px; + width: var(--popup-rule-cell-width); + } +#firewall > div > span:nth-of-type(2) { + display: none; + } +#firewall > div > span:nth-of-type(3), +#firewall > div > span:nth-of-type(4) { + color: var(--ink-2); + display: none; + font-family: monospace; + text-align: center; + } +#firewall > div.isDomain > span:first-of-type > span { + pointer-events: none; + } +#firewall > div.isDomain > span:first-of-type > span > span { + font-weight: 600; + pointer-events: auto; + } +#firewall > div.isDomain.hasSubdomains > span:first-of-type > span::before { + content: '\2026\A0'; + opacity: 0.6; + } +#firewall > div[data-des="*"] > span:nth-of-type(3), +#firewall > div.isSubdomain > span:nth-of-type(3), +#firewall > div.isSubdomain.isRootContext > span:nth-of-type(3), +#firewall.expanded > div:not(.expandException) > span:nth-of-type(3), +#firewall:not(.expanded) > div.expandException > span:nth-of-type(3), +#firewall:not(.expanded) > div.isDomain:not(.expandException) > span:nth-of-type(4), +#firewall.expanded > div.isDomain.expandException > span:nth-of-type(4), +#actionSelector > #dynaCounts { + display: inline-flex; + justify-content: space-between; + } +#firewall > div > span[data-acount]::before, +#firewall > div > span[data-bcount]::after, +#firewall > div > span[data-acount] > #actionSelector > #dynaCounts::before, +#firewall > div > span[data-acount] > #actionSelector > #dynaCounts::after { + content: ' '; + } +#firewall > div > span[data-acount]::before, +#firewall > div > span[data-acount] > #actionSelector > #dynaCounts::before { + padding-left: 0.1em; + } +#firewall > div > span[data-acount="1"]::before, +#firewall > div > span[data-acount="1"] > #actionSelector > #dynaCounts::before { + content: '+'; + } +#firewall > div > span[data-acount="2"]::before, +#firewall > div > span[data-acount="2"] > #actionSelector > #dynaCounts::before { + content: '++'; + } +#firewall > div > span[data-acount="3"]::before, +#firewall > div > span[data-acount="3"] > #actionSelector > #dynaCounts::before { + content: '+++'; + } +#firewall > div > span[data-bcount]::after, +#firewall > div > span[data-bcount] > #actionSelector > #dynaCounts::after { + padding-right: 0.1em; + } +#firewall > div > span[data-bcount="1"]::after, +#firewall > div > span[data-bcount="1"] > #actionSelector > #dynaCounts::after { + content: '\2212'; + } +#firewall > div > span[data-bcount="2"]::after, +#firewall > div > span[data-bcount="2"] > #actionSelector > #dynaCounts::after { + content: '\2212\2212'; + } +#firewall > div > span[data-bcount="3"]::after, +#firewall > div > span[data-bcount="3"] > #actionSelector > #dynaCounts::after { + content: '\2212\2212\2212'; + } + +body.advancedUser #firewall > div > span:first-of-type { + width: calc(100% - 2 * var(--popup-rule-cell-width)); + } +body.advancedUser #firewall > div > span:nth-of-type(2) { + display: inline-flex; + } +body.advancedUser #firewall > div:first-of-type ~ div[data-des="*"] { + display: flex; + } +body.advancedUser #firewall > div > span:first-of-type ~ span { + cursor: pointer; + } + +/** + Small coloured label at the left of a row + */ +#firewall > div.isRootContext > span:first-of-type::before, +#firewall > div.allowed > span:first-of-type::before, +#firewall > div.blocked > span:first-of-type::before, +#firewall:not(.expanded) > div.isDomain.totalAllowed:not(.expandException) > span:first-of-type::before, +#firewall:not(.expanded) > div.isDomain.totalBlocked:not(.expandException) > span:first-of-type::before, +#firewall.expanded > div.isDomain.totalAllowed.expandException > span:first-of-type::before, +#firewall.expanded > div.isDomain.totalBlocked.expandException > span:first-of-type::before { + box-sizing: border-box; + content: ''; + display: inline-block; + filter: var(--popup-cell-label-filter); + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 7px; + } +#firewall > div.isRootContext > span:first-of-type::before { + background: var(--ink-3); + width: 14px !important; + } +#firewall > div.allowed > span:first-of-type::before, +#firewall > div.isDomain.totalAllowed > span:first-of-type::before { + background: var(--popup-cell-allow-own-surface); + } +#firewall > div.blocked > span:first-of-type::before, +#firewall > div.isDomain.totalBlocked > span:first-of-type::before { + background: var(--popup-cell-block-own-surface); + } +#firewall > div.allowed.blocked > span:first-of-type::before, +#firewall > div.isDomain.totalAllowed.totalBlocked > span:first-of-type::before { + background: var(--popup-cell-label-mixed-surface); + } +/* Rule cells */ +body.advancedUser #firewall > div > span.allowRule, +#actionSelector > #dynaAllow { + background: var(--popup-cell-allow-surface); + } +body.advancedUser #firewall > div > span.blockRule, +#actionSelector > #dynaBlock { + background: var(--popup-cell-block-surface); + } +body.advancedUser #firewall > div > span.noopRule, +#actionSelector > #dynaNoop { + background: var(--popup-cell-noop-surface); + } +body.advancedUser #firewall > div > span.ownRule, +#firewall > div > span.ownRule { + color: var(--surface-1); + } +body.advancedUser #firewall > div > span.allowRule.ownRule, +:root:not(.mobile) #actionSelector > #dynaAllow:hover { + background: var(--popup-cell-allow-own-surface); + } +body.advancedUser #firewall > div > span.blockRule.ownRule, +:root:not(.mobile) #actionSelector > #dynaBlock:hover { + background: var(--popup-cell-block-own-surface); + } +body.advancedUser #firewall > div > span.noopRule.ownRule, +:root:not(.mobile) #actionSelector > #dynaNoop:hover { + background: var(--popup-cell-noop-own-surface); + } + +#actionSelector { + box-sizing: border-box; + display: flex; + height: 100%; + justify-items: stretch; + left: 0; + overflow: hidden; + position: absolute; + top: 0; + width: 100%; + z-index: 1; + } +#actionSelector > span { + display: inline-block; + flex-grow: 1; + } +#actionSelector > #dynaAllow { + display: none; + } +body.godMode #actionSelector > #dynaAllow { + display: inline-block; + } +#actionSelector > #dynaNoop { + } +#actionSelector > #dynaBlock { + } +#actionSelector > #dynaCounts { + background-color: transparent; + height: 100%; + left: 0; + pointer-events: none; + position: absolute; + top: 0; + width: 100%; + } + +/* configurable UI elements */ +:root:not(.mobile) .toolRibbon .caption, +:root.mobile body.no-tooltips .toolRibbon .caption, +:root.mobile body[data-ui~="-captions"] .toolRibbon .caption { + display: none; + } +:root.mobile .toolRibbon .caption, +:root:not(.mobile) body[data-ui~="+captions"] .toolRibbon .caption { + display: inherit; + } +:root:not(.mobile) .toolRibbon .tool, +:root.mobile body.no-tooltips .toolRibbon .tool, +:root.mobile body[data-ui~="-captions"] .toolRibbon .tool { + padding: var(--popup-gap) var(--popup-gap-thin); + } +:root.mobile #no-popups, +:root body[data-ui~="-no-popups"] #no-popups { + display: none; + } +:root:not(.mobile) #no-popups, +:root body[data-ui~="+no-popups"] #no-popups { + display: flex; + } +:root.mobile [href="logger-ui.html#_"], +:root body[data-ui~="-logger"] [href="logger-ui.html#_"] { + display: none; + } +:root:not(.mobile) [href="logger-ui.html#_"], +:root body[data-ui~="+logger"] [href="logger-ui.html#_"] { + display: flex; + } +body:not([data-more*="a"]) [data-more="a"], +body:not([data-more*="b"]) [data-more="b"], +body:not([data-more*="c"]) [data-more="c"], +body:not([data-more*="d"]) [data-more="d"], +body:not([data-more*="f"]) [data-more="f"] { + height: 0; + margin-bottom: 0 !important; + margin-top: 0 !important; + overflow-y: hidden; + visibility: hidden; + } +body[data-more*="d"] hr[data-more="a"] { + display: none; + } +body[data-more*="c"] hr[data-more="f"] { + display: none; + } +body[data-more*="c"]:not([data-more*="f"]) hr[data-more="g"] { + display: none; + } +body:not([data-more*="e"]) [data-more="e"] { + display: none; + } + +:root #firewall-vspacer { + display: none; + height: calc(6 * var(--popup-gap)); + } + +/* popup-in-tab mode, useful for screenshots */ +:root.desktop.intab body { + overflow: auto; + } +:root.desktop.intab #firewall { + max-height: none; + } + +/* horizontally-constrained viewport */ +:root.portrait:not(.desktop) body { + overflow-y: auto; + width: 100%; + } +:root.portrait #panes { + flex-direction: column; + } +:root.portrait #main { + max-width: unset; + } +:root.portrait #firewall { + max-height: unset; + max-width: unset; + min-width: unset; + overflow-y: hidden; + } +:root.portrait body[data-more*="e"] #firewall-vspacer { + display: block; + } + +/* touch-driven devices */ +:root.mobile #firewall { + line-height: 20px; + } + +/* mouse-driven devices */ +:root.desktop { + display: flex; + justify-content: flex-end; + } +:root.desktop body { + --popup-gap: calc(var(--font-size) * 0.875); + } +:root.desktop body:not(.off) #switch:hover { + fill: rgb(var(--popup-power-ink-rgb) / 90%); + } +:root.desktop body.off #switch:hover { + stroke: var(--popup-power-ink); + } +:root.desktop .rulesetTools [id]:hover { + background-color: var(--popup-ruleset-tool-surface-hover); + } +:root.desktop .rulesetTools [id]:hover > svg { + fill: var(--ink-2); + } +:root.desktop #firewall { + direction: rtl; + line-height: 1.4; + } +:root.desktop .tool:hover { + background-color: var(--popup-toolbar-surface-hover); + } +:root.desktop #moreOrLess > span:hover { + background-color: var(--surface-2); + /* background-color: var(--popup-toolbar-surface-hover); */ + } diff --git a/src/css/settings.css b/src/css/settings.css new file mode 100644 index 0000000..61a8c0e --- /dev/null +++ b/src/css/settings.css @@ -0,0 +1,74 @@ +body { + margin-bottom: 6rem; + } + +.synopsis { + color: var(--ink-0); + font-size: var(--font-size-smaller); + opacity: var(--medium-em); + } + +/* surface/ink */ +#themeMood { + align-items: stretch; + align-self: stretch; + display: inline-flex; + justify-content: stretch; + user-select: none; + } +#themeMood > span { + border: 1px solid var(--ink-1); + color: var(--ink-1); + display: inline-flex; + background-color: var(--surface-1); + display: inline-block; + padding: 0 0.5em; + text-align: center; + user-select: none; + } + +/* primary color */ +#themePrimary { + align-items: stretch; + align-self: stretch; + display: inline-flex; + justify-content: stretch; + position: relative; + } +#themePrimary > span { + background-color: rgb(var(--primary-50)); + display: inline-flex; + width: 2em; + } + +[href="advanced-settings.html"] { + display: none; + } +body.advancedUser [href="advanced-settings.html"] { + display: inline-flex; + } + +#localData > div { + margin-bottom: var(--default-gap-small); + } +#localData > div:last-of-type { + align-items: flex-start; + display: flex; + flex-direction: column; + } +#localData > div:last-of-type > button { + margin-bottom: var(--default-gap-small); + min-width: 280px; + } + +/* Mobile devices */ + +:root.mobile #localData { + max-width: 100vw; + } +:root.mobile #localData > div:last-of-type { + align-items: stretch; + } +:root.mobile #localData > div:last-of-type > button { + min-width: unset; + } diff --git a/src/css/support.css b/src/css/support.css new file mode 100644 index 0000000..0afd740 --- /dev/null +++ b/src/css/support.css @@ -0,0 +1,110 @@ +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + } + +body { + margin-bottom: 6rem; + } + +.body > div { + max-width: 800px; + } +h3 { + color: var(--fieldset-header-ink); + margin-bottom: 0; + } +.supportEntry { + display: flex; + margin-block: 1em; + } +:root.mobile .supportEntry { + flex-direction: column; + } +.supportEntry > * { + min-width: 6em; + } +.supportEntry > div:first-of-type { + flex-grow: 1; + } +:root:not(.mobile) .supportEntry > div:first-of-type { + margin-inline-end: 2em; + } +.supportEntry h3 { + margin: 1em 0; + } + +.e > .supportEntry { + flex-direction: column; + } +.e > .supportEntry > div:not(:first-of-type) { + margin-top: 1em; + } +.e > .supportEntry select { + min-width: 50%; + max-width: calc(100% - 1em); + } +body:not(.filterIssue) .body > div.e { + display: none; +} +body.filterIssue .body > div:not(.e) { + display: none; +} +body.filterIssue #moreButton { + display: none; +} + +body[data-should-update-lists]:not(.updated) .e .createEntry { + opacity: 0.25; + pointer-events: none; +} + +body:not([data-should-update-lists]) .shouldUpdate { + display: none; + } +body.updating { + pointer-events: none; + } +body.updating button { + filter: grayscale(1); + opacity: 0.5; + } +body.updated .shouldUpdate button { + display: none; + } +body.updating .shouldUpdate button .fa-icon svg { + animation: spin 1s linear infinite; + transform-origin: 50%; + } +body .shouldUpdate .updated { + align-self: center; + } +body:not(.updated) .shouldUpdate .updated { + display: none; + } + +button { + align-self: center; + } +span[data-url] { + color: var(--link-ink); + cursor: pointer; + } + +#showSupportInfo { + cursor: pointer; + } + +body.redacted #redactButton { + display: none; + } +#unredactButton { + display: none; + } +body.redacted #unredactButton { + display: inline; + } + +.cm-string.cm-property { + color: black; + } diff --git a/src/css/themes/default.css b/src/css/themes/default.css new file mode 100644 index 0000000..c37bd28 --- /dev/null +++ b/src/css/themes/default.css @@ -0,0 +1,526 @@ +/** + + References: + https://protocol.mozilla.org/ + https://material.io/ + + Color names from: + https://protocol.mozilla.org/docs/fundamentals/color.html + + Tools: + Lightness validator: https://www.hsluv.org/ + Contrast validator: https://bernaferrari.github.io/color-studio/#/ +*/ +:root { + --blue-5: 170 242 255; + --blue-10: 128 235 255; + --blue-20: 0 221 255; + --blue-30: 0 179 244; + --blue-40: 0 144 237; + --blue-50: 0 96 223; + --blue-60: 2 80 187; + --blue-70: 5 64 150; + --blue-80: 7 48 114; + --blue-90: 9 32 77; + --dark-gray-10: 82 82 94; + --dark-gray-20: 74 74 85; + --dark-gray-30: 66 65 77; + --dark-gray-40: 58 57 68; + --dark-gray-50: 50 49 60; + --dark-gray-60: 43 42 51; + --dark-gray-70: 35 34 43; + --dark-gray-80: 28 27 34; + --dark-gray-90: 21 20 26; + --green-30: 136 255 209; + --green-40: 84 255 189; + --green-50: 63 225 176; + --green-60: 42 195 162; + --green-65: 21 165 149; + --green-70: 0 135 135; + --green-80: 0 94 94; + --ink-10: 57 52 115; + --ink-80: 32 18 58; + --light-gray-10: 249 249 251; + --light-gray-20: 240 240 244; + --light-gray-30: 224 224 230; + --light-gray-40: 207 207 216; + --light-gray-50: 191 191 201; + --light-gray-60: 175 175 186; + --light-gray-70: 159 159 173; + --light-gray-80: 143 143 158; + --light-gray-90: 128 128 143; + --orange-5: 255 244 222; + --orange-10: 255 213 178; + --orange-20: 255 181 135; + --orange-30: 255 162 102; + --orange-40: 255 138 80; + --orange-50: 255 113 57; + --orange-60: 226 89 32; + --orange-70: 204 61 0; + --orange-80: 158 40 11; + --orange-90: 124 21 4; + --purple-5: 247 226 255; + --purple-10: 246 184 255; + --purple-20: 246 143 255; + --purple-30: 247 112 255; + --purple-40: 215 76 240; + --purple-50: 184 51 225; + --purple-60: 149 43 185; + --purple-70: 114 34 145; + --purple-80: 78 26 105; + --purple-90: 43 17 65; + --red-20: 255 154 162; + --red-30: 255 132 139; + --red-40: 255 106 117; + --red-50: 255 79 94; + --red-60: 226 40 80; + --red-70: 197 0 66; + --violet-5: 231 223 255; + --violet-10: 217 191 255; + --violet-20: 203 158 255; + --violet-30: 198 137 255; + --violet-40: 171 113 255; + --violet-50: 144 89 255; + --violet-60: 117 66 229; + --violet-70: 89 42 203; + --violet-80: 69 39 141; + --violet-90: 50 28 100; + --yellow-5: 255 255 204; + --yellow-10: 255 255 152; + --yellow-20: 255 234 128; + --yellow-30: 255 213 103; + --yellow-40: 255 189 79; + --yellow-50: 255 164 54; + --yellow-60: 226 127 46; + --yellow-70: 196 90 39; + --yellow-80: 167 52 31; + --yellow-90: 150 14 24; + + /* + * Reference gray: -light-gray-90, then calibrated with hsluv.org, where + * the number is Luv. + * + * */ + --gray-5: 16 16 22; + --gray-10: 27 27 35; + --gray-15: 37 37 47; + --gray-20: 47 47 59; + --gray-25: 58 58 72; + --gray-30: 69 69 85; + --gray-35: 81 81 98; + --gray-40: 93 93 110; + --gray-45: 105 105 121; + --gray-50: 118 118 133; + --gray-55: 131 131 145; + --gray-60: 144 144 156; + --gray-65: 157 157 168; + --gray-70: 170 170 180; + --gray-75: 184 184 192; + --gray-80: 198 198 204; + --gray-85: 212 212 217; + --gray-90: 226 226 229; + --gray-95: 240 240 242; +} + +/* + * Font + * + * */ +:root { + --font-size: 14px; + --font-size-smaller: calc(var(--font-size) - 1px); + --font-size-xsmall: calc(var(--font-size) - 3px); + --font-size-larger: 15px; + --font-family: Inter, sans-serif; + --monospace-size: 12px; +} + +:root.mobile { + --font-size: 16px; + --font-size-smaller: 14px; + --monospace-size: 13px; +} + +/* + * Default color theme + * + * Tool: hsluv.org + * + * */ +:root /* h255 */ { + --primary-5: 3 16 40; /* S:90 Luv:5 */ + --primary-10: 5 27 59; /* S:90 Luv:10 */ + --primary-20: 14 47 95; /* S:90 Luv:20 */ + --primary-30: 24 69 134; /* S:90 Luv:30 */ + --primary-40: 34 93 176; /* S:90 Luv:40 */ + --primary-50: 45 117 219; /* S:90 Luv:50 */ + --primary-60: 86 143 244; /* S:90 Luv:60 */ + --primary-70: 137 170 247; /* S:90 Luv:70 */ + --primary-80: 179 198 250; /* S:90 Luv:80 */ + --primary-90: 218 226 252; /* S:90 Luv:90 */ + --primary-95: 236 240 254; /* S:90 Luv:95 */ + } + +/* + * Default dark theme starts here + * + * https://github.com/uBlockOrigin/uBlock-issues/issues/1027#issuecomment-629641072 + * Assign a default background color if dark mode is enabled -- hopefully + * this will avoid flashes of white background until the document's own CSS + * overrides the default color value below. + * + * */ +@media (prefers-color-scheme: light) { + :root { + --surface-0-rgb: 255 255 255; + --surface-1: rgb(var(--gray-95)); + --surface-2: rgb(var(--gray-90)); + --surface-3: rgb(var(--gray-80)); + } +} +@media (prefers-color-scheme: dark) { + :root { + --surface-0-rgb: 0 0 0; + --surface-1: rgb(var(--gray-10)); + --surface-2: rgb(var(--gray-20)); + --surface-3: rgb(var(--gray-30)); + } +} + +:root.light { + --surface-0-rgb: 255 255 255; + --surface-1: rgb(var(--gray-95)); + --surface-2: rgb(var(--gray-90)); + --surface-3: rgb(var(--gray-80)); +} + +:root.dark { + --surface-0-rgb: 0 0 0; + --surface-1: rgb(var(--gray-10)); + --surface-2: rgb(var(--gray-20)); + --surface-3: rgb(var(--gray-30)); +} + +/* + * Components + * + * */ +:root { + --font-size: 14px; + + --ubo-red: #800000; + + --elevation-up-surface: black; + --elevation-up1-opacity: 4%; + --elevation-up2-opacity: 8%; + --elevation-down-surface: white; + --elevation-down1-opacity: 16%; + --elevation-down2-opacity: 32%; + + /* https://material.io/design/color/text-legibility.html#text-backgrounds */ + --ink-rgb: var(--ink-80); + --ink-0: black; + --ink-100: white; + + --border-1: rgb(var(--gray-75)); + --border-2: rgb(var(--gray-70)); + --border-3: rgb(var(--gray-65)); + --border-4: rgb(var(--gray-60)); + + --accent-ink-3: var(--ink-1); + --accent-surface-1: rgb(var(--primary-40)); + + --link-ink: rgb(var(--primary-40)); + --link-hover-ink: rgb(var(--primary-30)); + + /* buttons */ + --button-surface-rgb: var(--gray-80); + + --dashboard-tab-active-ink-rgb: var(--primary-40); + --dashboard-tab-focus-surface-rgb: var(--primary-90); + --dashboard-highlight-surface-rgb: var(--primary-90); + + --dashboard-happy-green: rgb(var(--green-65)); + + /* popup panel */ + --popup-cell-cname-ink: #0054d7; /* h260 S:100 Luv:40 */; + --popup-cell-label-mixed-surface: #c29100; /* TODO: fix */ + --popup-icon-x-ink: rgb(var(--red-60)); + --popup-power-ink-rgb: var(--primary-50); + + /* horizontal line separator */ + --hr-ink: var(--surface-2); + + /* cloud widget */ + --cloud-total-used-surface: rgb(var(--violet-60) / 25%); + --cloud-used-surface: rgb(var(--violet-60)); + + /* misc */ + --error-surface: #c00004; /* h:12 S:100 Luv:40 */ + + /* codemirror */ + --cm-active-line: rgb(var(--gray-90)); + --cm-cursor: var(--ink-0); + --cm-foldmarker-ink: rgb(var(--blue-40)); + --cm-gutter-border: var(--surface-1); + --cm-gutter-ink: var(--ink-3); + --cm-gutter-surface: var(--surface-2); + --cm-matchingbracket: rgb(var(--green-30)); + --cm-merge-copy-ink: rgb(var(--blue-50)); + --cm-merge-chunk-border: rgb(var(--surface-0-rgb) / 40%); + --cm-merge-chunk-surface: rgb(var(--surface-0-rgb) / 40%); + --cm-negative: #e32f00; /* h:15 S:100 Luv:50 */ + --cm-positive: #008a21; /* h:130 S:100 Luv:50 */ + --cm-selection-surface: rgb(var(--gray-80)); + --cm-selection-focused-surface: rgb(var(--primary-80)); + --cm-searching-ink: black; + --cm-searching-surface: #fee300cc /* h75 S:100 Luv:90 a:80% */; + --cm-search-match-surface: rgb(var(--yellow-40) / 50%); + + /* syntax highlight: static filtering */ + --sf-comment-ink: var(--ink-3); + --sf-def-ink: #3c3aff; /* h:266 S:100 Luv:40 */ + --sf-directive-ink: var(--ink-1); + --sf-error-ink: #ff8981; /* h15 S:100 Luv:70 */ + --sf-error-surface: #ff898133; /* h15 S:100 Luv:70 @ 20% */ + --sf-keyword-ink: #9b00ca; /* h:290 S:100 Luv:40 */ + --sf-notice-ink: var(--ink-4); + --sf-readonly-ink: var(--ink-3); + --sf-tag-ink: #006e2e /* h:135 S:100 Luv:40 */; + --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-surface: #e49d0033; /* h:50 S:100 Luv:70 @ 20% */ + + /* syntax highlight: dynamic filtering */ + --df-allow-ink: var(--cm-positive); + --df-block-ink: var(--cm-negative); + --df-noop-ink: rgb(var(--dark-gray-10)); + + /* logger */ + --logger-modified-surface: #0000c010; + --logger-modified-em-surface: #0000c028; + --logger-redirected-surface: rgb(var(--yellow-5) / 50%); + --logger-scriptlet-surface: rgb(var(--yellow-30) / 50%); +} + +/* https://material.io/design/color/dark-theme.html */ +:root.dark { + --elevation-down-surface: black; + --elevation-down1-opacity: 16%; + --elevation-down2-opacity: 32%; + --elevation-up-surface: white; + --elevation-up1-opacity: 12%; + --elevation-up2-opacity: 24%; + + --ink-rgb: var(--gray-95); + --ink-0: white; + --ink-100: black; + + --border-1: rgb(var(--gray-35)); + --border-2: rgb(var(--gray-40)); + --border-3: rgb(var(--gray-45)); + --border-4: rgb(var(--gray-50)); + + --accent-surface-1: rgb(var(--primary-70)); + + --link-ink: rgb(var(--primary-70)); + --link-hover-ink: rgb(var(--primary-80)); + + /* buttons */ + --button-surface-rgb: var(--gray-30); + + --dashboard-tab-active-ink-rgb: var(--primary-70); + --dashboard-tab-focus-surface-rgb: var(--primary-20); + --dashboard-highlight-surface-rgb: var(--primary-20); + + /* popup panel */ + --popup-cell-cname-ink: #93a6ff; /* h260 S:100 Luv:70 */; + --popup-cell-label-mixed-surface: hsla(45, 100%, 38%, 1); /* TODO: fix */ + --popup-icon-x-ink: rgb(var(--red-50)); + --popup-power-ink-rgb: var(--primary-60); + + /* cloud widget */ + --cloud-total-used-surface: rgb(var(--violet-20) / 25%); + --cloud-used-surface: rgb(var(--violet-20)); + + /* misc */ + --error-surface: #ff5354; /* h:12 S:100 Luv:60 */ + + /* codemirror */ + --cm-active-line: rgb(var(--gray-20)); + --cm-merge-copy-ink: rgb(var(--blue-30)); + --cm-foldmarker-ink: rgb(var(--blue-20)); + --cm-matchingbracket: rgb(var(--green-30) / 50%); + --cm-negative: #ff8982; /* h:15 S:100 Luv:70 */ + --cm-positive: #00c634; /* h:130 S:100 Luv:70 */ + --cm-selection-surface: rgb(var(--gray-40)); + --cm-selection-focused-surface: rgb(var(--primary-40)); + --cm-searching-ink: black; + --cm-searching-surface: #fee300cc /* h75 S:100 Luv:90 a:80% */; + + /* syntax highlight: static filtering */ + --sf-comment-ink: var(--ink-3); + --sf-def-ink: #a2a2ff; /* h:266 S:100 Luv:70 */ + --sf-error-ink: #ff8981; /* h15 S:100 Luv:70 */ + --sf-error-surface: #ff898166; /* h15 S:100 Luv:70 @ 40% */ + --sf-keyword-ink: #d78dff; /* h:290 S:100 Luv:70 */ + --sf-tag-ink: #00c559 /* h:135 S:100 Luv:70 */; + --sf-value-ink: #ff8d48 /* h:30 S:100 Luv:70 */; + --sf-variable-ink: var(--ink-1); + --sf-warning-ink: #e49d00; /* h:50 S:100 Luv:70 */ + --sf-warning-surface: #e49d0066; /* h:50 S:100 Luv:50 @ 40% */ + + /* syntax highlight: dynamic filtering */ + --df-noop-ink: var(--ink-3); + + /* logger */ + --logger-modified-surface: #663efd60; + --logger-redirected-surface: rgb(var(--yellow-5) / 40%); + --logger-scriptlet-surface: rgb(var(--yellow-30) / 40%); +} + +:root.dark input, +:root.dark select, +:root.dark textarea { + color-scheme: dark; +} + +/* + * Shared declarations + * */ +:root { + --high-em: 87%; + --medium-em: 60%; + --low-em: 38%; + + --surface-0: rgb(var(--surface-0-rgb)); + + --ink-1: rgb(var(--ink-rgb)); + --ink-2: rgb(var(--ink-rgb) / var(--high-em)); + --ink-3: rgb(var(--ink-rgb) / var(--medium-em)); + --ink-4: rgb(var(--ink-rgb) / var(--low-em)); + + --accent-ink-1: var(--surface-0); + --accent-ink-3: var(--ink-1); + + --subtil-ink: var(--accent-surface-1); + + --fieldset-header-surface: transparent; + --fieldset-header-ink: var(--ink-2); + + --button-ink: var(--ink-1); + --button-surface: rgb(var(--button-surface-rgb)); + --button-border-radius: 5px; + --button-preferred-ink: var(--accent-ink-1); + --button-preferred-surface: var(--accent-surface-1); + --button-disabled-surface: var(--surface-3); + --button-disabled-filter: opacity(50%); + + --checkbox-size: calc(var(--font-size) + 2px); + --checkbox-ink: var(--ink-3); + --checkbox-checked-ink: var(--accent-surface-1); + --checkbox-disabled-filter: opacity(50%); + --checkbox-margin-end: calc(var(--font-size) * 0.75); + + --notice-ink: var(--accent-ink-1); + --notice-surface: var(--accent-surface-1); + --notice-surface-shadow: #000 0 2px 8px; + + --dashboard-tab-ink: var(--ink-1); + --dashboard-tab-active-ink: rgb(var(--dashboard-tab-active-ink-rgb)); + --dashboard-tab-active-surface: transparent; + --dashboard-tab-focus-surface: rgb(var(--dashboard-tab-focus-surface-rgb)); + --dashboard-tab-hover-surface: var(--surface-2); + --dashboard-tab-hover-border: var(--surface-3); + + /* info levels: normal, fyi, warn, error -- we want same Luv */ + --info0-ink-rgb: 119 119 119; /* h: 0 S: 0 Luv:60 */ + --info1-ink-rgb: 72 143 255; /* h:255 S:100 Luv:60 */ + --info2-ink-rgb: 208 125 0; /* h: 40 S:100 Luv:60 */ + --info3-ink-rgb: 255 82 94; /* h: 10 S:100 Luv:60 */ + --info0-ink: rgb(var(--info0-ink-rgb)); + --info1-ink: rgb(var(--info1-ink-rgb)); + --info2-ink: rgb(var(--info2-ink-rgb)); + --info3-ink: rgb(var(--info3-ink-rgb)); + + --popup-cell-surface: var(--surface-2); + --popup-cell-label-filter: opacity(40%); + --popup-cell-allow-own-surface: rgb(var(--popup-cell-allow-own-surface-rgb)); + --popup-cell-allow-surface: rgb(var(--popup-cell-allow-surface-rgb)); + --popup-cell-noop-own-surface: rgb(var(--popup-cell-noop-own-surface-rgb)); + --popup-cell-noop-surface: rgb(var(--popup-cell-noop-surface-rgb)); + --popup-cell-block-own-surface: rgb(var(--popup-cell-block-own-surface-rgb)); + --popup-cell-block-surface: rgb(var(--popup-cell-block-surface-rgb)); + --popup-power-ink: rgb(var(--popup-power-ink-rgb)); + --popup-toolbar-surface: rgb(var(--primary-80) / 15%); + --popup-toolbar-surface-hover: rgb(var(--primary-80) / 20%); + --popup-ruleset-tool-ink: var(--ink-1); + --popup-ruleset-tool-surface: rgb(var(--primary-80) / 15%); + --popup-ruleset-tool-surface-hover: rgb(var(--primary-80) / 20%); + --popup-ruleset-tool-shadow: transparent; +} + +/* + * Rule colors + * */ +:root:not(.dark):not(.colorBlind) { + --popup-cell-allow-own-surface-rgb: 0 127 0; /* h:127.7 S:100 Luv:45 */ + --popup-cell-allow-surface-rgb: 129 202 129; /* h:127.7 S:50 Luv:75 */ + --popup-cell-block-own-surface-rgb: 216 0 0; /* h:12.2 S:100 Luv:45 */ + --popup-cell-block-surface-rgb: 224 172 172; /* h:12.2 S:50 Luv:75 */ + --popup-cell-noop-own-surface-rgb: 107 107 107; /* h:0 S:0 Luv:45 */ + --popup-cell-noop-surface-rgb: 185 185 185; /* h:0 S:0 Luv:75 */ +} + +:root.dark:not(.colorBlind) { + --popup-cell-allow-own-surface-rgb: 0 153 0; /* h:127.7 S:100 Luv:55 */ + --popup-cell-allow-surface-rgb: 73 117 73; /* h:127.7 S:50 Luv:45 */ + --popup-cell-block-own-surface-rgb: 255 40 40; /* h:12.2 S:100 Luv:55 */ + --popup-cell-block-surface-rgb: 175 74 74; /* h:12.2 S:50 Luv:45 */ + --popup-cell-noop-own-surface-rgb: 132 132 132; /* h:0 S:0 Luv:55 */ + --popup-cell-noop-surface-rgb: 94 94 94; /* h:0 S:0 Luv:40 */ +} + +/* + * Source for color-blind color scheme: + * https://davidmathlogic.com/colorblind/ + * First pair in "Accessible palettes" + * + * */ +:root.colorBlind { + --popup-cell-allow-own-surface-rgb: 151 113 0; /* h:58.5 S:100 Luv:50 */ + --popup-cell-block-own-surface-rgb: 0 120 216; /* h:252 S:100 Luv:50 */ + --popup-cell-noop-own-surface-rgb: 119 119 119; /* h:0 S:0 Luv:50 */ + --popup-cell-label-mixed-surface: #ff6a00; /* TODO: fix */ +} +:root.colorBlind:not(.dark) { + --popup-cell-allow-surface-rgb: 223 178 92; /* h:58.5 S:75 Luv:75 */ + --popup-cell-block-surface-rgb: 159 185 238; /* h:252 S:75 Luv:75 */ + --popup-cell-noop-surface-rgb: 185 185 185; /* h:0 S:0 Luv:75 */ +} +:root.dark.colorBlind { + --popup-cell-allow-surface-rgb: 115 91 44; /* h:58.5 S:75 Luv:40 */ + --popup-cell-block-surface-rgb: 53 95 154; /* h:252 S:75 Luv:40 */ + --popup-cell-noop-surface-rgb: 94 94 94; /* h:0 S:0 Luv:40 */ +} + +:root.classic:not(.dark) { + --notice-ink: rgb(var(--ink-80)); + --notice-surface: rgb(var(--yellow-5)); + --popup-power-ink-rgb: 0 110 254; + --popup-ruleset-tool-ink: var(--ink-1); + --popup-ruleset-tool-surface: rgb(var(--yellow-5) / 50%); + --popup-ruleset-tool-surface-hover: rgb(var(--yellow-5) / 75%); + --popup-ruleset-tool-shadow: rgb(var(--gray-85)); +} + +/* + * Experiment: use Firefox for Android dark theme colors +:root.mobile.dark { + --gray-10: 43 42 51; + --gray-20: 66 65 77; + --ink-rgb: 251 251 254; +} +*/ diff --git a/src/css/whitelist.css b/src/css/whitelist.css new file mode 100644 index 0000000..715c964 --- /dev/null +++ b/src/css/whitelist.css @@ -0,0 +1,22 @@ +html { + height: 100vh; + overflow: hidden; + width: 100vw; + } +body { + display: flex; + flex-direction: column; + height: 100%; + justify-content: stretch; + overflow: hidden; + width: 100%; + } +.body { + flex-shrink: 0; + } +.codeMirrorContainer { + flex-grow: 1; + } +#whitelist { + text-align: left; + } diff --git a/src/dashboard.html b/src/dashboard.html new file mode 100644 index 0000000..859de58 --- /dev/null +++ b/src/dashboard.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + +
+ +
+
+
+   +   + +
+
+
+ + + + + + + + + + + + + + diff --git a/src/devtools.html b/src/devtools.html new file mode 100644 index 0000000..af7b972 --- /dev/null +++ b/src/devtools.html @@ -0,0 +1,59 @@ + + + + + +uBlock — Dev tools + + + + + + + + + + + + + + + + +
+

+ + + + + + + + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/document-blocked.html b/src/document-blocked.html new file mode 100644 index 0000000..80a4546 --- /dev/null +++ b/src/document-blocked.html @@ -0,0 +1,64 @@ + + + + + + + + + + + + + +
+ + +
+

_

+ +
+ +
+

_

+

 

+ +
+ +
+ +
+ +
+ + + +
+ + +
+ + + + + + + + + + + + diff --git a/src/dyna-rules.html b/src/dyna-rules.html new file mode 100644 index 0000000..c9dd3bc --- /dev/null +++ b/src/dyna-rules.html @@ -0,0 +1,67 @@ + + + + + +uBlock — Dynamic filtering rules + + + + + + + + + + + + + + +
+
+

info-circle

+
+
+
+
+ + +
+
+
+ + + +
+
+
+
+
+ filter  double-angle-up +
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/src/img/cloud.png b/src/img/cloud.png new file mode 100644 index 0000000..6c78dde Binary files /dev/null and b/src/img/cloud.png differ diff --git a/src/img/flags-of-the-world/README b/src/img/flags-of-the-world/README new file mode 100644 index 0000000..d388796 --- /dev/null +++ b/src/img/flags-of-the-world/README @@ -0,0 +1,9 @@ +Source of all images in this folder: + https://flagpedia.net/ + +Licence: + https://flagpedia.net/about + +> Flag images are in the public domain (exempt from copyright). +> They are completely free for non-commercial and even commercial use. +> You can also download all flags." diff --git a/src/img/flags-of-the-world/ad.png b/src/img/flags-of-the-world/ad.png new file mode 100644 index 0000000..4df2966 Binary files /dev/null and b/src/img/flags-of-the-world/ad.png differ diff --git a/src/img/flags-of-the-world/ae.png b/src/img/flags-of-the-world/ae.png new file mode 100644 index 0000000..c182e95 Binary files /dev/null and b/src/img/flags-of-the-world/ae.png differ diff --git a/src/img/flags-of-the-world/af.png b/src/img/flags-of-the-world/af.png new file mode 100644 index 0000000..a8fc95d Binary files /dev/null and b/src/img/flags-of-the-world/af.png differ diff --git a/src/img/flags-of-the-world/ag.png b/src/img/flags-of-the-world/ag.png new file mode 100644 index 0000000..4b54da8 Binary files /dev/null and b/src/img/flags-of-the-world/ag.png differ diff --git a/src/img/flags-of-the-world/ai.png b/src/img/flags-of-the-world/ai.png new file mode 100644 index 0000000..c536a35 Binary files /dev/null and b/src/img/flags-of-the-world/ai.png differ diff --git a/src/img/flags-of-the-world/al.png b/src/img/flags-of-the-world/al.png new file mode 100644 index 0000000..6d70fe9 Binary files /dev/null and b/src/img/flags-of-the-world/al.png differ diff --git a/src/img/flags-of-the-world/am.png b/src/img/flags-of-the-world/am.png new file mode 100644 index 0000000..2d9be46 Binary files /dev/null and b/src/img/flags-of-the-world/am.png differ diff --git a/src/img/flags-of-the-world/ao.png b/src/img/flags-of-the-world/ao.png new file mode 100644 index 0000000..0b4e533 Binary files /dev/null and b/src/img/flags-of-the-world/ao.png differ diff --git a/src/img/flags-of-the-world/aq.png b/src/img/flags-of-the-world/aq.png new file mode 100644 index 0000000..1f1f14a Binary files /dev/null and b/src/img/flags-of-the-world/aq.png differ diff --git a/src/img/flags-of-the-world/ar.png b/src/img/flags-of-the-world/ar.png new file mode 100644 index 0000000..394ac6a Binary files /dev/null and b/src/img/flags-of-the-world/ar.png differ diff --git a/src/img/flags-of-the-world/as.png b/src/img/flags-of-the-world/as.png new file mode 100644 index 0000000..0a2075e Binary files /dev/null and b/src/img/flags-of-the-world/as.png differ diff --git a/src/img/flags-of-the-world/at.png b/src/img/flags-of-the-world/at.png new file mode 100644 index 0000000..f89b8b4 Binary files /dev/null and b/src/img/flags-of-the-world/at.png differ diff --git a/src/img/flags-of-the-world/au.png b/src/img/flags-of-the-world/au.png new file mode 100644 index 0000000..e44d53e Binary files /dev/null and b/src/img/flags-of-the-world/au.png differ diff --git a/src/img/flags-of-the-world/aw.png b/src/img/flags-of-the-world/aw.png new file mode 100644 index 0000000..50cd2e8 Binary files /dev/null and b/src/img/flags-of-the-world/aw.png differ diff --git a/src/img/flags-of-the-world/ax.png b/src/img/flags-of-the-world/ax.png new file mode 100644 index 0000000..9f49dcc Binary files /dev/null and b/src/img/flags-of-the-world/ax.png differ diff --git a/src/img/flags-of-the-world/az.png b/src/img/flags-of-the-world/az.png new file mode 100644 index 0000000..5eb5088 Binary files /dev/null and b/src/img/flags-of-the-world/az.png differ diff --git a/src/img/flags-of-the-world/ba.png b/src/img/flags-of-the-world/ba.png new file mode 100644 index 0000000..31ae9f6 Binary files /dev/null and b/src/img/flags-of-the-world/ba.png differ diff --git a/src/img/flags-of-the-world/bb.png b/src/img/flags-of-the-world/bb.png new file mode 100644 index 0000000..a754379 Binary files /dev/null and b/src/img/flags-of-the-world/bb.png differ diff --git a/src/img/flags-of-the-world/bd.png b/src/img/flags-of-the-world/bd.png new file mode 100644 index 0000000..9cd5932 Binary files /dev/null and b/src/img/flags-of-the-world/bd.png differ diff --git a/src/img/flags-of-the-world/be.png b/src/img/flags-of-the-world/be.png new file mode 100644 index 0000000..5c72923 Binary files /dev/null and b/src/img/flags-of-the-world/be.png differ diff --git a/src/img/flags-of-the-world/bf.png b/src/img/flags-of-the-world/bf.png new file mode 100644 index 0000000..ff6d6d2 Binary files /dev/null and b/src/img/flags-of-the-world/bf.png differ diff --git a/src/img/flags-of-the-world/bg.png b/src/img/flags-of-the-world/bg.png new file mode 100644 index 0000000..699d315 Binary files /dev/null and b/src/img/flags-of-the-world/bg.png differ diff --git a/src/img/flags-of-the-world/bh.png b/src/img/flags-of-the-world/bh.png new file mode 100644 index 0000000..025124d Binary files /dev/null and b/src/img/flags-of-the-world/bh.png differ diff --git a/src/img/flags-of-the-world/bi.png b/src/img/flags-of-the-world/bi.png new file mode 100644 index 0000000..2153878 Binary files /dev/null and b/src/img/flags-of-the-world/bi.png differ diff --git a/src/img/flags-of-the-world/bj.png b/src/img/flags-of-the-world/bj.png new file mode 100644 index 0000000..ffc7c29 Binary files /dev/null and b/src/img/flags-of-the-world/bj.png differ diff --git a/src/img/flags-of-the-world/bl.png b/src/img/flags-of-the-world/bl.png new file mode 100644 index 0000000..6a9d436 Binary files /dev/null and b/src/img/flags-of-the-world/bl.png differ diff --git a/src/img/flags-of-the-world/bm.png b/src/img/flags-of-the-world/bm.png new file mode 100644 index 0000000..9646117 Binary files /dev/null and b/src/img/flags-of-the-world/bm.png differ diff --git a/src/img/flags-of-the-world/bn.png b/src/img/flags-of-the-world/bn.png new file mode 100644 index 0000000..0e0cd68 Binary files /dev/null and b/src/img/flags-of-the-world/bn.png differ diff --git a/src/img/flags-of-the-world/bo.png b/src/img/flags-of-the-world/bo.png new file mode 100644 index 0000000..9fb5a4e Binary files /dev/null and b/src/img/flags-of-the-world/bo.png differ diff --git a/src/img/flags-of-the-world/bq.png b/src/img/flags-of-the-world/bq.png new file mode 100644 index 0000000..3d7bc43 Binary files /dev/null and b/src/img/flags-of-the-world/bq.png differ diff --git a/src/img/flags-of-the-world/br.png b/src/img/flags-of-the-world/br.png new file mode 100644 index 0000000..42a6e99 Binary files /dev/null and b/src/img/flags-of-the-world/br.png differ diff --git a/src/img/flags-of-the-world/bs.png b/src/img/flags-of-the-world/bs.png new file mode 100644 index 0000000..a3bdaeb Binary files /dev/null and b/src/img/flags-of-the-world/bs.png differ diff --git a/src/img/flags-of-the-world/bt.png b/src/img/flags-of-the-world/bt.png new file mode 100644 index 0000000..85deabd Binary files /dev/null and b/src/img/flags-of-the-world/bt.png differ diff --git a/src/img/flags-of-the-world/bv.png b/src/img/flags-of-the-world/bv.png new file mode 100644 index 0000000..ae72a77 Binary files /dev/null and b/src/img/flags-of-the-world/bv.png differ diff --git a/src/img/flags-of-the-world/bw.png b/src/img/flags-of-the-world/bw.png new file mode 100644 index 0000000..ee7ba62 Binary files /dev/null and b/src/img/flags-of-the-world/bw.png differ diff --git a/src/img/flags-of-the-world/by.png b/src/img/flags-of-the-world/by.png new file mode 100644 index 0000000..bd52949 Binary files /dev/null and b/src/img/flags-of-the-world/by.png differ diff --git a/src/img/flags-of-the-world/bz.png b/src/img/flags-of-the-world/bz.png new file mode 100644 index 0000000..8165ea0 Binary files /dev/null and b/src/img/flags-of-the-world/bz.png differ diff --git a/src/img/flags-of-the-world/ca.png b/src/img/flags-of-the-world/ca.png new file mode 100644 index 0000000..8f7c4a8 Binary files /dev/null and b/src/img/flags-of-the-world/ca.png differ diff --git a/src/img/flags-of-the-world/cc.png b/src/img/flags-of-the-world/cc.png new file mode 100644 index 0000000..1f6c7dc Binary files /dev/null and b/src/img/flags-of-the-world/cc.png differ diff --git a/src/img/flags-of-the-world/cd.png b/src/img/flags-of-the-world/cd.png new file mode 100644 index 0000000..1d554fa Binary files /dev/null and b/src/img/flags-of-the-world/cd.png differ diff --git a/src/img/flags-of-the-world/cf.png b/src/img/flags-of-the-world/cf.png new file mode 100644 index 0000000..214a4fb Binary files /dev/null and b/src/img/flags-of-the-world/cf.png differ diff --git a/src/img/flags-of-the-world/cg.png b/src/img/flags-of-the-world/cg.png new file mode 100644 index 0000000..8349522 Binary files /dev/null and b/src/img/flags-of-the-world/cg.png differ diff --git a/src/img/flags-of-the-world/ch.png b/src/img/flags-of-the-world/ch.png new file mode 100644 index 0000000..635de7b Binary files /dev/null and b/src/img/flags-of-the-world/ch.png differ diff --git a/src/img/flags-of-the-world/ci.png b/src/img/flags-of-the-world/ci.png new file mode 100644 index 0000000..1093fb9 Binary files /dev/null and b/src/img/flags-of-the-world/ci.png differ diff --git a/src/img/flags-of-the-world/ck.png b/src/img/flags-of-the-world/ck.png new file mode 100644 index 0000000..6387808 Binary files /dev/null and b/src/img/flags-of-the-world/ck.png differ diff --git a/src/img/flags-of-the-world/cl.png b/src/img/flags-of-the-world/cl.png new file mode 100644 index 0000000..4b9e866 Binary files /dev/null and b/src/img/flags-of-the-world/cl.png differ diff --git a/src/img/flags-of-the-world/cm.png b/src/img/flags-of-the-world/cm.png new file mode 100644 index 0000000..5de502c Binary files /dev/null and b/src/img/flags-of-the-world/cm.png differ diff --git a/src/img/flags-of-the-world/cn.png b/src/img/flags-of-the-world/cn.png new file mode 100644 index 0000000..e5b1554 Binary files /dev/null and b/src/img/flags-of-the-world/cn.png differ diff --git a/src/img/flags-of-the-world/co.png b/src/img/flags-of-the-world/co.png new file mode 100644 index 0000000..cc189b9 Binary files /dev/null and b/src/img/flags-of-the-world/co.png differ diff --git a/src/img/flags-of-the-world/cr.png b/src/img/flags-of-the-world/cr.png new file mode 100644 index 0000000..fcf6783 Binary files /dev/null and b/src/img/flags-of-the-world/cr.png differ diff --git a/src/img/flags-of-the-world/cu.png b/src/img/flags-of-the-world/cu.png new file mode 100644 index 0000000..3907e7c Binary files /dev/null and b/src/img/flags-of-the-world/cu.png differ diff --git a/src/img/flags-of-the-world/cv.png b/src/img/flags-of-the-world/cv.png new file mode 100644 index 0000000..35564a2 Binary files /dev/null and b/src/img/flags-of-the-world/cv.png differ diff --git a/src/img/flags-of-the-world/cw.png b/src/img/flags-of-the-world/cw.png new file mode 100644 index 0000000..81397ce Binary files /dev/null and b/src/img/flags-of-the-world/cw.png differ diff --git a/src/img/flags-of-the-world/cx.png b/src/img/flags-of-the-world/cx.png new file mode 100644 index 0000000..bc52786 Binary files /dev/null and b/src/img/flags-of-the-world/cx.png differ diff --git a/src/img/flags-of-the-world/cy.png b/src/img/flags-of-the-world/cy.png new file mode 100644 index 0000000..f8d39ab Binary files /dev/null and b/src/img/flags-of-the-world/cy.png differ diff --git a/src/img/flags-of-the-world/cz.png b/src/img/flags-of-the-world/cz.png new file mode 100644 index 0000000..7f36814 Binary files /dev/null and b/src/img/flags-of-the-world/cz.png differ diff --git a/src/img/flags-of-the-world/de.png b/src/img/flags-of-the-world/de.png new file mode 100644 index 0000000..4d311cc Binary files /dev/null and b/src/img/flags-of-the-world/de.png differ diff --git a/src/img/flags-of-the-world/dj.png b/src/img/flags-of-the-world/dj.png new file mode 100644 index 0000000..806cfdd Binary files /dev/null and b/src/img/flags-of-the-world/dj.png differ diff --git a/src/img/flags-of-the-world/dk.png b/src/img/flags-of-the-world/dk.png new file mode 100644 index 0000000..c5e3711 Binary files /dev/null and b/src/img/flags-of-the-world/dk.png differ diff --git a/src/img/flags-of-the-world/dm.png b/src/img/flags-of-the-world/dm.png new file mode 100644 index 0000000..281e48a Binary files /dev/null and b/src/img/flags-of-the-world/dm.png differ diff --git a/src/img/flags-of-the-world/do.png b/src/img/flags-of-the-world/do.png new file mode 100644 index 0000000..d933f8a Binary files /dev/null and b/src/img/flags-of-the-world/do.png differ diff --git a/src/img/flags-of-the-world/dz.png b/src/img/flags-of-the-world/dz.png new file mode 100644 index 0000000..7d1253b Binary files /dev/null and b/src/img/flags-of-the-world/dz.png differ diff --git a/src/img/flags-of-the-world/ec.png b/src/img/flags-of-the-world/ec.png new file mode 100644 index 0000000..6c88f1f Binary files /dev/null and b/src/img/flags-of-the-world/ec.png differ diff --git a/src/img/flags-of-the-world/ee.png b/src/img/flags-of-the-world/ee.png new file mode 100644 index 0000000..6fcf8cf Binary files /dev/null and b/src/img/flags-of-the-world/ee.png differ diff --git a/src/img/flags-of-the-world/eg.png b/src/img/flags-of-the-world/eg.png new file mode 100644 index 0000000..5fb759e Binary files /dev/null and b/src/img/flags-of-the-world/eg.png differ diff --git a/src/img/flags-of-the-world/eh.png b/src/img/flags-of-the-world/eh.png new file mode 100644 index 0000000..c25436d Binary files /dev/null and b/src/img/flags-of-the-world/eh.png differ diff --git a/src/img/flags-of-the-world/er.png b/src/img/flags-of-the-world/er.png new file mode 100644 index 0000000..d921f3f Binary files /dev/null and b/src/img/flags-of-the-world/er.png differ diff --git a/src/img/flags-of-the-world/es.png b/src/img/flags-of-the-world/es.png new file mode 100644 index 0000000..2e01ce9 Binary files /dev/null and b/src/img/flags-of-the-world/es.png differ diff --git a/src/img/flags-of-the-world/et.png b/src/img/flags-of-the-world/et.png new file mode 100644 index 0000000..211bb9c Binary files /dev/null and b/src/img/flags-of-the-world/et.png differ diff --git a/src/img/flags-of-the-world/fi.png b/src/img/flags-of-the-world/fi.png new file mode 100644 index 0000000..551de7c Binary files /dev/null and b/src/img/flags-of-the-world/fi.png differ diff --git a/src/img/flags-of-the-world/fj.png b/src/img/flags-of-the-world/fj.png new file mode 100644 index 0000000..8f6d8bf Binary files /dev/null and b/src/img/flags-of-the-world/fj.png differ diff --git a/src/img/flags-of-the-world/fk.png b/src/img/flags-of-the-world/fk.png new file mode 100644 index 0000000..12d316c Binary files /dev/null and b/src/img/flags-of-the-world/fk.png differ diff --git a/src/img/flags-of-the-world/fm.png b/src/img/flags-of-the-world/fm.png new file mode 100644 index 0000000..e5aefda Binary files /dev/null and b/src/img/flags-of-the-world/fm.png differ diff --git a/src/img/flags-of-the-world/fo.png b/src/img/flags-of-the-world/fo.png new file mode 100644 index 0000000..56a99a9 Binary files /dev/null and b/src/img/flags-of-the-world/fo.png differ diff --git a/src/img/flags-of-the-world/fr.png b/src/img/flags-of-the-world/fr.png new file mode 100644 index 0000000..8fe5ea4 Binary files /dev/null and b/src/img/flags-of-the-world/fr.png differ diff --git a/src/img/flags-of-the-world/ga.png b/src/img/flags-of-the-world/ga.png new file mode 100644 index 0000000..ffb3f72 Binary files /dev/null and b/src/img/flags-of-the-world/ga.png differ diff --git a/src/img/flags-of-the-world/gb-eng.png b/src/img/flags-of-the-world/gb-eng.png new file mode 100644 index 0000000..13c606d Binary files /dev/null and b/src/img/flags-of-the-world/gb-eng.png differ diff --git a/src/img/flags-of-the-world/gb-nir.png b/src/img/flags-of-the-world/gb-nir.png new file mode 100644 index 0000000..a633386 Binary files /dev/null and b/src/img/flags-of-the-world/gb-nir.png differ diff --git a/src/img/flags-of-the-world/gb-sct.png b/src/img/flags-of-the-world/gb-sct.png new file mode 100644 index 0000000..95dd4f4 Binary files /dev/null and b/src/img/flags-of-the-world/gb-sct.png differ diff --git a/src/img/flags-of-the-world/gb-wls.png b/src/img/flags-of-the-world/gb-wls.png new file mode 100644 index 0000000..a10fe43 Binary files /dev/null and b/src/img/flags-of-the-world/gb-wls.png differ diff --git a/src/img/flags-of-the-world/gb.png b/src/img/flags-of-the-world/gb.png new file mode 100644 index 0000000..8bffe4e Binary files /dev/null and b/src/img/flags-of-the-world/gb.png differ diff --git a/src/img/flags-of-the-world/gd.png b/src/img/flags-of-the-world/gd.png new file mode 100644 index 0000000..3d1dc86 Binary files /dev/null and b/src/img/flags-of-the-world/gd.png differ diff --git a/src/img/flags-of-the-world/ge.png b/src/img/flags-of-the-world/ge.png new file mode 100644 index 0000000..e19f689 Binary files /dev/null and b/src/img/flags-of-the-world/ge.png differ diff --git a/src/img/flags-of-the-world/gf.png b/src/img/flags-of-the-world/gf.png new file mode 100644 index 0000000..03b92f9 Binary files /dev/null and b/src/img/flags-of-the-world/gf.png differ diff --git a/src/img/flags-of-the-world/gg.png b/src/img/flags-of-the-world/gg.png new file mode 100644 index 0000000..7eb8b17 Binary files /dev/null and b/src/img/flags-of-the-world/gg.png differ diff --git a/src/img/flags-of-the-world/gh.png b/src/img/flags-of-the-world/gh.png new file mode 100644 index 0000000..9031733 Binary files /dev/null and b/src/img/flags-of-the-world/gh.png differ diff --git a/src/img/flags-of-the-world/gi.png b/src/img/flags-of-the-world/gi.png new file mode 100644 index 0000000..d96bfdb Binary files /dev/null and b/src/img/flags-of-the-world/gi.png differ diff --git a/src/img/flags-of-the-world/gl.png b/src/img/flags-of-the-world/gl.png new file mode 100644 index 0000000..c9f2504 Binary files /dev/null and b/src/img/flags-of-the-world/gl.png differ diff --git a/src/img/flags-of-the-world/gm.png b/src/img/flags-of-the-world/gm.png new file mode 100644 index 0000000..5c4f1e7 Binary files /dev/null and b/src/img/flags-of-the-world/gm.png differ diff --git a/src/img/flags-of-the-world/gn.png b/src/img/flags-of-the-world/gn.png new file mode 100644 index 0000000..bd100e9 Binary files /dev/null and b/src/img/flags-of-the-world/gn.png differ diff --git a/src/img/flags-of-the-world/gp.png b/src/img/flags-of-the-world/gp.png new file mode 100644 index 0000000..404b667 Binary files /dev/null and b/src/img/flags-of-the-world/gp.png differ diff --git a/src/img/flags-of-the-world/gq.png b/src/img/flags-of-the-world/gq.png new file mode 100644 index 0000000..159cee8 Binary files /dev/null and b/src/img/flags-of-the-world/gq.png differ diff --git a/src/img/flags-of-the-world/gr.png b/src/img/flags-of-the-world/gr.png new file mode 100644 index 0000000..7d782b1 Binary files /dev/null and b/src/img/flags-of-the-world/gr.png differ diff --git a/src/img/flags-of-the-world/gs.png b/src/img/flags-of-the-world/gs.png new file mode 100644 index 0000000..f17c180 Binary files /dev/null and b/src/img/flags-of-the-world/gs.png differ diff --git a/src/img/flags-of-the-world/gt.png b/src/img/flags-of-the-world/gt.png new file mode 100644 index 0000000..463b40d Binary files /dev/null and b/src/img/flags-of-the-world/gt.png differ diff --git a/src/img/flags-of-the-world/gu.png b/src/img/flags-of-the-world/gu.png new file mode 100644 index 0000000..d7c8b85 Binary files /dev/null and b/src/img/flags-of-the-world/gu.png differ diff --git a/src/img/flags-of-the-world/gw.png b/src/img/flags-of-the-world/gw.png new file mode 100644 index 0000000..9f5266f Binary files /dev/null and b/src/img/flags-of-the-world/gw.png differ diff --git a/src/img/flags-of-the-world/gy.png b/src/img/flags-of-the-world/gy.png new file mode 100644 index 0000000..0ad22a7 Binary files /dev/null and b/src/img/flags-of-the-world/gy.png differ diff --git a/src/img/flags-of-the-world/hk.png b/src/img/flags-of-the-world/hk.png new file mode 100644 index 0000000..375395c Binary files /dev/null and b/src/img/flags-of-the-world/hk.png differ diff --git a/src/img/flags-of-the-world/hm.png b/src/img/flags-of-the-world/hm.png new file mode 100644 index 0000000..90cce12 Binary files /dev/null and b/src/img/flags-of-the-world/hm.png differ diff --git a/src/img/flags-of-the-world/hn.png b/src/img/flags-of-the-world/hn.png new file mode 100644 index 0000000..3bedc54 Binary files /dev/null and b/src/img/flags-of-the-world/hn.png differ diff --git a/src/img/flags-of-the-world/hr.png b/src/img/flags-of-the-world/hr.png new file mode 100644 index 0000000..cfee4e4 Binary files /dev/null and b/src/img/flags-of-the-world/hr.png differ diff --git a/src/img/flags-of-the-world/ht.png b/src/img/flags-of-the-world/ht.png new file mode 100644 index 0000000..048d613 Binary files /dev/null and b/src/img/flags-of-the-world/ht.png differ diff --git a/src/img/flags-of-the-world/hu.png b/src/img/flags-of-the-world/hu.png new file mode 100644 index 0000000..93d8a8f Binary files /dev/null and b/src/img/flags-of-the-world/hu.png differ diff --git a/src/img/flags-of-the-world/id.png b/src/img/flags-of-the-world/id.png new file mode 100644 index 0000000..3efe836 Binary files /dev/null and b/src/img/flags-of-the-world/id.png differ diff --git a/src/img/flags-of-the-world/ie.png b/src/img/flags-of-the-world/ie.png new file mode 100644 index 0000000..ae04602 Binary files /dev/null and b/src/img/flags-of-the-world/ie.png differ diff --git a/src/img/flags-of-the-world/il.png b/src/img/flags-of-the-world/il.png new file mode 100644 index 0000000..0728e1b Binary files /dev/null and b/src/img/flags-of-the-world/il.png differ diff --git a/src/img/flags-of-the-world/im.png b/src/img/flags-of-the-world/im.png new file mode 100644 index 0000000..7cd7bfa Binary files /dev/null and b/src/img/flags-of-the-world/im.png differ diff --git a/src/img/flags-of-the-world/in.png b/src/img/flags-of-the-world/in.png new file mode 100644 index 0000000..c0fd2a0 Binary files /dev/null and b/src/img/flags-of-the-world/in.png differ diff --git a/src/img/flags-of-the-world/io.png b/src/img/flags-of-the-world/io.png new file mode 100644 index 0000000..71c045a Binary files /dev/null and b/src/img/flags-of-the-world/io.png differ diff --git a/src/img/flags-of-the-world/iq.png b/src/img/flags-of-the-world/iq.png new file mode 100644 index 0000000..2e529ab Binary files /dev/null and b/src/img/flags-of-the-world/iq.png differ diff --git a/src/img/flags-of-the-world/ir.png b/src/img/flags-of-the-world/ir.png new file mode 100644 index 0000000..6af8d63 Binary files /dev/null and b/src/img/flags-of-the-world/ir.png differ diff --git a/src/img/flags-of-the-world/is.png b/src/img/flags-of-the-world/is.png new file mode 100644 index 0000000..e01f3da Binary files /dev/null and b/src/img/flags-of-the-world/is.png differ diff --git a/src/img/flags-of-the-world/it.png b/src/img/flags-of-the-world/it.png new file mode 100644 index 0000000..c313486 Binary files /dev/null and b/src/img/flags-of-the-world/it.png differ diff --git a/src/img/flags-of-the-world/je.png b/src/img/flags-of-the-world/je.png new file mode 100644 index 0000000..8f049c6 Binary files /dev/null and b/src/img/flags-of-the-world/je.png differ diff --git a/src/img/flags-of-the-world/jm.png b/src/img/flags-of-the-world/jm.png new file mode 100644 index 0000000..ad9acd9 Binary files /dev/null and b/src/img/flags-of-the-world/jm.png differ diff --git a/src/img/flags-of-the-world/jo.png b/src/img/flags-of-the-world/jo.png new file mode 100644 index 0000000..7ba2ecc Binary files /dev/null and b/src/img/flags-of-the-world/jo.png differ diff --git a/src/img/flags-of-the-world/jp.png b/src/img/flags-of-the-world/jp.png new file mode 100644 index 0000000..c1b2f26 Binary files /dev/null and b/src/img/flags-of-the-world/jp.png differ diff --git a/src/img/flags-of-the-world/ke.png b/src/img/flags-of-the-world/ke.png new file mode 100644 index 0000000..4c8ae0b Binary files /dev/null and b/src/img/flags-of-the-world/ke.png differ diff --git a/src/img/flags-of-the-world/kg.png b/src/img/flags-of-the-world/kg.png new file mode 100644 index 0000000..a65c900 Binary files /dev/null and b/src/img/flags-of-the-world/kg.png differ diff --git a/src/img/flags-of-the-world/kh.png b/src/img/flags-of-the-world/kh.png new file mode 100644 index 0000000..55268b9 Binary files /dev/null and b/src/img/flags-of-the-world/kh.png differ diff --git a/src/img/flags-of-the-world/ki.png b/src/img/flags-of-the-world/ki.png new file mode 100644 index 0000000..f000d34 Binary files /dev/null and b/src/img/flags-of-the-world/ki.png differ diff --git a/src/img/flags-of-the-world/km.png b/src/img/flags-of-the-world/km.png new file mode 100644 index 0000000..bdd89a0 Binary files /dev/null and b/src/img/flags-of-the-world/km.png differ diff --git a/src/img/flags-of-the-world/kn.png b/src/img/flags-of-the-world/kn.png new file mode 100644 index 0000000..5bdd1bd Binary files /dev/null and b/src/img/flags-of-the-world/kn.png differ diff --git a/src/img/flags-of-the-world/kp.png b/src/img/flags-of-the-world/kp.png new file mode 100644 index 0000000..10bc580 Binary files /dev/null and b/src/img/flags-of-the-world/kp.png differ diff --git a/src/img/flags-of-the-world/kr.png b/src/img/flags-of-the-world/kr.png new file mode 100644 index 0000000..d8642ca Binary files /dev/null and b/src/img/flags-of-the-world/kr.png differ diff --git a/src/img/flags-of-the-world/kw.png b/src/img/flags-of-the-world/kw.png new file mode 100644 index 0000000..e9f283a Binary files /dev/null and b/src/img/flags-of-the-world/kw.png differ diff --git a/src/img/flags-of-the-world/ky.png b/src/img/flags-of-the-world/ky.png new file mode 100644 index 0000000..ec337e4 Binary files /dev/null and b/src/img/flags-of-the-world/ky.png differ diff --git a/src/img/flags-of-the-world/kz.png b/src/img/flags-of-the-world/kz.png new file mode 100644 index 0000000..ac3c0eb Binary files /dev/null and b/src/img/flags-of-the-world/kz.png differ diff --git a/src/img/flags-of-the-world/la.png b/src/img/flags-of-the-world/la.png new file mode 100644 index 0000000..5fc6bdf Binary files /dev/null and b/src/img/flags-of-the-world/la.png differ diff --git a/src/img/flags-of-the-world/lb.png b/src/img/flags-of-the-world/lb.png new file mode 100644 index 0000000..f8bd972 Binary files /dev/null and b/src/img/flags-of-the-world/lb.png differ diff --git a/src/img/flags-of-the-world/lc.png b/src/img/flags-of-the-world/lc.png new file mode 100644 index 0000000..f901fa7 Binary files /dev/null and b/src/img/flags-of-the-world/lc.png differ diff --git a/src/img/flags-of-the-world/li.png b/src/img/flags-of-the-world/li.png new file mode 100644 index 0000000..8d9246c Binary files /dev/null and b/src/img/flags-of-the-world/li.png differ diff --git a/src/img/flags-of-the-world/lk.png b/src/img/flags-of-the-world/lk.png new file mode 100644 index 0000000..e5a30da Binary files /dev/null and b/src/img/flags-of-the-world/lk.png differ diff --git a/src/img/flags-of-the-world/lr.png b/src/img/flags-of-the-world/lr.png new file mode 100644 index 0000000..6b4e8de Binary files /dev/null and b/src/img/flags-of-the-world/lr.png differ diff --git a/src/img/flags-of-the-world/ls.png b/src/img/flags-of-the-world/ls.png new file mode 100644 index 0000000..257632f Binary files /dev/null and b/src/img/flags-of-the-world/ls.png differ diff --git a/src/img/flags-of-the-world/lt.png b/src/img/flags-of-the-world/lt.png new file mode 100644 index 0000000..d62b622 Binary files /dev/null and b/src/img/flags-of-the-world/lt.png differ diff --git a/src/img/flags-of-the-world/lu.png b/src/img/flags-of-the-world/lu.png new file mode 100644 index 0000000..0659461 Binary files /dev/null and b/src/img/flags-of-the-world/lu.png differ diff --git a/src/img/flags-of-the-world/lv.png b/src/img/flags-of-the-world/lv.png new file mode 100644 index 0000000..892b6d0 Binary files /dev/null and b/src/img/flags-of-the-world/lv.png differ diff --git a/src/img/flags-of-the-world/ly.png b/src/img/flags-of-the-world/ly.png new file mode 100644 index 0000000..4ed1fec Binary files /dev/null and b/src/img/flags-of-the-world/ly.png differ diff --git a/src/img/flags-of-the-world/ma.png b/src/img/flags-of-the-world/ma.png new file mode 100644 index 0000000..6dc87a6 Binary files /dev/null and b/src/img/flags-of-the-world/ma.png differ diff --git a/src/img/flags-of-the-world/mc.png b/src/img/flags-of-the-world/mc.png new file mode 100644 index 0000000..a1ea537 Binary files /dev/null and b/src/img/flags-of-the-world/mc.png differ diff --git a/src/img/flags-of-the-world/md.png b/src/img/flags-of-the-world/md.png new file mode 100644 index 0000000..0c440b4 Binary files /dev/null and b/src/img/flags-of-the-world/md.png differ diff --git a/src/img/flags-of-the-world/me.png b/src/img/flags-of-the-world/me.png new file mode 100644 index 0000000..e591899 Binary files /dev/null and b/src/img/flags-of-the-world/me.png differ diff --git a/src/img/flags-of-the-world/mf.png b/src/img/flags-of-the-world/mf.png new file mode 100644 index 0000000..8fe5ea4 Binary files /dev/null and b/src/img/flags-of-the-world/mf.png differ diff --git a/src/img/flags-of-the-world/mg.png b/src/img/flags-of-the-world/mg.png new file mode 100644 index 0000000..c181ece Binary files /dev/null and b/src/img/flags-of-the-world/mg.png differ diff --git a/src/img/flags-of-the-world/mh.png b/src/img/flags-of-the-world/mh.png new file mode 100644 index 0000000..8b38bc0 Binary files /dev/null and b/src/img/flags-of-the-world/mh.png differ diff --git a/src/img/flags-of-the-world/mk.png b/src/img/flags-of-the-world/mk.png new file mode 100644 index 0000000..bb0c488 Binary files /dev/null and b/src/img/flags-of-the-world/mk.png differ diff --git a/src/img/flags-of-the-world/ml.png b/src/img/flags-of-the-world/ml.png new file mode 100644 index 0000000..70b7e8a Binary files /dev/null and b/src/img/flags-of-the-world/ml.png differ diff --git a/src/img/flags-of-the-world/mm.png b/src/img/flags-of-the-world/mm.png new file mode 100644 index 0000000..d533d86 Binary files /dev/null and b/src/img/flags-of-the-world/mm.png differ diff --git a/src/img/flags-of-the-world/mn.png b/src/img/flags-of-the-world/mn.png new file mode 100644 index 0000000..dcecc72 Binary files /dev/null and b/src/img/flags-of-the-world/mn.png differ diff --git a/src/img/flags-of-the-world/mo.png b/src/img/flags-of-the-world/mo.png new file mode 100644 index 0000000..cbf0a02 Binary files /dev/null and b/src/img/flags-of-the-world/mo.png differ diff --git a/src/img/flags-of-the-world/mp.png b/src/img/flags-of-the-world/mp.png new file mode 100644 index 0000000..b2b13f2 Binary files /dev/null and b/src/img/flags-of-the-world/mp.png differ diff --git a/src/img/flags-of-the-world/mq.png b/src/img/flags-of-the-world/mq.png new file mode 100644 index 0000000..1e339f8 Binary files /dev/null and b/src/img/flags-of-the-world/mq.png differ diff --git a/src/img/flags-of-the-world/mr.png b/src/img/flags-of-the-world/mr.png new file mode 100644 index 0000000..ccd0edf Binary files /dev/null and b/src/img/flags-of-the-world/mr.png differ diff --git a/src/img/flags-of-the-world/ms.png b/src/img/flags-of-the-world/ms.png new file mode 100644 index 0000000..95c4d61 Binary files /dev/null and b/src/img/flags-of-the-world/ms.png differ diff --git a/src/img/flags-of-the-world/mt.png b/src/img/flags-of-the-world/mt.png new file mode 100644 index 0000000..7ca7378 Binary files /dev/null and b/src/img/flags-of-the-world/mt.png differ diff --git a/src/img/flags-of-the-world/mu.png b/src/img/flags-of-the-world/mu.png new file mode 100644 index 0000000..8dee394 Binary files /dev/null and b/src/img/flags-of-the-world/mu.png differ diff --git a/src/img/flags-of-the-world/mv.png b/src/img/flags-of-the-world/mv.png new file mode 100644 index 0000000..2850def Binary files /dev/null and b/src/img/flags-of-the-world/mv.png differ diff --git a/src/img/flags-of-the-world/mw.png b/src/img/flags-of-the-world/mw.png new file mode 100644 index 0000000..8a43fd6 Binary files /dev/null and b/src/img/flags-of-the-world/mw.png differ diff --git a/src/img/flags-of-the-world/mx.png b/src/img/flags-of-the-world/mx.png new file mode 100644 index 0000000..e04b9d7 Binary files /dev/null and b/src/img/flags-of-the-world/mx.png differ diff --git a/src/img/flags-of-the-world/my.png b/src/img/flags-of-the-world/my.png new file mode 100644 index 0000000..2d23b89 Binary files /dev/null and b/src/img/flags-of-the-world/my.png differ diff --git a/src/img/flags-of-the-world/mz.png b/src/img/flags-of-the-world/mz.png new file mode 100644 index 0000000..c360800 Binary files /dev/null and b/src/img/flags-of-the-world/mz.png differ diff --git a/src/img/flags-of-the-world/na.png b/src/img/flags-of-the-world/na.png new file mode 100644 index 0000000..9a15ee1 Binary files /dev/null and b/src/img/flags-of-the-world/na.png differ diff --git a/src/img/flags-of-the-world/nc.png b/src/img/flags-of-the-world/nc.png new file mode 100644 index 0000000..0e935d7 Binary files /dev/null and b/src/img/flags-of-the-world/nc.png differ diff --git a/src/img/flags-of-the-world/ne.png b/src/img/flags-of-the-world/ne.png new file mode 100644 index 0000000..9b602d2 Binary files /dev/null and b/src/img/flags-of-the-world/ne.png differ diff --git a/src/img/flags-of-the-world/nf.png b/src/img/flags-of-the-world/nf.png new file mode 100644 index 0000000..05e5089 Binary files /dev/null and b/src/img/flags-of-the-world/nf.png differ diff --git a/src/img/flags-of-the-world/ng.png b/src/img/flags-of-the-world/ng.png new file mode 100644 index 0000000..30ddc5f Binary files /dev/null and b/src/img/flags-of-the-world/ng.png differ diff --git a/src/img/flags-of-the-world/ni.png b/src/img/flags-of-the-world/ni.png new file mode 100644 index 0000000..4bd0475 Binary files /dev/null and b/src/img/flags-of-the-world/ni.png differ diff --git a/src/img/flags-of-the-world/nl.png b/src/img/flags-of-the-world/nl.png new file mode 100644 index 0000000..724ae2f Binary files /dev/null and b/src/img/flags-of-the-world/nl.png differ diff --git a/src/img/flags-of-the-world/no.png b/src/img/flags-of-the-world/no.png new file mode 100644 index 0000000..ae72a77 Binary files /dev/null and b/src/img/flags-of-the-world/no.png differ diff --git a/src/img/flags-of-the-world/np.png b/src/img/flags-of-the-world/np.png new file mode 100644 index 0000000..c47f80e Binary files /dev/null and b/src/img/flags-of-the-world/np.png differ diff --git a/src/img/flags-of-the-world/nr.png b/src/img/flags-of-the-world/nr.png new file mode 100644 index 0000000..983c5c1 Binary files /dev/null and b/src/img/flags-of-the-world/nr.png differ diff --git a/src/img/flags-of-the-world/nu.png b/src/img/flags-of-the-world/nu.png new file mode 100644 index 0000000..13771aa Binary files /dev/null and b/src/img/flags-of-the-world/nu.png differ diff --git a/src/img/flags-of-the-world/nz.png b/src/img/flags-of-the-world/nz.png new file mode 100644 index 0000000..d3ecec6 Binary files /dev/null and b/src/img/flags-of-the-world/nz.png differ diff --git a/src/img/flags-of-the-world/om.png b/src/img/flags-of-the-world/om.png new file mode 100644 index 0000000..a874081 Binary files /dev/null and b/src/img/flags-of-the-world/om.png differ diff --git a/src/img/flags-of-the-world/pa.png b/src/img/flags-of-the-world/pa.png new file mode 100644 index 0000000..5d7efde Binary files /dev/null and b/src/img/flags-of-the-world/pa.png differ diff --git a/src/img/flags-of-the-world/pe.png b/src/img/flags-of-the-world/pe.png new file mode 100644 index 0000000..b64ad9c Binary files /dev/null and b/src/img/flags-of-the-world/pe.png differ diff --git a/src/img/flags-of-the-world/pf.png b/src/img/flags-of-the-world/pf.png new file mode 100644 index 0000000..9828f06 Binary files /dev/null and b/src/img/flags-of-the-world/pf.png differ diff --git a/src/img/flags-of-the-world/pg.png b/src/img/flags-of-the-world/pg.png new file mode 100644 index 0000000..db8ee16 Binary files /dev/null and b/src/img/flags-of-the-world/pg.png differ diff --git a/src/img/flags-of-the-world/ph.png b/src/img/flags-of-the-world/ph.png new file mode 100644 index 0000000..1c532d7 Binary files /dev/null and b/src/img/flags-of-the-world/ph.png differ diff --git a/src/img/flags-of-the-world/pk.png b/src/img/flags-of-the-world/pk.png new file mode 100644 index 0000000..1bc8e64 Binary files /dev/null and b/src/img/flags-of-the-world/pk.png differ diff --git a/src/img/flags-of-the-world/pl.png b/src/img/flags-of-the-world/pl.png new file mode 100644 index 0000000..9937d81 Binary files /dev/null and b/src/img/flags-of-the-world/pl.png differ diff --git a/src/img/flags-of-the-world/pm.png b/src/img/flags-of-the-world/pm.png new file mode 100644 index 0000000..986d041 Binary files /dev/null and b/src/img/flags-of-the-world/pm.png differ diff --git a/src/img/flags-of-the-world/pn.png b/src/img/flags-of-the-world/pn.png new file mode 100644 index 0000000..da91edb Binary files /dev/null and b/src/img/flags-of-the-world/pn.png differ diff --git a/src/img/flags-of-the-world/pr.png b/src/img/flags-of-the-world/pr.png new file mode 100644 index 0000000..bdd1c9d Binary files /dev/null and b/src/img/flags-of-the-world/pr.png differ diff --git a/src/img/flags-of-the-world/ps.png b/src/img/flags-of-the-world/ps.png new file mode 100644 index 0000000..0fd4a8f Binary files /dev/null and b/src/img/flags-of-the-world/ps.png differ diff --git a/src/img/flags-of-the-world/pt.png b/src/img/flags-of-the-world/pt.png new file mode 100644 index 0000000..ec73093 Binary files /dev/null and b/src/img/flags-of-the-world/pt.png differ diff --git a/src/img/flags-of-the-world/pw.png b/src/img/flags-of-the-world/pw.png new file mode 100644 index 0000000..8f97c9b Binary files /dev/null and b/src/img/flags-of-the-world/pw.png differ diff --git a/src/img/flags-of-the-world/py.png b/src/img/flags-of-the-world/py.png new file mode 100644 index 0000000..f852e0b Binary files /dev/null and b/src/img/flags-of-the-world/py.png differ diff --git a/src/img/flags-of-the-world/qa.png b/src/img/flags-of-the-world/qa.png new file mode 100644 index 0000000..a4e3f73 Binary files /dev/null and b/src/img/flags-of-the-world/qa.png differ diff --git a/src/img/flags-of-the-world/re.png b/src/img/flags-of-the-world/re.png new file mode 100644 index 0000000..7607946 Binary files /dev/null and b/src/img/flags-of-the-world/re.png differ diff --git a/src/img/flags-of-the-world/ro.png b/src/img/flags-of-the-world/ro.png new file mode 100644 index 0000000..fde2356 Binary files /dev/null and b/src/img/flags-of-the-world/ro.png differ diff --git a/src/img/flags-of-the-world/rs.png b/src/img/flags-of-the-world/rs.png new file mode 100644 index 0000000..94980fd Binary files /dev/null and b/src/img/flags-of-the-world/rs.png differ diff --git a/src/img/flags-of-the-world/ru.png b/src/img/flags-of-the-world/ru.png new file mode 100644 index 0000000..d24f786 Binary files /dev/null and b/src/img/flags-of-the-world/ru.png differ diff --git a/src/img/flags-of-the-world/rw.png b/src/img/flags-of-the-world/rw.png new file mode 100644 index 0000000..ea08fbe Binary files /dev/null and b/src/img/flags-of-the-world/rw.png differ diff --git a/src/img/flags-of-the-world/sa.png b/src/img/flags-of-the-world/sa.png new file mode 100644 index 0000000..caa18a5 Binary files /dev/null and b/src/img/flags-of-the-world/sa.png differ diff --git a/src/img/flags-of-the-world/sb.png b/src/img/flags-of-the-world/sb.png new file mode 100644 index 0000000..21b93e8 Binary files /dev/null and b/src/img/flags-of-the-world/sb.png differ diff --git a/src/img/flags-of-the-world/sc.png b/src/img/flags-of-the-world/sc.png new file mode 100644 index 0000000..3a1e558 Binary files /dev/null and b/src/img/flags-of-the-world/sc.png differ diff --git a/src/img/flags-of-the-world/sd.png b/src/img/flags-of-the-world/sd.png new file mode 100644 index 0000000..6234ed3 Binary files /dev/null and b/src/img/flags-of-the-world/sd.png differ diff --git a/src/img/flags-of-the-world/se.png b/src/img/flags-of-the-world/se.png new file mode 100644 index 0000000..1156f2f Binary files /dev/null and b/src/img/flags-of-the-world/se.png differ diff --git a/src/img/flags-of-the-world/sg.png b/src/img/flags-of-the-world/sg.png new file mode 100644 index 0000000..4a6e94b Binary files /dev/null and b/src/img/flags-of-the-world/sg.png differ diff --git a/src/img/flags-of-the-world/sh.png b/src/img/flags-of-the-world/sh.png new file mode 100644 index 0000000..6590d02 Binary files /dev/null and b/src/img/flags-of-the-world/sh.png differ diff --git a/src/img/flags-of-the-world/si.png b/src/img/flags-of-the-world/si.png new file mode 100644 index 0000000..274cd50 Binary files /dev/null and b/src/img/flags-of-the-world/si.png differ diff --git a/src/img/flags-of-the-world/sj.png b/src/img/flags-of-the-world/sj.png new file mode 100644 index 0000000..ae72a77 Binary files /dev/null and b/src/img/flags-of-the-world/sj.png differ diff --git a/src/img/flags-of-the-world/sk.png b/src/img/flags-of-the-world/sk.png new file mode 100644 index 0000000..72b8f4a Binary files /dev/null and b/src/img/flags-of-the-world/sk.png differ diff --git a/src/img/flags-of-the-world/sl.png b/src/img/flags-of-the-world/sl.png new file mode 100644 index 0000000..1010c07 Binary files /dev/null and b/src/img/flags-of-the-world/sl.png differ diff --git a/src/img/flags-of-the-world/sm.png b/src/img/flags-of-the-world/sm.png new file mode 100644 index 0000000..30c9a7e Binary files /dev/null and b/src/img/flags-of-the-world/sm.png differ diff --git a/src/img/flags-of-the-world/sn.png b/src/img/flags-of-the-world/sn.png new file mode 100644 index 0000000..a2f8197 Binary files /dev/null and b/src/img/flags-of-the-world/sn.png differ diff --git a/src/img/flags-of-the-world/so.png b/src/img/flags-of-the-world/so.png new file mode 100644 index 0000000..25b1e1e Binary files /dev/null and b/src/img/flags-of-the-world/so.png differ diff --git a/src/img/flags-of-the-world/sr.png b/src/img/flags-of-the-world/sr.png new file mode 100644 index 0000000..daaf01b Binary files /dev/null and b/src/img/flags-of-the-world/sr.png differ diff --git a/src/img/flags-of-the-world/ss.png b/src/img/flags-of-the-world/ss.png new file mode 100644 index 0000000..95c375c Binary files /dev/null and b/src/img/flags-of-the-world/ss.png differ diff --git a/src/img/flags-of-the-world/st.png b/src/img/flags-of-the-world/st.png new file mode 100644 index 0000000..caca63c Binary files /dev/null and b/src/img/flags-of-the-world/st.png differ diff --git a/src/img/flags-of-the-world/sv.png b/src/img/flags-of-the-world/sv.png new file mode 100644 index 0000000..e5ca956 Binary files /dev/null and b/src/img/flags-of-the-world/sv.png differ diff --git a/src/img/flags-of-the-world/sx.png b/src/img/flags-of-the-world/sx.png new file mode 100644 index 0000000..4041b21 Binary files /dev/null and b/src/img/flags-of-the-world/sx.png differ diff --git a/src/img/flags-of-the-world/sy.png b/src/img/flags-of-the-world/sy.png new file mode 100644 index 0000000..4b9583a Binary files /dev/null and b/src/img/flags-of-the-world/sy.png differ diff --git a/src/img/flags-of-the-world/sz.png b/src/img/flags-of-the-world/sz.png new file mode 100644 index 0000000..515edc6 Binary files /dev/null and b/src/img/flags-of-the-world/sz.png differ diff --git a/src/img/flags-of-the-world/tc.png b/src/img/flags-of-the-world/tc.png new file mode 100644 index 0000000..f66e54f Binary files /dev/null and b/src/img/flags-of-the-world/tc.png differ diff --git a/src/img/flags-of-the-world/td.png b/src/img/flags-of-the-world/td.png new file mode 100644 index 0000000..a1c978a Binary files /dev/null and b/src/img/flags-of-the-world/td.png differ diff --git a/src/img/flags-of-the-world/tf.png b/src/img/flags-of-the-world/tf.png new file mode 100644 index 0000000..72d7a9d Binary files /dev/null and b/src/img/flags-of-the-world/tf.png differ diff --git a/src/img/flags-of-the-world/tg.png b/src/img/flags-of-the-world/tg.png new file mode 100644 index 0000000..5ccbeaf Binary files /dev/null and b/src/img/flags-of-the-world/tg.png differ diff --git a/src/img/flags-of-the-world/th.png b/src/img/flags-of-the-world/th.png new file mode 100644 index 0000000..8a8153a Binary files /dev/null and b/src/img/flags-of-the-world/th.png differ diff --git a/src/img/flags-of-the-world/tj.png b/src/img/flags-of-the-world/tj.png new file mode 100644 index 0000000..1e43ecf Binary files /dev/null and b/src/img/flags-of-the-world/tj.png differ diff --git a/src/img/flags-of-the-world/tk.png b/src/img/flags-of-the-world/tk.png new file mode 100644 index 0000000..939ebd8 Binary files /dev/null and b/src/img/flags-of-the-world/tk.png differ diff --git a/src/img/flags-of-the-world/tl.png b/src/img/flags-of-the-world/tl.png new file mode 100644 index 0000000..528bc82 Binary files /dev/null and b/src/img/flags-of-the-world/tl.png differ diff --git a/src/img/flags-of-the-world/tm.png b/src/img/flags-of-the-world/tm.png new file mode 100644 index 0000000..65ba21e Binary files /dev/null and b/src/img/flags-of-the-world/tm.png differ diff --git a/src/img/flags-of-the-world/tn.png b/src/img/flags-of-the-world/tn.png new file mode 100644 index 0000000..836bbfe Binary files /dev/null and b/src/img/flags-of-the-world/tn.png differ diff --git a/src/img/flags-of-the-world/to.png b/src/img/flags-of-the-world/to.png new file mode 100644 index 0000000..af3c66e Binary files /dev/null and b/src/img/flags-of-the-world/to.png differ diff --git a/src/img/flags-of-the-world/tr.png b/src/img/flags-of-the-world/tr.png new file mode 100644 index 0000000..3848398 Binary files /dev/null and b/src/img/flags-of-the-world/tr.png differ diff --git a/src/img/flags-of-the-world/tt.png b/src/img/flags-of-the-world/tt.png new file mode 100644 index 0000000..76e5e84 Binary files /dev/null and b/src/img/flags-of-the-world/tt.png differ diff --git a/src/img/flags-of-the-world/tv.png b/src/img/flags-of-the-world/tv.png new file mode 100644 index 0000000..9c52a93 Binary files /dev/null and b/src/img/flags-of-the-world/tv.png differ diff --git a/src/img/flags-of-the-world/tw.png b/src/img/flags-of-the-world/tw.png new file mode 100644 index 0000000..ea1c4bc Binary files /dev/null and b/src/img/flags-of-the-world/tw.png differ diff --git a/src/img/flags-of-the-world/tz.png b/src/img/flags-of-the-world/tz.png new file mode 100644 index 0000000..9fa7dbc Binary files /dev/null and b/src/img/flags-of-the-world/tz.png differ diff --git a/src/img/flags-of-the-world/ua.png b/src/img/flags-of-the-world/ua.png new file mode 100644 index 0000000..a2e58d1 Binary files /dev/null and b/src/img/flags-of-the-world/ua.png differ diff --git a/src/img/flags-of-the-world/ug.png b/src/img/flags-of-the-world/ug.png new file mode 100644 index 0000000..72e9898 Binary files /dev/null and b/src/img/flags-of-the-world/ug.png differ diff --git a/src/img/flags-of-the-world/um.png b/src/img/flags-of-the-world/um.png new file mode 100644 index 0000000..2083ae3 Binary files /dev/null and b/src/img/flags-of-the-world/um.png differ diff --git a/src/img/flags-of-the-world/us.png b/src/img/flags-of-the-world/us.png new file mode 100644 index 0000000..2083ae3 Binary files /dev/null and b/src/img/flags-of-the-world/us.png differ diff --git a/src/img/flags-of-the-world/uy.png b/src/img/flags-of-the-world/uy.png new file mode 100644 index 0000000..460cc88 Binary files /dev/null and b/src/img/flags-of-the-world/uy.png differ diff --git a/src/img/flags-of-the-world/uz.png b/src/img/flags-of-the-world/uz.png new file mode 100644 index 0000000..a4124a6 Binary files /dev/null and b/src/img/flags-of-the-world/uz.png differ diff --git a/src/img/flags-of-the-world/va.png b/src/img/flags-of-the-world/va.png new file mode 100644 index 0000000..b543bd2 Binary files /dev/null and b/src/img/flags-of-the-world/va.png differ diff --git a/src/img/flags-of-the-world/vc.png b/src/img/flags-of-the-world/vc.png new file mode 100644 index 0000000..6ec6077 Binary files /dev/null and b/src/img/flags-of-the-world/vc.png differ diff --git a/src/img/flags-of-the-world/ve.png b/src/img/flags-of-the-world/ve.png new file mode 100644 index 0000000..3de0f72 Binary files /dev/null and b/src/img/flags-of-the-world/ve.png differ diff --git a/src/img/flags-of-the-world/vg.png b/src/img/flags-of-the-world/vg.png new file mode 100644 index 0000000..39cc85d Binary files /dev/null and b/src/img/flags-of-the-world/vg.png differ diff --git a/src/img/flags-of-the-world/vi.png b/src/img/flags-of-the-world/vi.png new file mode 100644 index 0000000..b186225 Binary files /dev/null and b/src/img/flags-of-the-world/vi.png differ diff --git a/src/img/flags-of-the-world/vn.png b/src/img/flags-of-the-world/vn.png new file mode 100644 index 0000000..9ba2e9e Binary files /dev/null and b/src/img/flags-of-the-world/vn.png differ diff --git a/src/img/flags-of-the-world/vu.png b/src/img/flags-of-the-world/vu.png new file mode 100644 index 0000000..0bc8fa2 Binary files /dev/null and b/src/img/flags-of-the-world/vu.png differ diff --git a/src/img/flags-of-the-world/wf.png b/src/img/flags-of-the-world/wf.png new file mode 100644 index 0000000..db3b768 Binary files /dev/null and b/src/img/flags-of-the-world/wf.png differ diff --git a/src/img/flags-of-the-world/ws.png b/src/img/flags-of-the-world/ws.png new file mode 100644 index 0000000..8003387 Binary files /dev/null and b/src/img/flags-of-the-world/ws.png differ diff --git a/src/img/flags-of-the-world/xk.png b/src/img/flags-of-the-world/xk.png new file mode 100644 index 0000000..1a6038d Binary files /dev/null and b/src/img/flags-of-the-world/xk.png differ diff --git a/src/img/flags-of-the-world/ye.png b/src/img/flags-of-the-world/ye.png new file mode 100644 index 0000000..1be6876 Binary files /dev/null and b/src/img/flags-of-the-world/ye.png differ diff --git a/src/img/flags-of-the-world/yt.png b/src/img/flags-of-the-world/yt.png new file mode 100644 index 0000000..529ea74 Binary files /dev/null and b/src/img/flags-of-the-world/yt.png differ diff --git a/src/img/flags-of-the-world/za.png b/src/img/flags-of-the-world/za.png new file mode 100644 index 0000000..994a276 Binary files /dev/null and b/src/img/flags-of-the-world/za.png differ diff --git a/src/img/flags-of-the-world/zm.png b/src/img/flags-of-the-world/zm.png new file mode 100644 index 0000000..3c28da4 Binary files /dev/null and b/src/img/flags-of-the-world/zm.png differ diff --git a/src/img/flags-of-the-world/zw.png b/src/img/flags-of-the-world/zw.png new file mode 100644 index 0000000..ef397b5 Binary files /dev/null and b/src/img/flags-of-the-world/zw.png differ diff --git a/src/img/fontawesome/LICENSE.txt b/src/img/fontawesome/LICENSE.txt new file mode 100644 index 0000000..2784b8c --- /dev/null +++ b/src/img/fontawesome/LICENSE.txt @@ -0,0 +1,25 @@ +# [Font Awesome v4.7.0](http://fontawesome.io) +### The iconic font and CSS framework + +Font Awesome is a full suite of 675 pictographic icons for easy scalable vector graphics on websites, +created and maintained by [Dave Gandy](https://twitter.com/davegandy). +Stay up to date with the latest release and announcements on Twitter: +[@fontawesome](http://twitter.com/fontawesome). + +Get started at http://fontawesome.io! + +## License +- The Font Awesome font is licensed under the SIL OFL 1.1: + - http://scripts.sil.org/OFL +- Font Awesome CSS, LESS, and Sass files are licensed under the MIT License: + - https://opensource.org/licenses/mit-license.html +- The Font Awesome documentation is licensed under the CC BY 3.0 License: + - http://creativecommons.org/licenses/by/3.0/ +- Attribution is no longer required as of Font Awesome 3.0, but much appreciated: + - `Font Awesome by Dave Gandy - http://fontawesome.io` +- Full details: http://fontawesome.io/license/ + +## Author +- Email: dave@fontawesome.io +- Twitter: http://twitter.com/davegandy +- GitHub: https://github.com/davegandy diff --git a/src/img/fontawesome/fontawesome-defs.svg b/src/img/fontawesome/fontawesome-defs.svg new file mode 100644 index 0000000..75bc67f --- /dev/null +++ b/src/img/fontawesome/fontawesome-defs.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/img/help16.png b/src/img/help16.png new file mode 100644 index 0000000..32a8b44 Binary files /dev/null and b/src/img/help16.png differ diff --git a/src/img/icon_128.png b/src/img/icon_128.png new file mode 100644 index 0000000..42f2cb4 Binary files /dev/null and b/src/img/icon_128.png differ diff --git a/src/img/icon_16-loading.png b/src/img/icon_16-loading.png new file mode 100644 index 0000000..54d274e Binary files /dev/null and b/src/img/icon_16-loading.png differ diff --git a/src/img/icon_16-off.png b/src/img/icon_16-off.png new file mode 100644 index 0000000..28a7a2a Binary files /dev/null and b/src/img/icon_16-off.png differ diff --git a/src/img/icon_16.png b/src/img/icon_16.png new file mode 100644 index 0000000..d72530a Binary files /dev/null and b/src/img/icon_16.png differ diff --git a/src/img/icon_32-loading.png b/src/img/icon_32-loading.png new file mode 100644 index 0000000..ca3db7e Binary files /dev/null and b/src/img/icon_32-loading.png differ diff --git a/src/img/icon_32-off.png b/src/img/icon_32-off.png new file mode 100644 index 0000000..260df42 Binary files /dev/null and b/src/img/icon_32-off.png differ diff --git a/src/img/icon_32.png b/src/img/icon_32.png new file mode 100644 index 0000000..c7c93e3 Binary files /dev/null and b/src/img/icon_32.png differ diff --git a/src/img/icon_64-loading.png b/src/img/icon_64-loading.png new file mode 100644 index 0000000..abd0fba Binary files /dev/null and b/src/img/icon_64-loading.png differ diff --git a/src/img/icon_64-off.png b/src/img/icon_64-off.png new file mode 100644 index 0000000..bbd881b Binary files /dev/null and b/src/img/icon_64-off.png differ diff --git a/src/img/icon_64.png b/src/img/icon_64.png new file mode 100644 index 0000000..50dcded Binary files /dev/null and b/src/img/icon_64.png differ diff --git a/src/img/material-design.svg b/src/img/material-design.svg new file mode 100644 index 0000000..3b5e727 --- /dev/null +++ b/src/img/material-design.svg @@ -0,0 +1,16 @@ + + + + + + + diff --git a/src/img/photon.svg b/src/img/photon.svg new file mode 100644 index 0000000..e6c42d5 --- /dev/null +++ b/src/img/photon.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/src/img/ublock-defs.svg b/src/img/ublock-defs.svg new file mode 100644 index 0000000..dbc59a3 --- /dev/null +++ b/src/img/ublock-defs.svg @@ -0,0 +1,27 @@ + + + + + + + diff --git a/src/img/ublock.svg b/src/img/ublock.svg new file mode 100644 index 0000000..ea2ffd3 --- /dev/null +++ b/src/img/ublock.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + diff --git a/src/js/1p-filters.js b/src/js/1p-filters.js new file mode 100644 index 0000000..fc50b50 --- /dev/null +++ b/src/js/1p-filters.js @@ -0,0 +1,337 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* global CodeMirror, uBlockDashboard */ + +'use strict'; + +import { onBroadcast } from './broadcast.js'; +import { dom, qs$ } from './dom.js'; +import { i18n$ } from './i18n.js'; +import './codemirror/ubo-static-filtering.js'; + +/******************************************************************************/ + +const cmEditor = new CodeMirror(qs$('#userFilters'), { + autoCloseBrackets: true, + autofocus: true, + extraKeys: { + 'Ctrl-Space': 'autocomplete', + 'Tab': 'toggleComment', + }, + foldGutter: true, + gutters: [ + 'CodeMirror-linenumbers', + { className: 'CodeMirror-lintgutter', style: 'width: 11px' }, + ], + lineNumbers: true, + lineWrapping: true, + matchBrackets: true, + maxScanLines: 1, + styleActiveLine: { + nonEmpty: true, + }, +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +let cachedUserFilters = ''; + +/******************************************************************************/ + +// Add auto-complete ability to the editor. Polling is used as the suggested +// hints also depend on the tabs currently opened. + +{ + let hintUpdateToken = 0; + + const getHints = async function() { + const hints = await vAPI.messaging.send('dashboard', { + what: 'getAutoCompleteDetails', + hintUpdateToken + }); + if ( hints instanceof Object === false ) { return; } + if ( hints.hintUpdateToken !== undefined ) { + cmEditor.setOption('uboHints', hints); + hintUpdateToken = hints.hintUpdateToken; + } + timer.on(2503); + }; + + const timer = vAPI.defer.create(( ) => { + getHints(); + }); + + getHints(); +} + +vAPI.messaging.send('dashboard', { + what: 'getTrustedScriptletTokens', +}).then(tokens => { + cmEditor.setOption('trustedScriptletTokens', tokens); +}); + +/******************************************************************************/ + +function getEditorText() { + const text = cmEditor.getValue().replace(/\s+$/, ''); + return text === '' ? text : text + '\n'; +} + +function setEditorText(text) { + cmEditor.setValue(text.replace(/\s+$/, '') + '\n\n'); +} + +/******************************************************************************/ + +function userFiltersChanged(changed) { + if ( typeof changed !== 'boolean' ) { + changed = self.hasUnsavedData(); + } + qs$('#userFiltersApply').disabled = !changed; + qs$('#userFiltersRevert').disabled = !changed; +} + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/3704 +// Merge changes to user filters occurring in the background with changes +// made in the editor. The code assumes that no deletion occurred in the +// background. + +function threeWayMerge(newContent) { + const prvContent = cachedUserFilters.trim().split(/\n/); + const differ = new self.diff_match_patch(); + const newChanges = differ.diff( + prvContent, + newContent.trim().split(/\n/) + ); + const usrChanges = differ.diff( + prvContent, + getEditorText().trim().split(/\n/) + ); + const out = []; + let i = 0, j = 0, k = 0; + while ( i < prvContent.length ) { + for ( ; j < newChanges.length; j++ ) { + const change = newChanges[j]; + if ( change[0] !== 1 ) { break; } + out.push(change[1]); + } + for ( ; k < usrChanges.length; k++ ) { + const change = usrChanges[k]; + if ( change[0] !== 1 ) { break; } + out.push(change[1]); + } + if ( k === usrChanges.length || usrChanges[k][0] !== -1 ) { + out.push(prvContent[i]); + } + i += 1; j += 1; k += 1; + } + for ( ; j < newChanges.length; j++ ) { + const change = newChanges[j]; + if ( change[0] !== 1 ) { continue; } + out.push(change[1]); + } + for ( ; k < usrChanges.length; k++ ) { + const change = usrChanges[k]; + if ( change[0] !== 1 ) { continue; } + out.push(change[1]); + } + return out.join('\n'); +} + +/******************************************************************************/ + +async function renderUserFilters(merge = false) { + const details = await vAPI.messaging.send('dashboard', { + what: 'readUserFilters', + }); + if ( details instanceof Object === false || details.error ) { return; } + + cmEditor.setOption('trustedSource', details.trustedSource === true); + + const newContent = details.content.trim(); + + if ( merge && self.hasUnsavedData() ) { + setEditorText(threeWayMerge(newContent)); + userFiltersChanged(true); + } else { + setEditorText(newContent); + userFiltersChanged(false); + } + + cachedUserFilters = newContent; +} + +/******************************************************************************/ + +function handleImportFilePicker(ev) { + const file = ev.target.files[0]; + if ( file === undefined || file.name === '' ) { return; } + if ( file.type.indexOf('text') !== 0 ) { return; } + const fr = new FileReader(); + fr.onload = function() { + if ( typeof fr.result !== 'string' ) { return; } + const content = uBlockDashboard.mergeNewLines(getEditorText(), fr.result); + cmEditor.operation(( ) => { + const cmPos = cmEditor.getCursor(); + setEditorText(content); + cmEditor.setCursor(cmPos); + cmEditor.focus(); + }); + }; + fr.readAsText(file); +} + +dom.on('#importFilePicker', 'change', handleImportFilePicker); + +function startImportFilePicker() { + const input = qs$('#importFilePicker'); + // Reset to empty string, this will ensure an change event is properly + // triggered if the user pick a file, even if it is the same as the last + // one picked. + input.value = ''; + input.click(); +} + +dom.on('#importUserFiltersFromFile', 'click', startImportFilePicker); + +/******************************************************************************/ + +function exportUserFiltersToFile() { + const val = getEditorText(); + if ( val === '' ) { return; } + const filename = i18n$('1pExportFilename') + .replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString()) + .replace(/ +/g, '_'); + vAPI.download({ + 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(val + '\n'), + 'filename': filename + }); +} + +/******************************************************************************/ + +async function applyChanges() { + const details = await vAPI.messaging.send('dashboard', { + what: 'writeUserFilters', + content: getEditorText(), + }); + if ( details instanceof Object === false || details.error ) { return; } + + cachedUserFilters = details.content.trim(); + userFiltersChanged(false); + vAPI.messaging.send('dashboard', { + what: 'reloadAllFilters', + }); +} + +function revertChanges() { + setEditorText(cachedUserFilters); +} + +/******************************************************************************/ + +function getCloudData() { + return getEditorText(); +} + +function setCloudData(data, append) { + if ( typeof data !== 'string' ) { return; } + if ( append ) { + data = uBlockDashboard.mergeNewLines(getEditorText(), data); + } + cmEditor.setValue(data); +} + +self.cloud.onPush = getCloudData; +self.cloud.onPull = setCloudData; + +/******************************************************************************/ + +self.hasUnsavedData = function() { + return getEditorText().trim() !== cachedUserFilters; +}; + +/******************************************************************************/ + +// Handle user interaction +dom.on('#exportUserFiltersToFile', 'click', exportUserFiltersToFile); +dom.on('#userFiltersApply', 'click', ( ) => { applyChanges(); }); +dom.on('#userFiltersRevert', 'click', revertChanges); + +(async ( ) => { + await renderUserFilters(); + + cmEditor.clearHistory(); + + // https://github.com/gorhill/uBlock/issues/3706 + // Save/restore cursor position + { + const line = await vAPI.localStorage.getItemAsync('myFiltersCursorPosition'); + if ( typeof line === 'number' ) { + cmEditor.setCursor(line, 0); + } + cmEditor.focus(); + } + + // https://github.com/gorhill/uBlock/issues/3706 + // Save/restore cursor position + { + let curline = 0; + cmEditor.on('cursorActivity', ( ) => { + if ( timer.ongoing() ) { return; } + if ( cmEditor.getCursor().line === curline ) { return; } + timer.on(701); + }); + const timer = vAPI.defer.create(( ) => { + curline = cmEditor.getCursor().line; + vAPI.localStorage.setItem('myFiltersCursorPosition', curline); + }); + } + + // https://github.com/gorhill/uBlock/issues/3704 + // Merge changes to user filters occurring in the background + onBroadcast(msg => { + switch ( msg.what ) { + case 'userFiltersUpdated': { + cmEditor.startOperation(); + const scroll = cmEditor.getScrollInfo(); + const selections = cmEditor.listSelections(); + renderUserFilters(true).then(( ) => { + cmEditor.clearHistory(); + cmEditor.setSelection(selections[0].anchor, selections[0].head); + cmEditor.scrollTo(scroll.left, scroll.top); + cmEditor.endOperation(); + }); + break; + } + default: + break; + } + }); +})(); + +cmEditor.on('changes', userFiltersChanged); +CodeMirror.commands.save = applyChanges; + +/******************************************************************************/ diff --git a/src/js/3p-filters.js b/src/js/3p-filters.js new file mode 100644 index 0000000..c59365f --- /dev/null +++ b/src/js/3p-filters.js @@ -0,0 +1,861 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +import { onBroadcast } from './broadcast.js'; +import { dom, qs$, qsa$ } from './dom.js'; +import { i18n, i18n$ } from './i18n.js'; + +/******************************************************************************/ + +const lastUpdateTemplateString = i18n$('3pLastUpdate'); +const obsoleteTemplateString = i18n$('3pExternalListObsolete'); +const reValidExternalList = /^[a-z-]+:\/\/(?:\S+\/\S*|\/\S+)/m; +const recentlyUpdated = 1 * 60 * 60 * 1000; // 1 hour + +let listsetDetails = {}; + +/******************************************************************************/ + +onBroadcast(msg => { + switch ( msg.what ) { + case 'assetUpdated': + updateAssetStatus(msg); + break; + case 'assetsUpdated': + dom.cl.remove(dom.body, 'updating'); + renderWidgets(); + break; + case 'staticFilteringDataChanged': + renderFilterLists(); + break; + default: + break; + } +}); + +/******************************************************************************/ + +const renderNumber = value => { + return value.toLocaleString(); +}; + +const listStatsTemplate = i18n$('3pListsOfBlockedHostsPerListStats'); + +const renderLeafStats = (used, total) => { + if ( isNaN(used) || isNaN(total) ) { return ''; } + return listStatsTemplate + .replace('{{used}}', renderNumber(used)) + .replace('{{total}}', renderNumber(total)); +}; + +const renderNodeStats = (used, total) => { + if ( isNaN(used) || isNaN(total) ) { return ''; } + return `${used.toLocaleString()}/${total.toLocaleString()}`; +}; + +const i18nGroupName = name => { + return i18n$('3pGroup' + name.charAt(0).toUpperCase() + name.slice(1)); +}; + +/******************************************************************************/ + +const renderFilterLists = ( ) => { + // Assemble a pretty list name if possible + const listNameFromListKey = listkey => { + const list = listsetDetails.current[listkey] || listsetDetails.available[listkey]; + const title = list && list.title || ''; + if ( title !== '' ) { return title; } + return listkey; + }; + + const initializeListEntry = (listDetails, listEntry) => { + const listkey = listEntry.dataset.key; + const listEntryPrevious = + qs$(`[data-key="${listDetails.group}"] [data-key="${listkey}"]`); + if ( listEntryPrevious !== null ) { + if ( dom.cl.has(listEntryPrevious, 'checked') ) { + dom.cl.add(listEntry, 'checked'); + } + if ( dom.cl.has(listEntryPrevious, 'stickied') ) { + dom.cl.add(listEntry, 'stickied'); + } + if ( dom.cl.has(listEntryPrevious, 'toRemove') ) { + dom.cl.add(listEntry, 'toRemove'); + } + if ( dom.cl.has(listEntryPrevious, 'searchMatch') ) { + dom.cl.add(listEntry, 'searchMatch'); + } + } else { + dom.cl.toggle(listEntry, 'checked', listDetails.off !== true); + } + const on = dom.cl.has(listEntry, 'checked'); + dom.prop(qs$(listEntry, ':scope > .detailbar input'), 'checked', on); + let elem = qs$(listEntry, ':scope > .detailbar a.content'); + dom.attr(elem, 'href', 'asset-viewer.html?url=' + encodeURIComponent(listkey)); + dom.attr(elem, 'type', 'text/html'); + dom.cl.remove(listEntry, 'toRemove'); + if ( listDetails.supportName ) { + elem = qs$(listEntry, ':scope > .detailbar a.support'); + dom.attr(elem, 'href', listDetails.supportURL || '#'); + dom.attr(elem, 'title', listDetails.supportName); + } + if ( listDetails.external ) { + dom.cl.add(listEntry, 'external'); + } else { + dom.cl.remove(listEntry, 'external'); + } + if ( listDetails.instructionURL ) { + elem = qs$(listEntry, ':scope > .detailbar a.mustread'); + dom.attr(elem, 'href', listDetails.instructionURL || '#'); + } + dom.cl.toggle(listEntry, 'isDefault', + listDetails.isDefault === true || + listDetails.isImportant === true || + listkey === 'user-filters' + ); + elem = qs$(listEntry, '.leafstats'); + dom.text(elem, renderLeafStats(on ? listDetails.entryUsedCount : 0, listDetails.entryCount)); + // https://github.com/chrisaljoudi/uBlock/issues/104 + const asset = listsetDetails.cache[listkey] || {}; + const remoteURL = asset.remoteURL; + dom.cl.toggle(listEntry, 'unsecure', + typeof remoteURL === 'string' && remoteURL.lastIndexOf('http:', 0) === 0 + ); + dom.cl.toggle(listEntry, 'failed', asset.error !== undefined); + dom.cl.toggle(listEntry, 'obsolete', asset.obsolete === true); + const lastUpdateString = lastUpdateTemplateString.replace('{{ago}}', + i18n.renderElapsedTimeToString(asset.writeTime || 0) + ); + if ( asset.obsolete === true ) { + let title = obsoleteTemplateString; + if ( asset.cached && asset.writeTime !== 0 ) { + title += '\n' + lastUpdateString; + } + dom.attr(qs$(listEntry, ':scope > .detailbar .status.obsolete'), 'title', title); + } + if ( asset.cached === true ) { + dom.cl.add(listEntry, 'cached'); + dom.attr(qs$(listEntry, ':scope > .detailbar .status.cache'), 'title', lastUpdateString); + const timeSinceLastUpdate = Date.now() - asset.writeTime; + dom.cl.toggle(listEntry, 'recent', timeSinceLastUpdate < recentlyUpdated); + } else { + dom.cl.remove(listEntry, 'cached'); + } + }; + + const createListEntry = (listDetails, depth) => { + if ( listDetails.lists === undefined ) { + return dom.clone('#templates .listEntry[data-role="leaf"]'); + } + if ( depth !== 0 ) { + return dom.clone('#templates .listEntry[data-role="node"]'); + } + return dom.clone('#templates .listEntry[data-role="node"][data-parent="root"]'); + }; + + const createListEntries = (parentkey, listTree, depth = 0) => { + const listEntries = dom.clone('#templates .listEntries'); + const treeEntries = Object.entries(listTree); + if ( depth !== 0 ) { + const reEmojis = /\p{Emoji}+/gu; + treeEntries.sort((a ,b) => { + const as = (a[1].title || a[0]).replace(reEmojis, ''); + const bs = (b[1].title || b[0]).replace(reEmojis, ''); + return as.localeCompare(bs); + }); + } + for ( const [ listkey, listDetails ] of treeEntries ) { + const listEntry = createListEntry(listDetails, depth); + if ( dom.cl.has(dom.root, 'mobile') ) { + const leafStats = qs$(listEntry, '.leafstats'); + if ( leafStats ) { + listEntry.append(leafStats); + } + } + listEntry.dataset.key = listkey; + listEntry.dataset.parent = parentkey; + qs$(listEntry, ':scope > .detailbar .listname').append( + i18n.patchUnicodeFlags(listDetails.title) + ); + if ( listDetails.lists !== undefined ) { + listEntry.append(createListEntries(listEntry.dataset.key, listDetails.lists, depth+1)); + dom.cl.toggle(listEntry, 'expanded', listIsExpanded(listkey)); + updateListNode(listEntry); + } else { + initializeListEntry(listDetails, listEntry); + } + listEntries.append(listEntry); + } + return listEntries; + }; + + const onListsReceived = response => { + // Store in global variable + listsetDetails = response; + hashFromListsetDetails(); + + // Build list tree + const listTree = {}; + const groupKeys = [ + 'user', + 'default', + 'ads', + 'privacy', + 'malware', + 'multipurpose', + 'annoyances', + 'regions', + 'custom' + ]; + for ( const key of groupKeys ) { + listTree[key] = { + title: i18nGroupName(key), + lists: {}, + }; + } + for ( const [ listkey, listDetails ] of Object.entries(response.available) ) { + let groupKey = listDetails.group; + if ( groupKey === 'social' ) { + groupKey = 'annoyances'; + } + const groupDetails = listTree[groupKey]; + if ( listDetails.parent !== undefined ) { + let lists = groupDetails.lists; + for ( const parent of listDetails.parent.split('|') ) { + if ( lists[parent] === undefined ) { + lists[parent] = { title: parent, lists: {} }; + } + lists = lists[parent].lists; + } + lists[listkey] = listDetails; + } else { + listDetails.title = listNameFromListKey(listkey); + groupDetails.lists[listkey] = listDetails; + } + } + const listEntries = createListEntries('root', listTree); + qs$('#lists .listEntries').replaceWith(listEntries); + + qs$('#autoUpdate').checked = listsetDetails.autoUpdate === true; + dom.text( + '#listsOfBlockedHostsPrompt', + i18n$('3pListsOfBlockedHostsPrompt') + .replace('{{netFilterCount}}', renderNumber(response.netFilterCount)) + .replace('{{cosmeticFilterCount}}', renderNumber(response.cosmeticFilterCount)) + ); + qs$('#parseCosmeticFilters').checked = + listsetDetails.parseCosmeticFilters === true; + qs$('#ignoreGenericCosmeticFilters').checked = + listsetDetails.ignoreGenericCosmeticFilters === true; + qs$('#suspendUntilListsAreLoaded').checked = + listsetDetails.suspendUntilListsAreLoaded === true; + + // https://github.com/gorhill/uBlock/issues/2394 + dom.cl.toggle(dom.body, 'updating', listsetDetails.isUpdating); + + renderWidgets(); + }; + + return vAPI.messaging.send('dashboard', { + what: 'getLists', + }).then(response => { + onListsReceived(response); + }); +}; + +/******************************************************************************/ + +const renderWidgets = ( ) => { + dom.cl.toggle('#buttonApply', 'disabled', + filteringSettingsHash === hashFromCurrentFromSettings() + ); + const updating = dom.cl.has(dom.body, 'updating'); + dom.cl.toggle('#buttonUpdate', 'active', updating); + dom.cl.toggle('#buttonUpdate', 'disabled', + updating === false && + qs$('#lists .listEntry.checked.obsolete:not(.toRemove)') === null + ); +}; + +/******************************************************************************/ + +const updateAssetStatus = details => { + const listEntry = qs$(`#lists .listEntry[data-key="${details.key}"]`); + if ( listEntry === null ) { return; } + dom.cl.toggle(listEntry, 'failed', !!details.failed); + dom.cl.toggle(listEntry, 'obsolete', !details.cached); + dom.cl.toggle(listEntry, 'cached', !!details.cached); + if ( details.cached ) { + dom.attr(qs$(listEntry, '.status.cache'), 'title', + lastUpdateTemplateString.replace('{{ago}}', i18n.renderElapsedTimeToString(Date.now())) + ); + dom.cl.add(listEntry, 'recent'); + } + updateAncestorListNodes(listEntry, ancestor => { + updateListNode(ancestor); + }); + renderWidgets(); +}; + +/******************************************************************************* + + Compute a hash from all the settings affecting how filter lists are loaded + in memory. + +**/ + +let filteringSettingsHash = ''; + +const hashFromListsetDetails = ( ) => { + const hashParts = [ + listsetDetails.parseCosmeticFilters === true, + listsetDetails.ignoreGenericCosmeticFilters === true, + ]; + const listHashes = []; + for ( const [ listkey, listDetails ] of Object.entries(listsetDetails.available) ) { + if ( listDetails.off === true ) { continue; } + listHashes.push(listkey); + } + hashParts.push( listHashes.sort().join(), '', false); + filteringSettingsHash = hashParts.join(); +}; + +const hashFromCurrentFromSettings = ( ) => { + const hashParts = [ + qs$('#parseCosmeticFilters').checked, + qs$('#ignoreGenericCosmeticFilters').checked, + ]; + const listHashes = []; + const listEntries = qsa$('#lists .listEntry[data-key]:not(.toRemove)'); + for ( const liEntry of listEntries ) { + if ( liEntry.dataset.role !== 'leaf' ) { continue; } + if ( dom.cl.has(liEntry, 'checked') === false ) { continue; } + listHashes.push(liEntry.dataset.key); + } + const textarea = qs$('#lists .listEntry[data-role="import"].expanded textarea'); + hashParts.push( + listHashes.sort().join(), + textarea !== null && textarea.value.trim() || '', + qs$('#lists .listEntry.toRemove') !== null + ); + return hashParts.join(); +}; + +/******************************************************************************/ + +const onListsetChanged = ev => { + const input = ev.target.closest('input'); + if ( input === null ) { return; } + toggleFilterList(input, input.checked, true); +}; + +dom.on('#lists', 'change', '.listEntry > .detailbar input', onListsetChanged); + +const toggleFilterList = (elem, on, ui = false) => { + const listEntry = elem.closest('.listEntry'); + if ( listEntry === null ) { return; } + if ( listEntry.dataset.parent === 'root' ) { return; } + const searchMode = dom.cl.has('#lists', 'searchMode'); + const input = qs$(listEntry, ':scope > .detailbar input'); + if ( on === undefined ) { + on = input.checked === false; + } + input.checked = on; + dom.cl.toggle(listEntry, 'checked', on); + dom.cl.toggle(listEntry, 'stickied', ui && !on && !searchMode); + // Select/unselect descendants. Twist: if in search-mode, select only + // search-matched descendants. + const childListEntries = searchMode + ? qsa$(listEntry, '.listEntry.searchMatch') + : qsa$(listEntry, '.listEntry'); + for ( const descendantList of childListEntries ) { + dom.cl.toggle(descendantList, 'checked', on); + qs$(descendantList, ':scope > .detailbar input').checked = on; + } + updateAncestorListNodes(listEntry, ancestor => { + updateListNode(ancestor); + }); + onFilteringSettingsChanged(); +}; + +const updateListNode = listNode => { + if ( listNode === null ) { return; } + if ( listNode.dataset.role !== 'node' ) { return; } + const checkedListLeaves = qsa$(listNode, '.listEntry[data-role="leaf"].checked'); + const allListLeaves = qsa$(listNode, '.listEntry[data-role="leaf"]'); + dom.text(qs$(listNode, '.nodestats'), + renderNodeStats(checkedListLeaves.length, allListLeaves.length) + ); + dom.cl.toggle(listNode, 'searchMatch', + qs$(listNode, ':scope > .listEntries > .listEntry.searchMatch') !== null + ); + if ( listNode.dataset.parent === 'root' ) { return; } + let usedFilterCount = 0; + let totalFilterCount = 0; + let isCached = false; + let isObsolete = false; + let latestWriteTime = 0; + let oldestWriteTime = Number.MAX_SAFE_INTEGER; + for ( const listLeaf of checkedListLeaves ) { + const listkey = listLeaf.dataset.key; + const listDetails = listsetDetails.available[listkey]; + usedFilterCount += listDetails.off ? 0 : listDetails.entryUsedCount || 0; + totalFilterCount += listDetails.entryCount || 0; + const assetCache = listsetDetails.cache[listkey] || {}; + isCached = isCached || dom.cl.has(listLeaf, 'cached'); + isObsolete = isObsolete || dom.cl.has(listLeaf, 'obsolete'); + latestWriteTime = Math.max(latestWriteTime, assetCache.writeTime || 0); + oldestWriteTime = Math.min(oldestWriteTime, assetCache.writeTime || Number.MAX_SAFE_INTEGER); + } + dom.cl.toggle(listNode, 'checked', checkedListLeaves.length !== 0); + dom.cl.toggle(qs$(listNode, ':scope > .detailbar .checkbox'), + 'partial', + checkedListLeaves.length !== allListLeaves.length + ); + dom.prop(qs$(listNode, ':scope > .detailbar input'), + 'checked', + checkedListLeaves.length !== 0 + ); + dom.text(qs$(listNode, '.leafstats'), + renderLeafStats(usedFilterCount, totalFilterCount) + ); + const firstLeaf = qs$(listNode, '.listEntry[data-role="leaf"]'); + if ( firstLeaf !== null ) { + dom.attr(qs$(listNode, ':scope > .detailbar a.support'), 'href', + dom.attr(qs$(firstLeaf, ':scope > .detailbar a.support'), 'href') || '#' + ); + dom.attr(qs$(listNode, ':scope > .detailbar a.mustread'), 'href', + dom.attr(qs$(firstLeaf, ':scope > .detailbar a.mustread'), 'href') || '#' + ); + } + dom.cl.toggle(listNode, 'cached', isCached); + dom.cl.toggle(listNode, 'obsolete', isObsolete); + if ( isCached ) { + dom.attr(qs$(listNode, ':scope > .detailbar .cache'), 'title', + lastUpdateTemplateString.replace('{{ago}}', i18n.renderElapsedTimeToString(latestWriteTime)) + ); + dom.cl.toggle(listNode, 'recent', (Date.now() - oldestWriteTime) < recentlyUpdated); + } + if ( qs$(listNode, '.listEntry.isDefault') !== null ) { + dom.cl.add(listNode, 'isDefault'); + } + if ( qs$(listNode, '.listEntry.stickied') !== null ) { + dom.cl.add(listNode, 'stickied'); + } +}; + +const updateAncestorListNodes = (listEntry, fn) => { + while ( listEntry !== null ) { + fn(listEntry); + listEntry = qs$(`.listEntry[data-key="${listEntry.dataset.parent}"]`); + } +}; + +/******************************************************************************/ + +const onFilteringSettingsChanged = ( ) => { + renderWidgets(); +}; + +dom.on('#parseCosmeticFilters', 'change', onFilteringSettingsChanged); +dom.on('#ignoreGenericCosmeticFilters', 'change', onFilteringSettingsChanged); +dom.on('#lists', 'input', '[data-role="import"] textarea', onFilteringSettingsChanged); + +/******************************************************************************/ + +const onRemoveExternalList = ev => { + const listEntry = ev.target.closest('[data-key]'); + if ( listEntry === null ) { return; } + dom.cl.toggle(listEntry, 'toRemove'); + renderWidgets(); +}; + +dom.on('#lists', 'click', '.listEntry .remove', onRemoveExternalList); + +/******************************************************************************/ + +const onPurgeClicked = ev => { + const liEntry = ev.target.closest('[data-key]'); + const listkey = liEntry.dataset.key || ''; + if ( listkey === '' ) { return; } + + const assetKeys = [ listkey ]; + for ( const listLeaf of qsa$(liEntry, '[data-role="leaf"]') ) { + assetKeys.push(listLeaf.dataset.key); + dom.cl.add(listLeaf, 'obsolete'); + dom.cl.remove(listLeaf, 'cached'); + } + + vAPI.messaging.send('dashboard', { + what: 'listsUpdateNow', + assetKeys, + preferOrigin: ev.shiftKey, + }); + + // If the cached version is purged, the installed version must be assumed + // to be obsolete. + // https://github.com/gorhill/uBlock/issues/1733 + // An external filter list must not be marked as obsolete, they will + // always be fetched anyways if there is no cached copy. + dom.cl.add(dom.body, 'updating'); + dom.cl.add(liEntry, 'obsolete'); + + if ( qs$(liEntry, 'input[type="checkbox"]').checked ) { + renderWidgets(); + } +}; + +dom.on('#lists', 'click', 'span.cache', onPurgeClicked); + +/******************************************************************************/ + +const selectFilterLists = async ( ) => { + // Cosmetic filtering switch + let checked = qs$('#parseCosmeticFilters').checked; + vAPI.messaging.send('dashboard', { + what: 'userSettings', + name: 'parseAllABPHideFilters', + value: checked, + }); + listsetDetails.parseCosmeticFilters = checked; + + checked = qs$('#ignoreGenericCosmeticFilters').checked; + vAPI.messaging.send('dashboard', { + what: 'userSettings', + name: 'ignoreGenericCosmeticFilters', + value: checked, + }); + listsetDetails.ignoreGenericCosmeticFilters = checked; + + // Filter lists to remove/select + const toSelect = []; + const toRemove = []; + for ( const liEntry of qsa$('#lists .listEntry[data-role="leaf"]') ) { + const listkey = liEntry.dataset.key; + if ( listsetDetails.available.hasOwnProperty(listkey) === false ) { + continue; + } + const listDetails = listsetDetails.available[listkey]; + if ( dom.cl.has(liEntry, 'toRemove') ) { + toRemove.push(listkey); + listDetails.off = true; + continue; + } + if ( dom.cl.has(liEntry, 'checked') ) { + toSelect.push(listkey); + listDetails.off = false; + } else { + listDetails.off = true; + } + } + + // External filter lists to import + const textarea = qs$('#lists .listEntry[data-role="import"].expanded textarea'); + const toImport = textarea !== null && textarea.value.trim() || ''; + if ( textarea !== null ) { + dom.cl.remove(textarea.closest('.expandable'), 'expanded'); + textarea.value = ''; + } + + hashFromListsetDetails(); + + await vAPI.messaging.send('dashboard', { + what: 'applyFilterListSelection', + toSelect, + toImport, + toRemove, + }); +}; + +/******************************************************************************/ + +const buttonApplyHandler = async ( ) => { + await selectFilterLists(); + dom.cl.add(dom.body, 'working'); + dom.cl.remove('#lists .listEntry.stickied', 'stickied'); + renderWidgets(); + await vAPI.messaging.send('dashboard', { what: 'reloadAllFilters' }); + dom.cl.remove(dom.body, 'working'); +}; + +dom.on('#buttonApply', 'click', ( ) => { buttonApplyHandler(); }); + +/******************************************************************************/ + +const buttonUpdateHandler = async ( ) => { + dom.cl.remove('#lists .listEntry.stickied', 'stickied'); + await selectFilterLists(); + dom.cl.add(dom.body, 'updating'); + renderWidgets(); + vAPI.messaging.send('dashboard', { what: 'updateNow' }); +}; + +dom.on('#buttonUpdate', 'click', ( ) => { buttonUpdateHandler(); }); + +/******************************************************************************/ + +const userSettingCheckboxChanged = ( ) => { + const target = event.target; + vAPI.messaging.send('dashboard', { + what: 'userSettings', + name: target.id, + value: target.checked, + }); + listsetDetails[target.id] = target.checked; +}; + +dom.on('#autoUpdate', 'change', userSettingCheckboxChanged); +dom.on('#suspendUntilListsAreLoaded', 'change', userSettingCheckboxChanged); + +/******************************************************************************/ + +const searchFilterLists = ( ) => { + const pattern = dom.prop('.searchbar input', 'value') || ''; + dom.cl.toggle('#lists', 'searchMode', pattern !== ''); + if ( pattern === '' ) { return; } + const reflectSearchMatches = listEntry => { + if ( listEntry.dataset.role !== 'node' ) { return; } + dom.cl.toggle(listEntry, 'searchMatch', + qs$(listEntry, ':scope > .listEntries > .listEntry.searchMatch') !== null + ); + }; + const toI18n = tags => { + if ( tags === '' ) { return ''; } + return tags.toLowerCase().split(/\s+/).reduce((a, v) => { + let s = i18n$(v); + if ( s === '' ) { + s = i18nGroupName(v); + if ( s === '' ) { return a; } + } + return `${a} ${s}`.trim(); + }, ''); + }; + const re = new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i'); + for ( const listEntry of qsa$('#lists [data-role="leaf"]') ) { + const listkey = listEntry.dataset.key; + const listDetails = listsetDetails.available[listkey]; + if ( listDetails === undefined ) { continue; } + let haystack = perListHaystack.get(listDetails); + if ( haystack === undefined ) { + haystack = [ + listDetails.title, + listDetails.group || '', + i18nGroupName(listDetails.group || ''), + listDetails.tags || '', + toI18n(listDetails.tags || ''), + ].join(' ').trim(); + perListHaystack.set(listDetails, haystack); + } + dom.cl.toggle(listEntry, 'searchMatch', re.test(haystack)); + updateAncestorListNodes(listEntry, reflectSearchMatches); + } +}; + +const perListHaystack = new WeakMap(); + +dom.on('.searchbar input', 'input', searchFilterLists); + +/******************************************************************************/ + +const expandedListSet = new Set([ + 'uBlock filters', + 'AdGuard – Annoyances', + 'EasyList – Annoyances', +]); + +const listIsExpanded = which => { + return expandedListSet.has(which); +}; + +const applyListExpansion = listkeys => { + if ( listkeys === undefined ) { + listkeys = Array.from(expandedListSet); + } + expandedListSet.clear(); + dom.cl.remove('#lists [data-role="node"]', 'expanded'); + listkeys.forEach(which => { + expandedListSet.add(which); + dom.cl.add(`#lists [data-key="${which}"]`, 'expanded'); + }); +}; + +const toggleListExpansion = which => { + const isExpanded = expandedListSet.has(which); + if ( which === '*' ) { + if ( isExpanded ) { + expandedListSet.clear(); + dom.cl.remove('#lists .expandable', 'expanded'); + dom.cl.remove('#lists .stickied', 'stickied'); + } else { + expandedListSet.clear(); + expandedListSet.add('*'); + dom.cl.add('#lists .rootstats', 'expanded'); + for ( const expandable of qsa$('#lists > .listEntries .expandable') ) { + const listkey = expandable.dataset.key || ''; + if ( listkey === '' ) { continue; } + expandedListSet.add(listkey); + dom.cl.add(expandable, 'expanded'); + } + } + } else { + if ( isExpanded ) { + expandedListSet.delete(which); + const listNode = qs$(`#lists > .listEntries [data-key="${which}"]`); + dom.cl.remove(listNode, 'expanded'); + if ( listNode.dataset.parent === 'root' ) { + dom.cl.remove(qsa$(listNode, '.stickied'), 'stickied'); + } + } else { + expandedListSet.add(which); + dom.cl.add(`#lists > .listEntries [data-key="${which}"]`, 'expanded'); + } + } + vAPI.localStorage.setItem('expandedListSet', Array.from(expandedListSet)); + vAPI.localStorage.removeItem('hideUnusedFilterLists'); +}; + +dom.on('#listsOfBlockedHostsPrompt', 'click', ( ) => { + toggleListExpansion('*'); +}); + +dom.on('#lists', 'click', '.listExpander', ev => { + const expandable = ev.target.closest('.expandable'); + if ( expandable === null ) { return; } + const which = expandable.dataset.key; + if ( which !== undefined ) { + toggleListExpansion(which); + } else { + dom.cl.toggle(expandable, 'expanded'); + if ( expandable.dataset.role === 'import' ) { + onFilteringSettingsChanged(); + } + } + ev.preventDefault(); +}); + +dom.on('#lists', 'click', '[data-parent="root"] > .detailbar .listname', ev => { + const listEntry = ev.target.closest('.listEntry'); + if ( listEntry === null ) { return; } + const listkey = listEntry.dataset.key; + if ( listkey === undefined ) { return; } + toggleListExpansion(listkey); + ev.preventDefault(); +}); + +dom.on('#lists', 'click', '[data-role="import"] > .detailbar .listname', ev => { + const expandable = ev.target.closest('.listEntry'); + if ( expandable === null ) { return; } + dom.cl.toggle(expandable, 'expanded'); + ev.preventDefault(); +}); + +dom.on('#lists', 'click', '.listEntry > .detailbar .nodestats', ev => { + const listEntry = ev.target.closest('.listEntry'); + if ( listEntry === null ) { return; } + const listkey = listEntry.dataset.key; + if ( listkey === undefined ) { return; } + toggleListExpansion(listkey); + ev.preventDefault(); +}); + +// Initialize from saved state. +vAPI.localStorage.getItemAsync('expandedListSet').then(listkeys => { + if ( Array.isArray(listkeys) === false ) { return; } + applyListExpansion(listkeys); +}); + +/******************************************************************************/ + +// Cloud storage-related. + +self.cloud.onPush = function toCloudData() { + const bin = { + parseCosmeticFilters: qs$('#parseCosmeticFilters').checked, + ignoreGenericCosmeticFilters: qs$('#ignoreGenericCosmeticFilters').checked, + selectedLists: [] + }; + + const liEntries = qsa$('#lists .listEntry.checked[data-role="leaf"]'); + for ( const liEntry of liEntries ) { + bin.selectedLists.push(liEntry.dataset.key); + } + + return bin; +}; + +self.cloud.onPull = function fromCloudData(data, append) { + if ( typeof data !== 'object' || data === null ) { return; } + + let elem = qs$('#parseCosmeticFilters'); + let checked = data.parseCosmeticFilters === true || append && elem.checked; + elem.checked = listsetDetails.parseCosmeticFilters = checked; + + elem = qs$('#ignoreGenericCosmeticFilters'); + checked = data.ignoreGenericCosmeticFilters === true || append && elem.checked; + elem.checked = listsetDetails.ignoreGenericCosmeticFilters = checked; + + const selectedSet = new Set(data.selectedLists); + for ( const listEntry of qsa$('#lists .listEntry[data-role="leaf"]') ) { + const listkey = listEntry.dataset.key; + const mustEnable = selectedSet.has(listkey); + selectedSet.delete(listkey); + if ( mustEnable === false && append ) { continue; } + toggleFilterList(listEntry, mustEnable); + } + + // If there are URL-like list keys left in the selected set, import them. + for ( const listkey of selectedSet ) { + if ( reValidExternalList.test(listkey) ) { continue; } + selectedSet.delete(listkey); + } + if ( selectedSet.size !== 0 ) { + const textarea = qs$('#lists .listEntry[data-role="import"] textarea'); + const lines = append + ? textarea.value.split(/[\n\r]+/) + : []; + lines.push(...selectedSet); + if ( lines.length !== 0 ) { lines.push(''); } + textarea.value = lines.join('\n'); + dom.cl.toggle('#lists .listEntry[data-role="import"]', 'expanded', textarea.value !== ''); + } + + renderWidgets(); +}; + +/******************************************************************************/ + +self.hasUnsavedData = function() { + return hashFromCurrentFromSettings() !== filteringSettingsHash; +}; + +/******************************************************************************/ + +renderFilterLists().then(( ) => { + const buttonUpdate = qs$('#buttonUpdate'); + if ( dom.cl.has(buttonUpdate, 'active') ) { return; } + if ( dom.cl.has(buttonUpdate, 'disabled') ) { return; } + if ( listsetDetails.autoUpdate !== true ) { return; } + buttonUpdateHandler(); +}); + +/******************************************************************************/ diff --git a/src/js/about.js b/src/js/about.js new file mode 100644 index 0000000..680fab1 --- /dev/null +++ b/src/js/about.js @@ -0,0 +1,34 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +import { dom } from './dom.js'; + +/******************************************************************************/ + +(async ( ) => { + const appData = await vAPI.messaging.send('dashboard', { + what: 'getAppData', + }); + + dom.text('#aboutNameVer', appData.name + ' ' + appData.version); +})(); diff --git a/src/js/advanced-settings.js b/src/js/advanced-settings.js new file mode 100644 index 0000000..c21346f --- /dev/null +++ b/src/js/advanced-settings.js @@ -0,0 +1,194 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2016-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 +*/ + +/* global CodeMirror, uBlockDashboard */ + +'use strict'; + +import { dom, qs$ } from './dom.js'; + +/******************************************************************************/ + +let defaultSettings = new Map(); +let adminSettings = new Map(); +let beforeHash = ''; + +/******************************************************************************/ + +CodeMirror.defineMode('raw-settings', function() { + let lastSetting = ''; + + return { + token: function(stream) { + if ( stream.sol() ) { + stream.eatSpace(); + const match = stream.match(/\S+/); + if ( match !== null && defaultSettings.has(match[0]) ) { + lastSetting = match[0]; + return adminSettings.has(match[0]) + ? 'readonly keyword' + : 'keyword'; + } + stream.skipToEnd(); + return 'line-cm-error'; + } + stream.eatSpace(); + const match = stream.match(/.*$/); + if ( match !== null ) { + if ( match[0].trim() !== defaultSettings.get(lastSetting) ) { + return 'line-cm-strong'; + } + if ( adminSettings.has(lastSetting) ) { + return 'readonly'; + } + } + stream.skipToEnd(); + return null; + } + }; +}); + +const cmEditor = new CodeMirror(qs$('#advancedSettings'), { + autofocus: true, + lineNumbers: true, + lineWrapping: false, + styleActiveLine: true +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +/******************************************************************************/ + +const hashFromAdvancedSettings = function(raw) { + const aa = typeof raw === 'string' + ? arrayFromString(raw) + : arrayFromObject(raw); + aa.sort((a, b) => a[0].localeCompare(b[0])); + return JSON.stringify(aa); +}; + +/******************************************************************************/ + +const arrayFromObject = function(o) { + const out = []; + for ( const k in o ) { + if ( o.hasOwnProperty(k) === false ) { continue; } + out.push([ k, `${o[k]}` ]); + } + return out; +}; + +const arrayFromString = function(s) { + const out = []; + for ( let line of s.split(/[\n\r]+/) ) { + line = line.trim(); + if ( line === '' ) { continue; } + const pos = line.indexOf(' '); + let k, v; + if ( pos !== -1 ) { + k = line.slice(0, pos); + v = line.slice(pos + 1); + } else { + k = line; + v = ''; + } + out.push([ k.trim(), v.trim() ]); + } + return out; +}; + +/******************************************************************************/ + +const advancedSettingsChanged = (( ) => { + const handler = ( ) => { + const changed = hashFromAdvancedSettings(cmEditor.getValue()) !== beforeHash; + qs$('#advancedSettingsApply').disabled = !changed; + CodeMirror.commands.save = changed ? applyChanges : function(){}; + }; + + const timer = vAPI.defer.create(handler); + + return function() { + timer.offon(200); + }; +})(); + +cmEditor.on('changes', advancedSettingsChanged); + +/******************************************************************************/ + +const renderAdvancedSettings = async function(first) { + const details = await vAPI.messaging.send('dashboard', { + what: 'readHiddenSettings', + }); + defaultSettings = new Map(arrayFromObject(details.default)); + adminSettings = new Map(arrayFromObject(details.admin)); + beforeHash = hashFromAdvancedSettings(details.current); + const pretty = []; + const roLines = []; + const entries = arrayFromObject(details.current); + let max = 0; + for ( const [ k ] of entries ) { + if ( k.length > max ) { max = k.length; } + } + for ( let i = 0; i < entries.length; i++ ) { + const [ k, v ] = entries[i]; + pretty.push(' '.repeat(max - k.length) + `${k} ${v}`); + if ( adminSettings.has(k) ) { + roLines.push(i); + } + } + pretty.push(''); + cmEditor.setValue(pretty.join('\n')); + if ( first ) { + cmEditor.clearHistory(); + } + for ( const line of roLines ) { + cmEditor.markText( + { line, ch: 0 }, + { line: line + 1, ch: 0 }, + { readOnly: true } + ); + } + advancedSettingsChanged(); + cmEditor.focus(); +}; + +/******************************************************************************/ + +const applyChanges = async function() { + await vAPI.messaging.send('dashboard', { + what: 'writeHiddenSettings', + content: cmEditor.getValue(), + }); + renderAdvancedSettings(); +}; + +/******************************************************************************/ + +dom.on('#advancedSettings', 'input', advancedSettingsChanged); +dom.on('#advancedSettingsApply', 'click', ( ) => { + applyChanges(); +}); + +renderAdvancedSettings(true); + +/******************************************************************************/ diff --git a/src/js/asset-viewer.js b/src/js/asset-viewer.js new file mode 100644 index 0000000..eabe136 --- /dev/null +++ b/src/js/asset-viewer.js @@ -0,0 +1,112 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* global CodeMirror, uBlockDashboard */ + +'use strict'; + +/******************************************************************************/ + +import { dom, qs$ } from './dom.js'; +import './codemirror/ubo-static-filtering.js'; + +/******************************************************************************/ + +(async ( ) => { + const subscribeURL = new URL(document.location); + const subscribeParams = subscribeURL.searchParams; + const assetKey = subscribeParams.get('url'); + if ( assetKey === null ) { return; } + + const subscribeElem = subscribeParams.get('subscribe') !== null + ? qs$('#subscribe') + : null; + if ( subscribeElem !== null && subscribeURL.hash !== '#subscribed' ) { + const title = subscribeParams.get('title'); + const promptElem = qs$('#subscribePrompt'); + dom.text(promptElem.children[0], title); + const a = promptElem.children[1]; + dom.text(a, assetKey); + dom.attr(a, 'href', assetKey); + dom.cl.remove(subscribeElem, 'hide'); + } + + const cmEditor = new CodeMirror(qs$('#content'), { + autofocus: true, + foldGutter: true, + gutters: [ + 'CodeMirror-linenumbers', + { className: 'CodeMirror-lintgutter', style: 'width: 11px' }, + ], + lineNumbers: true, + lineWrapping: true, + matchBrackets: true, + maxScanLines: 1, + readOnly: true, + styleActiveLine: { + nonEmpty: true, + }, + }); + + uBlockDashboard.patchCodeMirrorEditor(cmEditor); + + vAPI.messaging.send('dashboard', { + what: 'getAutoCompleteDetails' + }).then(hints => { + if ( hints instanceof Object === false ) { return; } + cmEditor.setOption('uboHints', hints); + }); + + vAPI.messaging.send('dashboard', { + what: 'getTrustedScriptletTokens', + }).then(tokens => { + cmEditor.setOption('trustedScriptletTokens', tokens); + }); + + const details = await vAPI.messaging.send('default', { + what : 'getAssetContent', + url: assetKey, + }); + cmEditor.setOption('trustedSource', details.trustedSource === true); + cmEditor.setValue(details && details.content || ''); + + if ( subscribeElem !== null ) { + dom.on('#subscribeButton', 'click', ( ) => { + dom.cl.add(subscribeElem, 'hide'); + vAPI.messaging.send('scriptlets', { + what: 'applyFilterListSelection', + toImport: assetKey, + }).then(( ) => { + vAPI.messaging.send('scriptlets', { + what: 'reloadAllFilters' + }); + }); + }, { once: true }); + } + + if ( details.sourceURL ) { + const a = qs$('.cm-search-widget .sourceURL'); + dom.attr(a, 'href', details.sourceURL); + dom.attr(a, 'title', details.sourceURL); + } + + dom.cl.remove(dom.body, 'loading'); +})(); diff --git a/src/js/assets.js b/src/js/assets.js new file mode 100644 index 0000000..69c2ef3 --- /dev/null +++ b/src/js/assets.js @@ -0,0 +1,1478 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import µb from './background.js'; +import { broadcast } from './broadcast.js'; +import cacheStorage from './cachestorage.js'; +import { ubolog } from './console.js'; +import { i18n$ } from './i18n.js'; +import logger from './logger.js'; +import * as sfp from './static-filtering-parser.js'; +import { orphanizeString, } from './text-utils.js'; + +/******************************************************************************/ + +const reIsExternalPath = /^(?:[a-z-]+):\/\//; +const reIsUserAsset = /^user-/; +const errorCantConnectTo = i18n$('errorCantConnectTo'); +const MS_PER_HOUR = 60 * 60 * 1000; +const MS_PER_DAY = 24 * MS_PER_HOUR; +const MINUTES_PER_DAY = 24 * 60; +const EXPIRES_DEFAULT = 7; + +const assets = {}; + +// A hint for various pieces of code to take measures if possible to save +// bandwidth of remote servers. +let remoteServerFriendly = false; + +/******************************************************************************/ + +const stringIsNotEmpty = s => typeof s === 'string' && s !== ''; + +const parseExpires = s => { + const matches = s.match(/(\d+)\s*([dhm]?)/i); + if ( matches === null ) { return; } + let updateAfter = parseInt(matches[1], 10); + if ( matches[2] === 'h' ) { + updateAfter = Math.max(updateAfter, 4) / 24; + } else if ( matches[2] === 'm' ) { + updateAfter = Math.max(updateAfter, 240) / 1440; + } + return updateAfter; +}; + +const 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 && orphanizeString(value); + } + // Pre-process known fields + if ( out.lastModified ) { + out.lastModified = (new Date(out.lastModified)).getTime() || 0; + } + if ( out.expires ) { + out.expires = parseExpires(out.expires); + } + if ( out.diffExpires ) { + out.diffExpires = parseExpires(out.diffExpires); + } + return out; +}; +assets.extractMetadataFromList = extractMetadataFromList; + +const resourceTimeFromXhr = xhr => { + if ( typeof xhr.response !== 'string' ) { return 0; } + const metadata = extractMetadataFromList(xhr.response, [ + 'Last-Modified' + ]); + return metadata.lastModified || 0; +}; + +const resourceTimeFromParts = (parts, time) => { + const goodParts = parts.filter(part => typeof part === 'object'); + return goodParts.reduce((acc, part) => + ((part.resourceTime || 0) > acc ? part.resourceTime : acc), + time + ); +}; + +const resourceIsStale = (networkDetails, cacheDetails) => { + if ( typeof networkDetails.resourceTime !== 'number' ) { return false; } + if ( networkDetails.resourceTime === 0 ) { return false; } + if ( typeof cacheDetails.resourceTime !== 'number' ) { return false; } + if ( cacheDetails.resourceTime === 0 ) { return false; } + if ( networkDetails.resourceTime < cacheDetails.resourceTime ) { + ubolog(`Skip ${networkDetails.url}\n\tolder than ${cacheDetails.remoteURL}`); + return true; + } + return false; +}; + +const getUpdateAfterTime = (assetKey, diff = false) => { + const entry = assetCacheRegistry[assetKey]; + if ( entry ) { + if ( diff && typeof entry.diffExpires === 'number' ) { + return entry.diffExpires * MS_PER_DAY; + } + if ( typeof entry.expires === 'number' ) { + return entry.expires * MS_PER_DAY; + } + } + if ( assetSourceRegistry ) { + const entry = assetSourceRegistry[assetKey]; + if ( entry && typeof entry.updateAfter === 'number' ) { + return entry.updateAfter * MS_PER_DAY; + } + } + return EXPIRES_DEFAULT * MS_PER_DAY; // default to 7-day +}; + +const getWriteTime = assetKey => { + const entry = assetCacheRegistry[assetKey]; + if ( entry ) { return entry.writeTime || 0; } + return 0; +}; + +const isDiffUpdatableAsset = content => { + if ( typeof content !== 'string' ) { return false; } + const data = extractMetadataFromList(content, [ + 'Diff-Path', + ]); + return typeof data.diffPath === 'string' && + data.diffPath.startsWith('%') === false; +}; + +const computedPatchUpdateTime = assetKey => { + const entry = assetCacheRegistry[assetKey]; + if ( entry === undefined ) { return 0; } + if ( typeof entry.diffPath !== 'string' ) { return 0; } + if ( typeof entry.diffExpires !== 'number' ) { return 0; } + const match = /(\d+)\.(\d+)\.(\d+)\.(\d+)/.exec(entry.diffPath); + if ( match === null ) { return getWriteTime(); } + const date = new Date(); + date.setUTCFullYear( + parseInt(match[1], 10), + parseInt(match[2], 10) - 1, + parseInt(match[3], 10) + ); + date.setUTCHours(0, parseInt(match[4], 10) + entry.diffExpires * MINUTES_PER_DAY, 0, 0); + return date.getTime(); +}; + +/******************************************************************************/ + +// favorLocal: avoid making network requests whenever possible +// favorOrigin: avoid using CDN URLs whenever possible + +const getContentURLs = (assetKey, options = {}) => { + const contentURLs = []; + const entry = assetSourceRegistry[assetKey]; + if ( entry instanceof Object === false ) { return contentURLs; } + if ( typeof entry.contentURL === 'string' ) { + contentURLs.push(entry.contentURL); + } else if ( Array.isArray(entry.contentURL) ) { + contentURLs.push(...entry.contentURL); + } else if ( reIsExternalPath.test(assetKey) ) { + contentURLs.push(assetKey); + } + if ( options.favorLocal ) { + contentURLs.sort((a, b) => { + if ( reIsExternalPath.test(a) ) { return 1; } + if ( reIsExternalPath.test(b) ) { return -1; } + return 0; + }); + } + if ( options.favorOrigin !== true && Array.isArray(entry.cdnURLs) ) { + const cdnURLs = entry.cdnURLs.slice(); + for ( let i = 0, n = cdnURLs.length; i < n; i++ ) { + const j = Math.floor(Math.random() * n); + if ( j === i ) { continue; } + [ cdnURLs[j], cdnURLs[i] ] = [ cdnURLs[i], cdnURLs[j] ]; + } + if ( options.favorLocal ) { + contentURLs.push(...cdnURLs); + } else { + contentURLs.unshift(...cdnURLs); + } + } + return contentURLs; +}; + +/******************************************************************************/ + +const observers = []; + +assets.addObserver = function(observer) { + if ( observers.indexOf(observer) === -1 ) { + observers.push(observer); + } +}; + +assets.removeObserver = function(observer) { + let pos; + while ( (pos = observers.indexOf(observer)) !== -1 ) { + observers.splice(pos, 1); + } +}; + +const fireNotification = function(topic, details) { + let result; + for ( const observer of observers ) { + const r = observer(topic, details); + if ( r !== undefined ) { result = r; } + } + return result; +}; + +/******************************************************************************/ + +assets.fetch = function(url, options = {}) { + return new Promise((resolve, reject) => { + // Start of executor + + const timeoutAfter = µb.hiddenSettings.assetFetchTimeout || 30; + const xhr = new XMLHttpRequest(); + let contentLoaded = 0; + + const cleanup = function() { + xhr.removeEventListener('load', onLoadEvent); + xhr.removeEventListener('error', onErrorEvent); + xhr.removeEventListener('abort', onErrorEvent); + xhr.removeEventListener('progress', onProgressEvent); + timeoutTimer.off(); + }; + + const fail = function(details, msg) { + logger.writeOne({ + realm: 'message', + type: 'error', + text: msg, + }); + details.content = ''; + details.error = msg; + reject(details); + }; + + // https://github.com/gorhill/uMatrix/issues/15 + const onLoadEvent = function() { + cleanup(); + // xhr for local files gives status 0, but actually succeeds + const details = { + url, + statusCode: this.status || 200, + statusText: this.statusText || '' + }; + if ( details.statusCode < 200 || details.statusCode >= 300 ) { + return fail(details, `${url}: ${details.statusCode} ${details.statusText}`); + } + details.content = this.response; + details.resourceTime = resourceTimeFromXhr(this); + resolve(details); + }; + + const onErrorEvent = function() { + cleanup(); + fail({ url }, errorCantConnectTo.replace('{{msg}}', url)); + }; + + const onTimeout = function() { + xhr.abort(); + }; + + // https://github.com/gorhill/uBlock/issues/2526 + // - Timeout only when there is no progress. + const onProgressEvent = function(ev) { + if ( ev.loaded === contentLoaded ) { return; } + contentLoaded = ev.loaded; + timeoutTimer.offon({ sec: timeoutAfter }); + }; + + const timeoutTimer = vAPI.defer.create(onTimeout); + + // Be ready for thrown exceptions: + // I am pretty sure it used to work, but now using a URL such as + // `file:///` on Chromium 40 results in an exception being thrown. + try { + xhr.open('get', url, true); + xhr.addEventListener('load', onLoadEvent); + xhr.addEventListener('error', onErrorEvent); + xhr.addEventListener('abort', onErrorEvent); + xhr.addEventListener('progress', onProgressEvent); + xhr.responseType = options.responseType || 'text'; + xhr.send(); + timeoutTimer.on({ sec: timeoutAfter }); + } catch (e) { + onErrorEvent.call(xhr); + } + + // End of executor + }); +}; + +/******************************************************************************/ + +assets.fetchText = async function(url) { + const isExternal = reIsExternalPath.test(url); + let actualUrl = isExternal ? url : vAPI.getURL(url); + + // https://github.com/gorhill/uBlock/issues/2592 + // Force browser cache to be bypassed, but only for resources which have + // been fetched more than one hour ago. + // https://github.com/uBlockOrigin/uBlock-issues/issues/682#issuecomment-515197130 + // Provide filter list authors a way to completely bypass + // the browser cache. + // https://github.com/gorhill/uBlock/commit/048bfd251c9b#r37972005 + // Use modulo prime numbers to avoid generating the same token at the + // same time across different days. + // Do not bypass browser cache if we are asked to be gentle on remote + // servers. + if ( isExternal && remoteServerFriendly !== true ) { + const cacheBypassToken = + µb.hiddenSettings.updateAssetBypassBrowserCache + ? Math.floor(Date.now() / 1000) % 86413 + : Math.floor(Date.now() / 3600000) % 13; + const queryValue = `_=${cacheBypassToken}`; + if ( actualUrl.indexOf('?') === -1 ) { + actualUrl += '?'; + } else { + actualUrl += '&'; + } + actualUrl += queryValue; + } + + let details = { content: '' }; + try { + details = await assets.fetch(actualUrl); + + // Consider an empty result to be an error + if ( stringIsNotEmpty(details.content) === false ) { + details.content = ''; + } + + // We never download anything else than plain text: discard if + // response appears to be a HTML document: could happen when server + // serves some kind of error page for example. + const text = details.content.trim(); + if ( text.startsWith('<') && text.endsWith('>') ) { + details.content = ''; + details.error = 'assets.fetchText(): Not a text file'; + } + } catch(ex) { + details = ex; + } + + // We want to return the caller's URL, not our internal one which may + // differ from the caller's one. + details.url = url; + + return details; +}; + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/3331 +// Support the seamless loading of sublists. + +assets.fetchFilterList = async function(mainlistURL) { + const toParsedURL = url => { + try { + return new URL(url.trim()); + } catch (ex) { + } + }; + + // https://github.com/NanoAdblocker/NanoCore/issues/239 + // Anything under URL's root directory is allowed to be fetched. The + // URL of a sublist will always be relative to the URL of the parent + // list (instead of the URL of the root list). + let rootDirectoryURL = toParsedURL( + reIsExternalPath.test(mainlistURL) + ? mainlistURL + : vAPI.getURL(mainlistURL) + ); + if ( rootDirectoryURL !== undefined ) { + const pos = rootDirectoryURL.pathname.lastIndexOf('/'); + if ( pos !== -1 ) { + rootDirectoryURL.pathname = + rootDirectoryURL.pathname.slice(0, pos + 1); + } else { + rootDirectoryURL = undefined; + } + } + + const sublistURLs = new Set(); + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1113 + // Process only `!#include` directives which are not excluded by an + // `!#if` directive. + const processIncludeDirectives = function(results) { + const out = []; + const reInclude = /^!#include +(\S+)[^\n\r]*(?:[\n\r]+|$)/gm; + for ( const result of results ) { + if ( typeof result === 'string' ) { + out.push(result); + continue; + } + if ( result instanceof Object === false ) { continue; } + const content = result.content; + const slices = sfp.utils.preparser.splitter( + content, + vAPI.webextFlavor.env + ); + for ( let i = 0, n = slices.length - 1; i < n; i++ ) { + const slice = content.slice(slices[i+0], slices[i+1]); + if ( (i & 1) !== 0 ) { + out.push(slice); + continue; + } + let lastIndex = 0; + for (;;) { + if ( rootDirectoryURL === undefined ) { break; } + const match = reInclude.exec(slice); + if ( match === null ) { break; } + if ( toParsedURL(match[1]) !== undefined ) { continue; } + if ( match[1].indexOf('..') !== -1 ) { continue; } + // Compute nested list path relative to parent list path + const pos = result.url.lastIndexOf('/'); + if ( pos === -1 ) { continue; } + const subURL = result.url.slice(0, pos + 1) + match[1].trim(); + if ( sublistURLs.has(subURL) ) { continue; } + sublistURLs.add(subURL); + out.push( + slice.slice(lastIndex, match.index + match[0].length), + `! >>>>>>>> ${subURL}\n`, + assets.fetchText(subURL), + `! <<<<<<<< ${subURL}\n` + ); + lastIndex = reInclude.lastIndex; + } + out.push(lastIndex === 0 ? slice : slice.slice(lastIndex)); + } + } + return out; + }; + + // https://github.com/AdguardTeam/FiltersRegistry/issues/82 + // Not checking for `errored` status was causing repeated notifications + // to the caller. This can happen when more than one out of multiple + // sublists can't be fetched. + + let allParts = [ + this.fetchText(mainlistURL) + ]; + // Abort processing `include` directives if at least one included sublist + // can't be fetched. + let resourceTime = 0; + do { + allParts = await Promise.all(allParts); + const part = allParts + .find(part => typeof part === 'object' && part.error !== undefined); + if ( part !== undefined ) { + return { url: mainlistURL, content: '', error: part.error }; + } + resourceTime = resourceTimeFromParts(allParts, resourceTime); + // Skip pre-parser directives for diff-updatable assets + if ( allParts.length === 1 && allParts[0] instanceof Object ) { + if ( isDiffUpdatableAsset(allParts[0].content) ) { + allParts[0] = allParts[0].content; + break; + } + } + allParts = processIncludeDirectives(allParts); + } while ( allParts.some(part => typeof part !== 'string') ); + // If we reach this point, this means all fetches were successful. + return { + url: mainlistURL, + resourceTime, + content: allParts.length === 1 + ? allParts[0] + : allParts.join('') + '\n' + }; +}; + +/******************************************************************************* + + The purpose of the asset source registry is to keep key detail information + about an asset: + - Where to load it from: this may consist of one or more URLs, either local + or remote. + - After how many days an asset should be deemed obsolete -- i.e. in need of + an update. + - The origin and type of an asset. + - The last time an asset was registered. + +**/ + +let assetSourceRegistryPromise; +let assetSourceRegistry = Object.create(null); + +function getAssetSourceRegistry() { + if ( assetSourceRegistryPromise === undefined ) { + assetSourceRegistryPromise = cacheStorage.get( + 'assetSourceRegistry' + ).then(bin => { + if ( + bin instanceof Object && + bin.assetSourceRegistry instanceof Object + ) { + assetSourceRegistry = bin.assetSourceRegistry; + return assetSourceRegistry; + } + return assets.fetchText( + µb.assetsBootstrapLocation || µb.assetsJsonPath + ).then(details => { + return details.content !== '' + ? details + : assets.fetchText(µb.assetsJsonPath); + }).then(details => { + updateAssetSourceRegistry(details.content, true); + return assetSourceRegistry; + }); + }); + } + + return assetSourceRegistryPromise; +} + +function registerAssetSource(assetKey, newDict) { + const currentDict = assetSourceRegistry[assetKey] || {}; + for ( const [ k, v ] of Object.entries(newDict) ) { + if ( v === undefined || v === null ) { + delete currentDict[k]; + } else { + currentDict[k] = newDict[k]; + } + } + let contentURL = newDict.contentURL; + if ( contentURL !== undefined ) { + if ( typeof contentURL === 'string' ) { + contentURL = currentDict.contentURL = [ contentURL ]; + } else if ( Array.isArray(contentURL) === false ) { + contentURL = currentDict.contentURL = []; + } + let remoteURLCount = 0; + for ( let i = 0; i < contentURL.length; i++ ) { + if ( reIsExternalPath.test(contentURL[i]) ) { + remoteURLCount += 1; + } + } + currentDict.hasLocalURL = remoteURLCount !== contentURL.length; + currentDict.hasRemoteURL = remoteURLCount !== 0; + } else if ( currentDict.contentURL === undefined ) { + currentDict.contentURL = []; + } + if ( currentDict.submitter ) { + currentDict.submitTime = Date.now(); // To detect stale entries + } + assetSourceRegistry[assetKey] = currentDict; +} + +function unregisterAssetSource(assetKey) { + assetCacheRemove(assetKey); + delete assetSourceRegistry[assetKey]; +} + +const saveAssetSourceRegistry = (( ) => { + const save = ( ) => { + timer.off(); + cacheStorage.set({ assetSourceRegistry }); + }; + const timer = vAPI.defer.create(save); + return function(lazily) { + if ( lazily ) { + timer.offon(500); + } else { + save(); + } + }; +})(); + +async function assetSourceGetDetails(assetKey) { + await getAssetSourceRegistry(); + const entry = assetSourceRegistry[assetKey]; + if ( entry === undefined ) { return; } + return entry; +} + +function updateAssetSourceRegistry(json, silent = false) { + let newDict; + try { + newDict = JSON.parse(json); + newDict['assets.json'].defaultListset = + Array.from(Object.entries(newDict)) + .filter(a => a[1].content === 'filters' && a[1].off === undefined) + .map(a => a[0]); + } catch (ex) { + } + if ( newDict instanceof Object === false ) { return; } + + const oldDict = assetSourceRegistry; + + fireNotification('assets.json-updated', { newDict, oldDict }); + + // Remove obsolete entries (only those which were built-in). + for ( const assetKey in oldDict ) { + if ( + newDict[assetKey] === undefined && + oldDict[assetKey].submitter === undefined + ) { + unregisterAssetSource(assetKey); + } + } + // Add/update existing entries. Notify of new asset sources. + for ( const assetKey in newDict ) { + if ( oldDict[assetKey] === undefined && !silent ) { + fireNotification( + 'builtin-asset-source-added', + { assetKey: assetKey, entry: newDict[assetKey] } + ); + } + registerAssetSource(assetKey, newDict[assetKey]); + } + saveAssetSourceRegistry(); +} + +assets.registerAssetSource = async function(assetKey, details) { + await getAssetSourceRegistry(); + registerAssetSource(assetKey, details); + saveAssetSourceRegistry(true); +}; + +assets.unregisterAssetSource = async function(assetKey) { + await getAssetSourceRegistry(); + unregisterAssetSource(assetKey); + saveAssetSourceRegistry(true); +}; + +/******************************************************************************* + + The purpose of the asset cache registry is to keep track of all assets + which have been persisted into the local cache. + +**/ + +const assetCacheRegistryStartTime = Date.now(); +let assetCacheRegistryPromise; +let assetCacheRegistry = {}; + +function getAssetCacheRegistry() { + if ( assetCacheRegistryPromise === undefined ) { + assetCacheRegistryPromise = cacheStorage.get( + 'assetCacheRegistry' + ).then(bin => { + if ( + bin instanceof Object && + bin.assetCacheRegistry instanceof Object + ) { + if ( Object.keys(assetCacheRegistry).length === 0 ) { + assetCacheRegistry = bin.assetCacheRegistry; + } else { + console.error( + 'getAssetCacheRegistry(): assetCacheRegistry reassigned!' + ); + if ( + Object.keys(bin.assetCacheRegistry).sort().join() !== + Object.keys(assetCacheRegistry).sort().join() + ) { + console.error( + 'getAssetCacheRegistry(): assetCacheRegistry changes overwritten!' + ); + } + } + } + return assetCacheRegistry; + }); + } + + return assetCacheRegistryPromise; +} + +const saveAssetCacheRegistry = (( ) => { + const save = function() { + timer.off(); + cacheStorage.set({ assetCacheRegistry }); + }; + const timer = vAPI.defer.create(save); + return function(lazily) { + if ( lazily ) { + timer.offon({ sec: 30 }); + } else { + save(); + } + }; +})(); + +async function assetCacheRead(assetKey, updateReadTime = false) { + const t0 = Date.now(); + const internalKey = `cache/${assetKey}`; + + const reportBack = function(content) { + if ( content instanceof Blob ) { content = ''; } + const details = { assetKey, content }; + if ( content === '' ) { details.error = 'ENOTFOUND'; } + return details; + }; + + const [ , bin ] = await Promise.all([ + getAssetCacheRegistry(), + cacheStorage.get(internalKey), + ]); + + if ( µb.readyToFilter !== true ) { + µb.supportStats.maxAssetCacheWait = Math.max( + Date.now() - t0, + parseInt(µb.supportStats.maxAssetCacheWait, 10) || 0 + ) + ' ms'; + } + + if ( + bin instanceof Object === false || + bin.hasOwnProperty(internalKey) === false + ) { + return reportBack(''); + } + + const entry = assetCacheRegistry[assetKey]; + if ( entry === undefined ) { + return reportBack(''); + } + + entry.readTime = Date.now(); + if ( updateReadTime ) { + saveAssetCacheRegistry(true); + } + + return reportBack(bin[internalKey]); +} + +async function assetCacheWrite(assetKey, details) { + let content = ''; + let options = {}; + if ( typeof details === 'string' ) { + content = details; + } else if ( details instanceof Object ) { + content = details.content || ''; + options = details; + } + + if ( content === '' ) { + return assetCacheRemove(assetKey); + } + + const cacheDict = await getAssetCacheRegistry(); + + let entry = cacheDict[assetKey]; + if ( entry === undefined ) { + entry = cacheDict[assetKey] = {}; + } + entry.writeTime = entry.readTime = Date.now(); + entry.resourceTime = options.resourceTime || 0; + if ( typeof options.url === 'string' ) { + entry.remoteURL = options.url; + } + cacheStorage.set({ + assetCacheRegistry, + [`cache/${assetKey}`]: content + }); + + const result = { assetKey, content }; + // https://github.com/uBlockOrigin/uBlock-issues/issues/248 + if ( options.silent !== true ) { + fireNotification('after-asset-updated', result); + } + return result; +} + +async function assetCacheRemove(pattern) { + const cacheDict = await getAssetCacheRegistry(); + const removedEntries = []; + const removedContent = []; + for ( const assetKey in cacheDict ) { + if ( pattern instanceof RegExp && !pattern.test(assetKey) ) { + continue; + } + if ( typeof pattern === 'string' && assetKey !== pattern ) { + continue; + } + removedEntries.push(assetKey); + removedContent.push('cache/' + assetKey); + delete cacheDict[assetKey]; + } + if ( removedContent.length !== 0 ) { + await Promise.all([ + cacheStorage.remove(removedContent), + cacheStorage.set({ assetCacheRegistry }), + ]); + } + for ( let i = 0; i < removedEntries.length; i++ ) { + fireNotification('after-asset-updated', { + assetKey: removedEntries[i] + }); + } +} + +async function assetCacheGetDetails(assetKey) { + const cacheDict = await getAssetCacheRegistry(); + const entry = cacheDict[assetKey]; + if ( entry === undefined ) { return; } + return entry; +} + +async function assetCacheSetDetails(assetKey, details) { + const cacheDict = await getAssetCacheRegistry(); + const entry = cacheDict[assetKey]; + if ( entry === undefined ) { return; } + let modified = false; + for ( const [ k, v ] of Object.entries(details) ) { + if ( v === undefined ) { + if ( entry[k] !== undefined ) { + delete entry[k]; + modified = true; + continue; + } + } + if ( v !== entry[k] ) { + entry[k] = v; + modified = true; + } + } + if ( modified ) { + saveAssetCacheRegistry(); + } +} + +async function assetCacheMarkAsDirty(pattern, exclude) { + const cacheDict = await getAssetCacheRegistry(); + let mustSave = false; + for ( const assetKey in cacheDict ) { + if ( pattern instanceof RegExp ) { + if ( pattern.test(assetKey) === false ) { continue; } + } else if ( typeof pattern === 'string' ) { + if ( assetKey !== pattern ) { continue; } + } else if ( Array.isArray(pattern) ) { + if ( pattern.indexOf(assetKey) === -1 ) { continue; } + } + if ( exclude instanceof RegExp ) { + if ( exclude.test(assetKey) ) { continue; } + } else if ( typeof exclude === 'string' ) { + if ( assetKey === exclude ) { continue; } + } else if ( Array.isArray(exclude) ) { + if ( exclude.indexOf(assetKey) !== -1 ) { continue; } + } + const cacheEntry = cacheDict[assetKey]; + if ( !cacheEntry.writeTime ) { continue; } + cacheDict[assetKey].writeTime = 0; + mustSave = true; + } + if ( mustSave ) { + cacheStorage.set({ assetCacheRegistry }); + } +} + +/******************************************************************************* + + User assets are NOT persisted in the cache storage. User assets are + recognized by the asset key which always starts with 'user-'. + + TODO(seamless migration): + Can remove instances of old user asset keys when I am confident all users + are using uBO v1.11 and beyond. + +**/ + +/******************************************************************************* + + User assets are NOT persisted in the cache storage. User assets are + recognized by the asset key which always starts with 'user-'. + +**/ + +const readUserAsset = async function(assetKey) { + const bin = await vAPI.storage.get(assetKey); + const content = + bin instanceof Object && typeof bin[assetKey] === 'string' + ? bin[assetKey] + : ''; + return { assetKey, content }; +}; + +const saveUserAsset = function(assetKey, content) { + return vAPI.storage.set({ [assetKey]: content }).then(( ) => { + return { assetKey, content }; + }); +}; + +/******************************************************************************/ + +assets.get = async function(assetKey, options = {}) { + if ( assetKey === µb.userFiltersPath ) { + return readUserAsset(assetKey); + } + + let assetDetails = {}; + + const reportBack = (content, url = '', err = undefined) => { + const details = { assetKey, content }; + if ( err !== undefined ) { + details.error = assetDetails.lastError = err; + } else { + assetDetails.lastError = undefined; + } + if ( options.needSourceURL ) { + if ( + url === '' && + assetCacheRegistry instanceof Object && + assetCacheRegistry[assetKey] instanceof Object + ) { + details.sourceURL = assetCacheRegistry[assetKey].remoteURL; + } + if ( reIsExternalPath.test(url) ) { + details.sourceURL = url; + } + } + return details; + }; + + // Skip read-time property for non-updatable assets: the property is + // completely unused for such assets and thus there is no point incurring + // storage write overhead at launch when reading compiled or selfie assets. + const updateReadTime = /^(?:compiled|selfie)\//.test(assetKey) === false; + + const details = await assetCacheRead(assetKey, updateReadTime); + if ( details.content !== '' ) { + return reportBack(details.content); + } + + const assetRegistry = await getAssetSourceRegistry(); + + assetDetails = assetRegistry[assetKey] || {}; + + const contentURLs = getContentURLs(assetKey, options); + if ( contentURLs.length === 0 && reIsExternalPath.test(assetKey) ) { + assetDetails.content = 'filters'; + contentURLs.push(assetKey); + } + + let error = 'ENOTFOUND'; + for ( const contentURL of contentURLs ) { + const details = assetDetails.content === 'filters' + ? await assets.fetchFilterList(contentURL) + : await assets.fetchText(contentURL); + if ( details.error !== undefined ) { + error = details.error; + } + if ( details.content === '' ) { continue; } + if ( reIsExternalPath.test(contentURL) && options.dontCache !== true ) { + assetCacheWrite(assetKey, { + content: details.content, + url: contentURL, + silent: options.silent === true, + }); + registerAssetSource(assetKey, { error: undefined }); + if ( assetDetails.content === 'filters' ) { + const metadata = extractMetadataFromList(details.content, [ + 'Last-Modified', + 'Expires', + 'Diff-Name', + 'Diff-Path', + 'Diff-Expires', + ]); + metadata.diffUpdated = undefined; + assetCacheSetDetails(assetKey, metadata); + } + } + return reportBack(details.content, contentURL); + } + if ( assetRegistry[assetKey] !== undefined ) { + registerAssetSource(assetKey, { + error: { time: Date.now(), error } + }); + } + return reportBack('', '', error); +}; + +/******************************************************************************/ + +async function getRemote(assetKey, options = {}) { + const [ + assetDetails = {}, + cacheDetails = {}, + ] = await Promise.all([ + assetSourceGetDetails(assetKey), + assetCacheGetDetails(assetKey), + ]); + + let error; + let stale = false; + + const reportBack = function(content, url = '', err = '') { + const details = { assetKey, content, url }; + if ( err !== '') { + details.error = assetDetails.lastError = err; + } else { + assetDetails.lastError = undefined; + } + return details; + }; + + for ( const contentURL of getContentURLs(assetKey, options) ) { + if ( reIsExternalPath.test(contentURL) === false ) { continue; } + + const result = assetDetails.content === 'filters' + ? await assets.fetchFilterList(contentURL) + : await assets.fetchText(contentURL); + + // Failure + if ( stringIsNotEmpty(result.content) === false ) { + error = result.statusText; + if ( result.statusCode === 0 ) { + error = 'network error'; + } + continue; + } + + error = undefined; + + // If fetched resource is older than cached one, ignore + if ( options.favorOrigin !== true ) { + stale = resourceIsStale(result, cacheDetails); + if ( stale ) { continue; } + } + + // Success + assetCacheWrite(assetKey, { + content: result.content, + url: contentURL, + resourceTime: result.resourceTime || 0, + }); + + if ( assetDetails.content === 'filters' ) { + const metadata = extractMetadataFromList(result.content, [ + 'Last-Modified', + 'Expires', + 'Diff-Name', + 'Diff-Path', + 'Diff-Expires', + ]); + metadata.diffUpdated = undefined; + assetCacheSetDetails(assetKey, metadata); + } + + registerAssetSource(assetKey, { birthtime: undefined, error: undefined }); + return reportBack(result.content, contentURL); + } + + if ( error !== undefined ) { + registerAssetSource(assetKey, { error: { time: Date.now(), error } }); + return reportBack('', '', 'ENOTFOUND'); + } + + if ( stale ) { + assetCacheSetDetails(assetKey, { writeTime: cacheDetails.resourceTime }); + } + + return reportBack(''); +} + +/******************************************************************************/ + +assets.put = async function(assetKey, content) { + return reIsUserAsset.test(assetKey) + ? await saveUserAsset(assetKey, content) + : await assetCacheWrite(assetKey, content); +}; + +/******************************************************************************/ + +assets.metadata = async function() { + await Promise.all([ + getAssetSourceRegistry(), + getAssetCacheRegistry(), + ]); + + const assetDict = JSON.parse(JSON.stringify(assetSourceRegistry)); + const cacheDict = assetCacheRegistry; + const now = Date.now(); + for ( const assetKey in assetDict ) { + const assetEntry = assetDict[assetKey]; + const cacheEntry = cacheDict[assetKey]; + if ( + assetEntry.content === 'filters' && + assetEntry.external !== true + ) { + assetEntry.isDefault = + assetEntry.off === undefined || + assetEntry.off === true && + µb.listMatchesEnvironment(assetEntry); + } + if ( cacheEntry ) { + assetEntry.cached = true; + assetEntry.writeTime = cacheEntry.writeTime; + const obsoleteAfter = cacheEntry.writeTime + getUpdateAfterTime(assetKey); + assetEntry.obsolete = obsoleteAfter < now; + assetEntry.remoteURL = cacheEntry.remoteURL; + if ( cacheEntry.diffUpdated ) { + assetEntry.diffUpdated = cacheEntry.diffUpdated; + } + } else if ( + assetEntry.contentURL && + assetEntry.contentURL.length !== 0 + ) { + assetEntry.writeTime = 0; + assetEntry.obsolete = true; + } + } + + return assetDict; +}; + +/******************************************************************************/ + +assets.purge = assetCacheMarkAsDirty; + +assets.remove = function(pattern) { + return assetCacheRemove(pattern); +}; + +assets.rmrf = function() { + return assetCacheRemove(/./); +}; + +/******************************************************************************/ + +assets.getUpdateAges = async function(conditions = {}) { + const assetDict = await assets.metadata(); + const now = Date.now(); + const out = []; + for ( const [ assetKey, asset ] of Object.entries(assetDict) ) { + if ( asset.hasRemoteURL !== true ) { continue; } + const tokens = conditions[asset.content]; + if ( Array.isArray(tokens) === false ) { continue; } + if ( tokens.includes('*') === false ) { + if ( tokens.includes(assetKey) === false ) { continue; } + } + const age = now - (asset.writeTime || 0); + out.push({ + assetKey, + age, + ageNormalized: age / Math.max(1, getUpdateAfterTime(assetKey)), + }); + } + return out; +}; + +/******************************************************************************/ + +// Asset updater area. +const updaterAssetDelayDefault = 120000; +const updaterUpdated = []; +const updaterFetched = new Set(); + +let updaterStatus; +let updaterAssetDelay = updaterAssetDelayDefault; +let updaterAuto = false; + +const getAssetDiffDetails = assetKey => { + const out = { assetKey }; + const cacheEntry = assetCacheRegistry[assetKey]; + if ( cacheEntry === undefined ) { return; } + out.patchPath = cacheEntry.diffPath; + if ( out.patchPath === undefined ) { return; } + const match = /#.+$/.exec(out.patchPath); + if ( match !== null ) { + out.diffName = match[0].slice(1); + } else { + out.diffName = cacheEntry.diffName; + } + if ( out.diffName === undefined ) { return; } + out.diffExpires = getUpdateAfterTime(assetKey, true); + out.lastModified = cacheEntry.lastModified; + out.writeTime = cacheEntry.writeTime; + const assetEntry = assetSourceRegistry[assetKey]; + if ( assetEntry === undefined ) { return; } + if ( assetEntry.content !== 'filters' ) { return; } + if ( Array.isArray(assetEntry.cdnURLs) ) { + out.cdnURLs = assetEntry.cdnURLs.slice(); + } else if ( reIsExternalPath.test(assetKey) ) { + out.cdnURLs = [ assetKey ]; + } else if ( typeof assetEntry.contentURL === 'string' ) { + out.cdnURLs = [ assetEntry.contentURL ]; + } else if ( Array.isArray(assetEntry.contentURL) ) { + out.cdnURLs = assetEntry.contentURL.slice(0).filter(url => + reIsExternalPath.test(url) + ); + } + if ( Array.isArray(out.cdnURLs) === false ) { return; } + if ( out.cdnURLs.length === 0 ) { return; } + return out; +}; + +async function diffUpdater() { + if ( updaterAuto === false ) { return; } + if ( µb.hiddenSettings.differentialUpdate === false ) { return; } + const toUpdate = await getUpdateCandidates(); + const now = Date.now(); + const toHardUpdate = []; + const toSoftUpdate = []; + while ( toUpdate.length !== 0 ) { + const assetKey = toUpdate.shift(); + const assetDetails = getAssetDiffDetails(assetKey); + if ( assetDetails === undefined ) { continue; } + assetDetails.what = 'update'; + const computedUpdateTime = computedPatchUpdateTime(assetKey); + if ( computedUpdateTime !== 0 && computedUpdateTime <= now ) { + assetDetails.fetch = true; + toHardUpdate.push(assetDetails); + } else { + assetDetails.fetch = false; + toSoftUpdate.push(assetDetails); + } + } + if ( toHardUpdate.length === 0 ) { return; } + ubolog('Diff updater: cycle start'); + return new Promise(resolve => { + let pendingOps = 0; + const bc = new globalThis.BroadcastChannel('diffUpdater'); + const terminate = error => { + worker.terminate(); + bc.close(); + resolve(); + if ( typeof error !== 'string' ) { return; } + ubolog(`Diff updater: terminate because ${error}`); + }; + const checkAndCorrectDiffPath = data => { + if ( typeof data.text !== 'string' ) { return; } + if ( data.text === '' ) { return; } + const metadata = extractMetadataFromList(data.text, [ 'Diff-Path' ]); + if ( metadata instanceof Object === false ) { return; } + if ( metadata.diffPath === data.patchPath ) { return; } + assetCacheSetDetails(data.assetKey, metadata); + }; + bc.onmessage = ev => { + const data = ev.data || {}; + if ( data.what === 'ready' ) { + ubolog('Diff updater: hard updating', toHardUpdate.map(v => v.assetKey).join()); + while ( toHardUpdate.length !== 0 ) { + const assetDetails = toHardUpdate.shift(); + assetDetails.fetch = true; + bc.postMessage(assetDetails); + pendingOps += 1; + } + return; + } + if ( data.what === 'broken' ) { + terminate(data.error); + return; + } + if ( data.status === 'needtext' ) { + ubolog('Diff updater: need text for', data.assetKey); + assetCacheRead(data.assetKey).then(result => { + data.text = result.content; + data.status = undefined; + checkAndCorrectDiffPath(data); + bc.postMessage(data); + }); + return; + } + if ( data.status === 'updated' ) { + ubolog(`Diff updater: successfully patched ${data.assetKey} using ${data.patchURL} (${data.patchSize})`); + const metadata = extractMetadataFromList(data.text, [ + 'Last-Modified', + 'Expires', + 'Diff-Name', + 'Diff-Path', + 'Diff-Expires', + ]); + assetCacheWrite(data.assetKey, { + content: data.text, + resourceTime: metadata.lastModified || 0, + }); + metadata.diffUpdated = true; + assetCacheSetDetails(data.assetKey, metadata); + updaterUpdated.push(data.assetKey); + } else if ( data.error ) { + ubolog(`Diff updater: failed to update ${data.assetKey} using ${data.patchPath}\n\treason: ${data.error}`); + } else if ( data.status === 'nopatch-yet' || data.status === 'nodiff' ) { + ubolog(`Diff updater: skip update of ${data.assetKey} using ${data.patchPath}\n\treason: ${data.status}`); + assetCacheSetDetails(data.assetKey, { writeTime: data.writeTime }); + broadcast({ + what: 'assetUpdated', + key: data.assetKey, + cached: true, + }); + } else { + ubolog(`Diff updater: ${data.assetKey} / ${data.patchPath} / ${data.status}`); + } + pendingOps -= 1; + if ( pendingOps === 0 && toSoftUpdate.length !== 0 ) { + ubolog('Diff updater: soft updating', toSoftUpdate.map(v => v.assetKey).join()); + while ( toSoftUpdate.length !== 0 ) { + bc.postMessage(toSoftUpdate.shift()); + pendingOps += 1; + } + } + if ( pendingOps !== 0 ) { return; } + ubolog('Diff updater: cycle complete'); + terminate(); + }; + const worker = new Worker('js/diff-updater.js'); + }); +} + +function updateFirst() { + ubolog('Updater: cycle start'); + ubolog('Updater: prefer', updaterAuto ? 'CDNs' : 'origin'); + updaterStatus = 'updating'; + updaterFetched.clear(); + updaterUpdated.length = 0; + diffUpdater().catch(reason => { + ubolog(reason); + }).finally(( ) => { + updateNext(); + }); +} + +async function getUpdateCandidates() { + const [ assetDict, cacheDict ] = await Promise.all([ + getAssetSourceRegistry(), + getAssetCacheRegistry(), + ]); + const toUpdate = []; + for ( const assetKey in assetDict ) { + const assetEntry = assetDict[assetKey]; + if ( assetEntry.hasRemoteURL !== true ) { continue; } + if ( updaterFetched.has(assetKey) ) { continue; } + const cacheEntry = cacheDict[assetKey]; + if ( + fireNotification('before-asset-updated', { + assetKey, + type: assetEntry.content + }) === true + ) { + toUpdate.push(assetKey); + continue; + } + // This will remove a cached asset when it's no longer in use. + if ( cacheEntry && cacheEntry.readTime < assetCacheRegistryStartTime ) { + assetCacheRemove(assetKey); + } + } + // https://github.com/uBlockOrigin/uBlock-issues/issues/1165 + // Update most obsolete asset first. + toUpdate.sort((a, b) => { + const ta = cacheDict[a] !== undefined ? cacheDict[a].writeTime : 0; + const tb = cacheDict[b] !== undefined ? cacheDict[b].writeTime : 0; + return ta - tb; + }); + return toUpdate; +} + +async function updateNext() { + const toUpdate = await getUpdateCandidates(); + const now = Date.now(); + const toHardUpdate = []; + + while ( toUpdate.length !== 0 ) { + const assetKey = toUpdate.shift(); + const writeTime = getWriteTime(assetKey); + const updateDelay = getUpdateAfterTime(assetKey); + if ( (writeTime + updateDelay) > now ) { continue; } + toHardUpdate.push(assetKey); + } + if ( toHardUpdate.length === 0 ) { + return updateDone(); + } + + const assetKey = toHardUpdate.pop(); + updaterFetched.add(assetKey); + + // In auto-update context, be gentle on remote servers. + remoteServerFriendly = updaterAuto; + + let result; + if ( assetKey !== 'assets.json' || µb.hiddenSettings.debugAssetsJson !== true ) { + result = await getRemote(assetKey, { favorOrigin: updaterAuto === false }); + } else { + result = await assets.fetchText(µb.assetsJsonPath); + result.assetKey = 'assets.json'; + } + + remoteServerFriendly = false; + + if ( result.error ) { + ubolog(`Full updater: failed to update ${assetKey}`); + fireNotification('asset-update-failed', { assetKey: result.assetKey }); + } else { + ubolog(`Full updater: successfully updated ${assetKey}`); + updaterUpdated.push(result.assetKey); + if ( result.assetKey === 'assets.json' && result.content !== '' ) { + updateAssetSourceRegistry(result.content); + } + } + + updaterTimer.on(updaterAssetDelay); +} + +const updaterTimer = vAPI.defer.create(updateNext); + +function updateDone() { + const assetKeys = updaterUpdated.slice(0); + updaterFetched.clear(); + updaterUpdated.length = 0; + updaterStatus = undefined; + updaterAuto = false; + updaterAssetDelay = updaterAssetDelayDefault; + ubolog('Updater: cycle end'); + if ( assetKeys.length ) { + ubolog(`Updater: ${assetKeys.join()} were updated`); + } + fireNotification('after-assets-updated', { assetKeys }); +} + +assets.updateStart = function(details) { + const oldUpdateDelay = updaterAssetDelay; + const newUpdateDelay = typeof details.fetchDelay === 'number' + ? details.fetchDelay + : updaterAssetDelayDefault; + updaterAssetDelay = Math.min(oldUpdateDelay, newUpdateDelay); + updaterAuto = details.auto === true; + if ( updaterStatus !== undefined ) { + if ( newUpdateDelay < oldUpdateDelay ) { + updaterTimer.offon(updaterAssetDelay); + } + return; + } + updateFirst(); +}; + +assets.updateStop = function() { + updaterTimer.off(); + if ( updaterStatus !== undefined ) { + updateDone(); + } +}; + +assets.isUpdating = function() { + return updaterStatus === 'updating' && + updaterAssetDelay <= µb.hiddenSettings.manualUpdateAssetFetchPeriod; +}; + +/******************************************************************************/ + +export default assets; + +/******************************************************************************/ diff --git a/src/js/background.js b/src/js/background.js new file mode 100644 index 0000000..578d8a6 --- /dev/null +++ b/src/js/background.js @@ -0,0 +1,410 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ + +import logger from './logger.js'; +import { FilteringContext } from './filtering-context.js'; +import { ubologSet } from './console.js'; + +import { + domainFromHostname, + hostnameFromURI, + originFromURI, +} from './uri-utils.js'; + +/******************************************************************************/ + +// Not all platforms may have properly declared vAPI.webextFlavor. + +if ( vAPI.webextFlavor === undefined ) { + vAPI.webextFlavor = { major: 0, soup: new Set([ 'ublock' ]) }; +} + +/******************************************************************************/ + +const hiddenSettingsDefault = { + allowGenericProceduralFilters: false, + assetFetchTimeout: 30, + autoCommentFilterTemplate: '{{date}} {{origin}}', + autoUpdateAssetFetchPeriod: 15, + autoUpdateDelayAfterLaunch: 105, + autoUpdatePeriod: 1, + benchmarkDatasetURL: 'unset', + blockingProfiles: '11111/#F00 11010/#C0F 11001/#00F 00001', + cacheStorageAPI: 'unset', + cacheStorageCompression: true, + cacheControlForFirefox1376932: 'no-cache, no-store, must-revalidate', + cloudStorageCompression: true, + cnameIgnoreList: 'unset', + cnameIgnore1stParty: true, + cnameIgnoreExceptions: true, + cnameIgnoreRootDocument: true, + cnameMaxTTL: 120, + cnameReplayFullURL: false, + cnameUncloakProxied: false, + consoleLogLevel: 'unset', + debugAssetsJson: false, + debugScriptlets: false, + debugScriptletInjector: false, + differentialUpdate: true, + disableWebAssembly: false, + extensionUpdateForceReload: false, + filterAuthorMode: false, + loggerPopupType: 'popup', + manualUpdateAssetFetchPeriod: 500, + modifyWebextFlavor: 'unset', + popupFontSize: 'unset', + popupPanelDisabledSections: 0, + popupPanelLockedSections: 0, + popupPanelHeightMode: 0, + requestJournalProcessPeriod: 1000, + selfieAfter: 2, + strictBlockingBypassDuration: 120, + toolbarWarningTimeout: 60, + trustedListPrefixes: 'ublock-', + uiPopupConfig: 'unset', + uiStyles: 'unset', + updateAssetBypassBrowserCache: false, + userResourcesLocation: 'unset', +}; + +if ( vAPI.webextFlavor.soup.has('devbuild') ) { + hiddenSettingsDefault.consoleLogLevel = 'info'; + hiddenSettingsDefault.trustedListPrefixes += ' user-'; + ubologSet(true); +} + +const userSettingsDefault = { + advancedUserEnabled: false, + alwaysDetachLogger: true, + autoUpdate: true, + cloudStorageEnabled: false, + cnameUncloakEnabled: true, + collapseBlocked: true, + colorBlindFriendly: false, + contextMenuEnabled: true, + uiAccentCustom: false, + uiAccentCustom0: '#aca0f7', + uiTheme: 'auto', + externalLists: '', + firewallPaneMinimized: true, + hyperlinkAuditingDisabled: true, + ignoreGenericCosmeticFilters: vAPI.webextFlavor.soup.has('mobile'), + importedLists: [], + largeMediaSize: 50, + parseAllABPHideFilters: true, + popupPanelSections: 0b111, + prefetchingDisabled: true, + requestLogMaxEntries: 1000, + showIconBadge: true, + suspendUntilListsAreLoaded: vAPI.Net.canSuspend(), + tooltipsDisabled: false, + webrtcIPAddressHidden: false, +}; + +const dynamicFilteringDefault = [ + 'behind-the-scene * * noop', + 'behind-the-scene * image noop', + 'behind-the-scene * 3p noop', + 'behind-the-scene * inline-script noop', + 'behind-the-scene * 1p-script noop', + 'behind-the-scene * 3p-script noop', + 'behind-the-scene * 3p-frame noop', +]; + +const hostnameSwitchesDefault = [ + 'no-large-media: behind-the-scene false', +]; +// https://github.com/LiCybora/NanoDefenderFirefox/issues/196 +if ( vAPI.webextFlavor.soup.has('firefox') ) { + hostnameSwitchesDefault.push('no-csp-reports: * true'); +} + +const µBlock = { // jshint ignore:line + wakeupReason: '', + + userSettingsDefault, + userSettings: Object.assign({}, userSettingsDefault), + + hiddenSettingsDefault, + hiddenSettingsAdmin: {}, + hiddenSettings: Object.assign({}, hiddenSettingsDefault), + + dynamicFilteringDefault, + hostnameSwitchesDefault, + + noDashboard: false, + + // Features detection. + privacySettingsSupported: vAPI.browserSettings instanceof Object, + cloudStorageSupported: vAPI.cloud instanceof Object, + canFilterResponseData: typeof browser.webRequest.filterResponseData === 'function', + + // https://github.com/chrisaljoudi/uBlock/issues/180 + // Whitelist directives need to be loaded once the PSL is available + netWhitelist: new Map(), + netWhitelistModifyTime: 0, + netWhitelistDefault: [ + 'about-scheme', + 'chrome-extension-scheme', + 'chrome-scheme', + 'edge-scheme', + 'moz-extension-scheme', + 'opera-scheme', + 'vivaldi-scheme', + 'wyciwyg-scheme', // Firefox's "What-You-Cache-Is-What-You-Get" + ], + + localSettings: { + blockedRequestCount: 0, + allowedRequestCount: 0, + }, + localSettingsLastModified: 0, + + // Read-only + systemSettings: { + compiledMagic: 57, // Increase when compiled format changes + selfieMagic: 57, // Increase when selfie format changes + }, + + // https://github.com/uBlockOrigin/uBlock-issues/issues/759#issuecomment-546654501 + // The assumption is that cache storage state reflects whether + // compiled or selfie assets are available or not. The properties + // below is to no longer rely on this assumption -- though it's still + // not clear how the assumption could be wrong, and it's still not + // clear whether relying on those properties will really solve the + // issue. It's just an attempt at hardening. + compiledFormatChanged: false, + selfieIsInvalid: false, + + restoreBackupSettings: { + lastRestoreFile: '', + lastRestoreTime: 0, + lastBackupFile: '', + lastBackupTime: 0, + }, + + commandShortcuts: new Map(), + + // Allows to fully customize uBO's assets, typically set through admin + // settings. The content of 'assets.json' will also tell which filter + // lists to enable by default when uBO is first installed. + assetsBootstrapLocation: undefined, + + assetsJsonPath: vAPI.webextFlavor.soup.has('devbuild') + ? '/assets/assets.dev.json' + : '/assets/assets.json', + userFiltersPath: 'user-filters', + pslAssetKey: 'public_suffix_list.dat', + + selectedFilterLists: [], + availableFilterLists: {}, + badLists: new Map(), + + inMemoryFilters: [], + inMemoryFiltersCompiled: '', + + // https://github.com/uBlockOrigin/uBlock-issues/issues/974 + // This can be used to defer filtering decision-making. + readyToFilter: false, + + supportStats: { + allReadyAfter: '?', + maxAssetCacheWait: '?', + }, + + pageStores: new Map(), + pageStoresToken: 0, + + storageQuota: vAPI.storage.QUOTA_BYTES, + storageUsed: 0, + + noopFunc: function(){}, + + apiErrorCount: 0, + + maybeGoodPopup: { + tabId: 0, + url: '', + }, + + epickerArgs: { + eprom: null, + mouse: false, + target: '', + zap: false, + }, + + scriptlets: {}, + + cspNoInlineScript: "script-src 'unsafe-eval' * blob: data:", + cspNoScripting: 'script-src http: https:', + cspNoInlineFont: 'font-src *', + + liveBlockingProfiles: [], + blockingProfileColorCache: new Map(), + parsedTrustedListPrefixes: [], + uiAccentStylesheet: '', +}; + +µBlock.isReadyPromise = new Promise(resolve => { + µBlock.isReadyResolve = resolve; +}); + +µBlock.domainFromHostname = domainFromHostname; +µBlock.hostnameFromURI = hostnameFromURI; + +µBlock.FilteringContext = class extends FilteringContext { + duplicate() { + return (new µBlock.FilteringContext(this)); + } + + fromTabId(tabId) { + const tabContext = µBlock.tabContextManager.mustLookup(tabId); + this.tabOrigin = tabContext.origin; + this.tabHostname = tabContext.rootHostname; + this.tabDomain = tabContext.rootDomain; + this.tabId = tabContext.tabId; + return this; + } + + maybeFromDocumentURL(documentUrl) { + if ( documentUrl === undefined ) { return; } + if ( documentUrl.startsWith(this.tabOrigin) ) { return; } + this.tabOrigin = originFromURI(µBlock.normalizeTabURL(0, documentUrl)); + this.tabHostname = hostnameFromURI(this.tabOrigin); + this.tabDomain = domainFromHostname(this.tabHostname); + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/459 + // In case of a request for frame and if ever no context is specified, + // assume the origin of the context is the same as the request itself. + fromWebrequestDetails(details) { + const tabId = details.tabId; + this.type = details.type; + const isMainFrame = this.itype === this.MAIN_FRAME; + if ( isMainFrame && tabId > 0 ) { + µBlock.tabContextManager.push(tabId, details.url); + } + this.fromTabId(tabId); // Must be called AFTER tab context management + this.realm = ''; + this.id = details.requestId; + this.setMethod(details.method); + this.setURL(details.url); + this.aliasURL = details.aliasURL || undefined; + this.redirectURL = undefined; + this.filter = undefined; + if ( this.itype !== this.SUB_FRAME ) { + this.docId = details.frameId; + this.frameId = -1; + } else { + this.docId = details.parentFrameId; + this.frameId = details.frameId; + } + if ( this.tabId > 0 ) { + if ( this.docId === 0 ) { + if ( isMainFrame === false ) { + this.maybeFromDocumentURL(details.documentUrl); + } + this.docOrigin = this.tabOrigin; + this.docHostname = this.tabHostname; + this.docDomain = this.tabDomain; + return this; + } + if ( details.documentUrl !== undefined ) { + this.setDocOriginFromURL(details.documentUrl); + return this; + } + const pageStore = µBlock.pageStoreFromTabId(this.tabId); + const docStore = pageStore && pageStore.getFrameStore(this.docId); + if ( docStore ) { + this.setDocOriginFromURL(docStore.rawURL); + } else { + this.setDocOrigin(this.tabOrigin); + } + return this; + } + if ( details.documentUrl !== undefined ) { + const origin = originFromURI( + µBlock.normalizeTabURL(0, details.documentUrl) + ); + this.setDocOrigin(origin).setTabOrigin(origin); + return this; + } + const origin = (this.itype & this.FRAME_ANY) !== 0 + ? originFromURI(this.url) + : this.tabOrigin; + this.setDocOrigin(origin).setTabOrigin(origin); + return this; + } + + getTabOrigin() { + if ( this.tabOrigin === undefined ) { + const tabContext = µBlock.tabContextManager.mustLookup(this.tabId); + this.tabOrigin = tabContext.origin; + this.tabHostname = tabContext.rootHostname; + this.tabDomain = tabContext.rootDomain; + } + return super.getTabOrigin(); + } + + toLogger() { + const details = { + id: this.id, + tstamp: Date.now(), + realm: this.realm, + method: this.getMethodName(), + type: this.stype, + tabId: this.tabId, + tabDomain: this.getTabDomain(), + tabHostname: this.getTabHostname(), + docDomain: this.getDocDomain(), + docHostname: this.getDocHostname(), + domain: this.getDomain(), + hostname: this.getHostname(), + url: this.url, + aliasURL: this.aliasURL, + filter: undefined, + }; + // Many filters may have been applied to the current context + if ( Array.isArray(this.filter) === false ) { + details.filter = this.filter; + return logger.writeOne(details); + } + for ( const filter of this.filter ) { + details.filter = filter; + logger.writeOne(details); + } + } +}; + +µBlock.filteringContext = new µBlock.FilteringContext(); + +self.µBlock = µBlock; + +/******************************************************************************/ + +export default µBlock; diff --git a/src/js/base64-custom.js b/src/js/base64-custom.js new file mode 100644 index 0000000..34141b8 --- /dev/null +++ b/src/js/base64-custom.js @@ -0,0 +1,246 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +// Custom base64 codecs. These codecs are meant to encode/decode typed arrays +// to/from strings. + +// https://github.com/uBlockOrigin/uBlock-issues/issues/461 +// Provide a fallback encoding for Chromium 59 and less by issuing a plain +// JSON string. The fallback can be removed once min supported version is +// above 59. + +// TODO: rename µBlock.base64 to µBlock.SparseBase64, now that +// µBlock.DenseBase64 has been introduced. +// TODO: Should no longer need to test presence of TextEncoder/TextDecoder. + +const valToDigit = new Uint8Array(64); +const digitToVal = new Uint8Array(128); +{ + const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@%'; + for ( let i = 0, n = chars.length; i < n; i++ ) { + const c = chars.charCodeAt(i); + valToDigit[i] = c; + digitToVal[c] = i; + } +} + +// The sparse base64 codec is best for buffers which contains a lot of +// small u32 integer values. Those small u32 integer values are better +// represented with stringified integers, because small values can be +// represented with fewer bits than the usual base64 codec. For example, +// 0 become '0 ', i.e. 16 bits instead of 48 bits with official base64 +// codec. + +const sparseBase64 = { + magic: 'Base64_1', + + encode: function(arrbuf, arrlen) { + const inputLength = (arrlen + 3) >>> 2; + const inbuf = new Uint32Array(arrbuf, 0, inputLength); + const outputLength = this.magic.length + 7 + inputLength * 7; + const outbuf = new Uint8Array(outputLength); + // magic bytes + let j = 0; + for ( let i = 0; i < this.magic.length; i++ ) { + outbuf[j++] = this.magic.charCodeAt(i); + } + // array size + let v = inputLength; + do { + outbuf[j++] = valToDigit[v & 0b111111]; + v >>>= 6; + } while ( v !== 0 ); + outbuf[j++] = 0x20 /* ' ' */; + // array content + for ( let i = 0; i < inputLength; i++ ) { + v = inbuf[i]; + do { + outbuf[j++] = valToDigit[v & 0b111111]; + v >>>= 6; + } while ( v !== 0 ); + outbuf[j++] = 0x20 /* ' ' */; + } + if ( typeof TextDecoder === 'undefined' ) { + return JSON.stringify( + Array.from(new Uint32Array(outbuf.buffer, 0, j >>> 2)) + ); + } + const textDecoder = new TextDecoder(); + return textDecoder.decode(new Uint8Array(outbuf.buffer, 0, j)); + }, + + decode: function(instr, arrbuf) { + if ( instr.charCodeAt(0) === 0x5B /* '[' */ ) { + const inbuf = JSON.parse(instr); + if ( arrbuf instanceof ArrayBuffer === false ) { + return new Uint32Array(inbuf); + } + const outbuf = new Uint32Array(arrbuf); + outbuf.set(inbuf); + return outbuf; + } + if ( instr.startsWith(this.magic) === false ) { + throw new Error('Invalid µBlock.base64 encoding'); + } + const inputLength = instr.length; + const outputLength = this.decodeSize(instr) >> 2; + const outbuf = arrbuf instanceof ArrayBuffer === false + ? new Uint32Array(outputLength) + : new Uint32Array(arrbuf); + let i = instr.indexOf(' ', this.magic.length) + 1; + if ( i === -1 ) { + throw new Error('Invalid µBlock.base64 encoding'); + } + // array content + let j = 0; + for (;;) { + if ( j === outputLength || i >= inputLength ) { break; } + let v = 0, l = 0; + for (;;) { + const c = instr.charCodeAt(i++); + if ( c === 0x20 /* ' ' */ ) { break; } + v += digitToVal[c] << l; + l += 6; + } + outbuf[j++] = v; + } + if ( i < inputLength || j < outputLength ) { + throw new Error('Invalid µBlock.base64 encoding'); + } + return outbuf; + }, + + decodeSize: function(instr) { + if ( instr.startsWith(this.magic) === false ) { return 0; } + let v = 0, l = 0, i = this.magic.length; + for (;;) { + const c = instr.charCodeAt(i++); + if ( c === 0x20 /* ' ' */ ) { break; } + v += digitToVal[c] << l; + l += 6; + } + return v << 2; + }, +}; + +// The dense base64 codec is best for typed buffers which values are +// more random. For example, buffer contents as a result of compression +// contain less repetitive values and thus the content is more +// random-looking. + +// TODO: Investigate that in Firefox, creating a new Uint8Array from the +// ArrayBuffer fails, the content of the resulting Uint8Array is +// non-sensical. WASM-related? + +const denseBase64 = { + magic: 'DenseBase64_1', + + encode: function(input) { + const m = input.length % 3; + const n = input.length - m; + let outputLength = n / 3 * 4; + if ( m !== 0 ) { + outputLength += m + 1; + } + const output = new Uint8Array(outputLength); + let j = 0; + for ( let i = 0; i < n; i += 3) { + const i1 = input[i+0]; + const i2 = input[i+1]; + const i3 = input[i+2]; + output[j+0] = valToDigit[ i1 >>> 2]; + output[j+1] = valToDigit[i1 << 4 & 0b110000 | i2 >>> 4]; + output[j+2] = valToDigit[i2 << 2 & 0b111100 | i3 >>> 6]; + output[j+3] = valToDigit[i3 & 0b111111 ]; + j += 4; + } + if ( m !== 0 ) { + const i1 = input[n]; + output[j+0] = valToDigit[i1 >>> 2]; + if ( m === 1 ) { // 1 value + output[j+1] = valToDigit[i1 << 4 & 0b110000]; + } else { // 2 values + const i2 = input[n+1]; + output[j+1] = valToDigit[i1 << 4 & 0b110000 | i2 >>> 4]; + output[j+2] = valToDigit[i2 << 2 & 0b111100 ]; + } + } + const textDecoder = new TextDecoder(); + const b64str = textDecoder.decode(output); + return this.magic + b64str; + }, + + decode: function(instr, arrbuf) { + if ( instr.startsWith(this.magic) === false ) { + throw new Error('Invalid µBlock.denseBase64 encoding'); + } + const outputLength = this.decodeSize(instr); + const outbuf = arrbuf instanceof ArrayBuffer === false + ? new Uint8Array(outputLength) + : new Uint8Array(arrbuf); + const inputLength = instr.length - this.magic.length; + let i = this.magic.length; + let j = 0; + const m = inputLength & 3; + const n = i + inputLength - m; + while ( i < n ) { + const i1 = digitToVal[instr.charCodeAt(i+0)]; + const i2 = digitToVal[instr.charCodeAt(i+1)]; + const i3 = digitToVal[instr.charCodeAt(i+2)]; + const i4 = digitToVal[instr.charCodeAt(i+3)]; + i += 4; + outbuf[j+0] = i1 << 2 | i2 >>> 4; + outbuf[j+1] = i2 << 4 & 0b11110000 | i3 >>> 2; + outbuf[j+2] = i3 << 6 & 0b11000000 | i4; + j += 3; + } + if ( m !== 0 ) { + const i1 = digitToVal[instr.charCodeAt(i+0)]; + const i2 = digitToVal[instr.charCodeAt(i+1)]; + outbuf[j+0] = i1 << 2 | i2 >>> 4; + if ( m === 3 ) { + const i3 = digitToVal[instr.charCodeAt(i+2)]; + outbuf[j+1] = i2 << 4 & 0b11110000 | i3 >>> 2; + } + } + return outbuf; + }, + + decodeSize: function(instr) { + if ( instr.startsWith(this.magic) === false ) { return 0; } + const inputLength = instr.length - this.magic.length; + const m = inputLength & 3; + const n = inputLength - m; + let outputLength = (n >>> 2) * 3; + if ( m !== 0 ) { + outputLength += m - 1; + } + return outputLength; + }, +}; + +/******************************************************************************/ + +export { denseBase64, sparseBase64 }; diff --git a/src/js/benchmarks.js b/src/js/benchmarks.js new file mode 100644 index 0000000..8792f03 --- /dev/null +++ b/src/js/benchmarks.js @@ -0,0 +1,421 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import cosmeticFilteringEngine from './cosmetic-filtering.js'; +import io from './assets.js'; +import scriptletFilteringEngine from './scriptlet-filtering.js'; +import staticNetFilteringEngine from './static-net-filtering.js'; +import µb from './background.js'; +import webRequest from './traffic.js'; +import { FilteringContext } from './filtering-context.js'; +import { LineIterator } from './text-utils.js'; +import { sessionFirewall } from './filtering-engines.js'; + +import { + domainFromHostname, + entityFromDomain, + hostnameFromURI, +} from './uri-utils.js'; + +/******************************************************************************/ + +// The requests.json.gz file can be downloaded from: +// https://cdn.cliqz.com/adblocking/requests_top500.json.gz +// +// Which is linked from: +// https://whotracks.me/blog/adblockers_performance_study.html +// +// Copy the file into ./tmp/requests.json.gz +// +// If the file is present when you build uBO using `make-[target].sh` from +// the shell, the resulting package will have `./assets/requests.json`, which +// will be looked-up by the method below to launch a benchmark session. +// +// From uBO's dev console, launch the benchmark: +// µBlock.staticNetFilteringEngine.benchmark(); +// +// The usual browser dev tools can be used to obtain useful profiling +// data, i.e. start the profiler, call the benchmark method from the +// console, then stop the profiler when it completes. +// +// Keep in mind that the measurements at the blog post above where obtained +// with ONLY EasyList. The CPU reportedly used was: +// https://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i7-6600U+%40+2.60GHz&id=2608 +// +// Rename ./tmp/requests.json.gz to something else if you no longer want +// ./assets/requests.json in the build. + +const loadBenchmarkDataset = (( ) => { + let datasetPromise; + + const ttlTimer = vAPI.defer.create(( ) => { + datasetPromise = undefined; + }); + + return function() { + ttlTimer.offon({ min: 5 }); + + if ( datasetPromise !== undefined ) { + return datasetPromise; + } + + const datasetURL = µb.hiddenSettings.benchmarkDatasetURL; + if ( datasetURL === 'unset' ) { + console.info(`No benchmark dataset available.`); + return Promise.resolve(); + } + console.info(`Loading benchmark dataset...`); + datasetPromise = io.fetchText(datasetURL).then(details => { + console.info(`Parsing benchmark dataset...`); + let requests = []; + if ( details.content.startsWith('[') ) { + try { + requests = JSON.parse(details.content); + } catch(ex) { + } + } else { + const lineIter = new LineIterator(details.content); + const parsed = []; + while ( lineIter.eot() === false ) { + const line = lineIter.next().trim(); + if ( line === '' ) { continue; } + try { + parsed.push(JSON.parse(line)); + } catch(ex) { + parsed.length = 0; + break; + } + } + requests = parsed; + } + if ( requests.length === 0 ) { return; } + const out = []; + for ( const request of requests ) { + if ( request instanceof Object === false ) { continue; } + if ( !request.frameUrl || !request.url ) { continue; } + if ( request.cpt === 'document' ) { + request.cpt = 'main_frame'; + } else if ( request.cpt === 'xhr' ) { + request.cpt = 'xmlhttprequest'; + } + out.push(request); + } + return out; + }).catch(details => { + console.info(`Not found: ${details.url}`); + datasetPromise = undefined; + }); + + return datasetPromise; + }; +})(); + +/******************************************************************************/ + +// action: 1=test + +µb.benchmarkStaticNetFiltering = async function(options = {}) { + const { target, redirectEngine } = options; + + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + const text = 'No dataset found to benchmark'; + console.info(text); + return text; + } + + console.info(`Benchmarking staticNetFilteringEngine.matchRequest()...`); + + const fctxt = new FilteringContext(); + + if ( typeof target === 'number' ) { + const request = requests[target]; + fctxt.setURL(request.url); + fctxt.setDocOriginFromURL(request.frameUrl); + fctxt.setType(request.cpt); + const r = staticNetFilteringEngine.matchRequest(fctxt); + console.info(`Result=${r}:`); + console.info(`\ttype=${fctxt.type}`); + console.info(`\turl=${fctxt.url}`); + console.info(`\tdocOrigin=${fctxt.getDocOrigin()}`); + if ( r !== 0 ) { + console.info(staticNetFilteringEngine.toLogData()); + } + return; + } + + const t0 = performance.now(); + let matchCount = 0; + let blockCount = 0; + let allowCount = 0; + let redirectCount = 0; + let removeparamCount = 0; + let cspCount = 0; + let permissionsCount = 0; + let replaceCount = 0; + for ( let i = 0; i < requests.length; i++ ) { + const request = requests[i]; + fctxt.setURL(request.url); + fctxt.setDocOriginFromURL(request.frameUrl); + fctxt.setType(request.cpt); + staticNetFilteringEngine.redirectURL = undefined; + const r = staticNetFilteringEngine.matchRequest(fctxt); + matchCount += 1; + if ( r === 1 ) { blockCount += 1; } + else if ( r === 2 ) { allowCount += 1; } + if ( r !== 1 ) { + if ( staticNetFilteringEngine.transformRequest(fctxt) ) { + redirectCount += 1; + } + if ( fctxt.redirectURL !== undefined && staticNetFilteringEngine.hasQuery(fctxt) ) { + if ( staticNetFilteringEngine.filterQuery(fctxt, 'removeparam') ) { + removeparamCount += 1; + } + } + if ( fctxt.type === 'main_frame' || fctxt.type === 'sub_frame' ) { + if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp') ) { + cspCount += 1; + } + if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'permissions') ) { + permissionsCount += 1; + } + } + staticNetFilteringEngine.matchHeaders(fctxt, []); + if ( staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'replace') ) { + replaceCount += 1; + } + } else if ( redirectEngine !== undefined ) { + if ( staticNetFilteringEngine.redirectRequest(redirectEngine, fctxt) ) { + redirectCount += 1; + } + } + } + const t1 = performance.now(); + const dur = t1 - t0; + + const output = [ + 'Benchmarked static network filtering engine:', + `\tEvaluated ${matchCount} match calls in ${dur.toFixed(0)} ms`, + `\tAverage: ${(dur / matchCount).toFixed(3)} ms per request`, + `\tNot blocked: ${matchCount - blockCount - allowCount}`, + `\tBlocked: ${blockCount}`, + `\tUnblocked: ${allowCount}`, + `\tredirect=: ${redirectCount}`, + `\tremoveparam=: ${removeparamCount}`, + `\tcsp=: ${cspCount}`, + `\tpermissions=: ${permissionsCount}`, + `\treplace=: ${replaceCount}`, + ]; + const s = output.join('\n'); + console.info(s); + return s; +}; + +/******************************************************************************/ + +µb.tokenHistograms = async function() { + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + + console.info(`Computing token histograms...`); + + const fctxt = new FilteringContext(); + const missTokenMap = new Map(); + const hitTokenMap = new Map(); + const reTokens = /[0-9a-z%]{2,}/g; + + for ( let i = 0; i < requests.length; i++ ) { + const request = requests[i]; + fctxt.setURL(request.url); + fctxt.setDocOriginFromURL(request.frameUrl); + fctxt.setType(request.cpt); + const r = staticNetFilteringEngine.matchRequest(fctxt); + for ( let [ keyword ] of request.url.toLowerCase().matchAll(reTokens) ) { + const token = keyword.slice(0, 7); + if ( r === 0 ) { + missTokenMap.set(token, (missTokenMap.get(token) || 0) + 1); + } else if ( r === 1 ) { + hitTokenMap.set(token, (hitTokenMap.get(token) || 0) + 1); + } + } + } + const customSort = (a, b) => b[1] - a[1]; + const topmisses = Array.from(missTokenMap).sort(customSort).slice(0, 100); + for ( const [ token ] of topmisses ) { + hitTokenMap.delete(token); + } + const tophits = Array.from(hitTokenMap).sort(customSort).slice(0, 100); + console.info('Misses:', JSON.stringify(topmisses)); + console.info('Hits:', JSON.stringify(tophits)); +}; + +/******************************************************************************/ + +µb.benchmarkDynamicNetFiltering = async function() { + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + console.info(`Benchmarking sessionFirewall.evaluateCellZY()...`); + const fctxt = new FilteringContext(); + const t0 = performance.now(); + for ( const request of requests ) { + fctxt.setURL(request.url); + fctxt.setTabOriginFromURL(request.frameUrl); + fctxt.setType(request.cpt); + sessionFirewall.evaluateCellZY( + fctxt.getTabHostname(), + fctxt.getHostname(), + fctxt.type + ); + } + const t1 = performance.now(); + const dur = t1 - t0; + console.info(`Evaluated ${requests.length} requests in ${dur.toFixed(0)} ms`); + console.info(`\tAverage: ${(dur / requests.length).toFixed(3)} ms per request`); +}; + +/******************************************************************************/ + +µb.benchmarkCosmeticFiltering = async function() { + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + console.info('Benchmarking cosmeticFilteringEngine.retrieveSpecificSelectors()...'); + const details = { + tabId: undefined, + frameId: undefined, + hostname: '', + domain: '', + entity: '', + }; + const options = { + noSpecificCosmeticFiltering: false, + noGenericCosmeticFiltering: false, + }; + let count = 0; + const t0 = performance.now(); + for ( let i = 0; i < requests.length; i++ ) { + const request = requests[i]; + if ( request.cpt !== 'main_frame' ) { continue; } + count += 1; + details.hostname = hostnameFromURI(request.url); + details.domain = domainFromHostname(details.hostname); + details.entity = entityFromDomain(details.domain); + void cosmeticFilteringEngine.retrieveSpecificSelectors(details, options); + } + const t1 = performance.now(); + const dur = t1 - t0; + console.info(`Evaluated ${count} requests in ${dur.toFixed(0)} ms`); + console.info(`\tAverage: ${(dur / count).toFixed(3)} ms per request`); +}; + +/******************************************************************************/ + +µb.benchmarkScriptletFiltering = async function() { + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + console.info('Benchmarking scriptletFilteringEngine.retrieve()...'); + const details = { + domain: '', + entity: '', + hostname: '', + tabId: 0, + url: '', + }; + let count = 0; + const t0 = performance.now(); + for ( let i = 0; i < requests.length; i++ ) { + const request = requests[i]; + if ( request.cpt !== 'main_frame' ) { continue; } + count += 1; + details.url = request.url; + details.hostname = hostnameFromURI(request.url); + details.domain = domainFromHostname(details.hostname); + details.entity = entityFromDomain(details.domain); + void scriptletFilteringEngine.retrieve(details); + } + const t1 = performance.now(); + const dur = t1 - t0; + console.info(`Evaluated ${count} requests in ${dur.toFixed(0)} ms`); + console.info(`\tAverage: ${(dur / count).toFixed(3)} ms per request`); +}; + +/******************************************************************************/ + +µb.benchmarkOnBeforeRequest = async function() { + const requests = await loadBenchmarkDataset(); + if ( Array.isArray(requests) === false || requests.length === 0 ) { + console.info('No requests found to benchmark'); + return; + } + const mappedTypes = new Map([ + [ 'document', 'main_frame' ], + [ 'subdocument', 'sub_frame' ], + ]); + console.info('webRequest.onBeforeRequest()...'); + const t0 = self.performance.now(); + const promises = []; + const details = { + documentUrl: '', + tabId: -1, + parentFrameId: -1, + frameId: 0, + type: '', + url: '', + }; + for ( const request of requests ) { + details.documentUrl = request.frameUrl; + details.tabId = -1; + details.parentFrameId = -1; + details.frameId = 0; + details.type = mappedTypes.get(request.cpt) || request.cpt; + details.url = request.url; + if ( details.type === 'main_frame' ) { continue; } + promises.push(webRequest.onBeforeRequest(details)); + } + return Promise.all(promises).then(results => { + let blockCount = 0; + for ( const r of results ) { + if ( r !== undefined ) { blockCount += 1; } + } + const t1 = self.performance.now(); + const dur = t1 - t0; + console.info(`Evaluated ${requests.length} requests in ${dur.toFixed(0)} ms`); + console.info(`\tBlocked ${blockCount} requests`); + console.info(`\tAverage: ${(dur / requests.length).toFixed(3)} ms per request`); + }); +}; + +/******************************************************************************/ diff --git a/src/js/biditrie.js b/src/js/biditrie.js new file mode 100644 index 0000000..d0f64ee --- /dev/null +++ b/src/js/biditrie.js @@ -0,0 +1,947 @@ +/******************************************************************************* + + 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 +*/ + +/* globals WebAssembly, vAPI */ + +'use strict'; + +/******************************************************************************* + + A BidiTrieContainer is mostly a large buffer in which distinct but related + tries are stored. The memory layout of the buffer is as follow: + + 0-2047: haystack section + 2048-2051: number of significant characters in the haystack + 2052-2055: offset to start of trie data section (=> trie0) + 2056-2059: offset to end of trie data section (=> trie1) + 2060-2063: offset to start of character data section (=> char0) + 2064-2067: offset to end of character data section (=> char1) + 2068: start of trie data section + + +--------------+ + Normal cell: | And | If "Segment info" matches: + (aka CELL) +--------------+ Goto "And" + | Or | Else + +--------------+ Goto "Or" + | Segment info | + +--------------+ + + +--------------+ + Boundary cell: | Right And | "Right And" and/or "Left And" + (aka BCELL) +--------------+ can be 0 in last-segment condition. + | Left And | + +--------------+ + | 0 | + +--------------+ + + Given following filters and assuming token is "ad" for all of them: + + -images/ad- + /google_ad. + /images_ad. + _images/ad. + + We get the following internal representation: + + +-----------+ +-----------+ +---+ + | |---->| |---->| 0 | + +-----------+ +-----------+ +---+ +-----------+ + | 0 | +--| | | |---->| 0 | + +-----------+ | +-----------+ +---+ +-----------+ + | ad | | | - | | 0 | | 0 | + +-----------+ | +-----------+ +---+ +-----------+ + | | -images/ | + | +-----------+ +---+ +-----------+ + +->| |---->| 0 | + +-----------+ +---+ +-----------+ +-----------+ + | 0 | | |---->| |---->| 0 | + +-----------+ +---+ +-----------+ +-----------+ + | . | | 0 | +--| | +--| | + +-----------+ +---+ | +-----------+ | +-----------+ + | | _ | | | /google | + | +-----------+ | +-----------+ + | | + | | +-----------+ + | +->| 0 | + | +-----------+ + | | 0 | + | +-----------+ + | | /images | + | +-----------+ + | + | +-----------+ + +->| 0 | + +-----------+ + | 0 | + +-----------+ + | _images/ | + +-----------+ + +*/ + +const PAGE_SIZE = 65536*2; +const HAYSTACK_START = 0; +const HAYSTACK_SIZE = 2048; // i32 / i8 +const HAYSTACK_SIZE_SLOT = HAYSTACK_SIZE >>> 2; // 512 / 2048 +const TRIE0_SLOT = HAYSTACK_SIZE_SLOT + 1; // 513 / 2052 +const TRIE1_SLOT = HAYSTACK_SIZE_SLOT + 2; // 514 / 2056 +const CHAR0_SLOT = HAYSTACK_SIZE_SLOT + 3; // 515 / 2060 +const CHAR1_SLOT = HAYSTACK_SIZE_SLOT + 4; // 516 / 2064 +const RESULT_L_SLOT = HAYSTACK_SIZE_SLOT + 5; // 517 / 2068 +const RESULT_R_SLOT = HAYSTACK_SIZE_SLOT + 6; // 518 / 2072 +const RESULT_IU_SLOT = HAYSTACK_SIZE_SLOT + 7; // 519 / 2076 +const TRIE0_START = HAYSTACK_SIZE_SLOT + 8 << 2; // 2080 + +const CELL_BYTE_LENGTH = 12; +const MIN_FREE_CELL_BYTE_LENGTH = CELL_BYTE_LENGTH * 8; + +const CELL_AND = 0; +const CELL_OR = 1; +const SEGMENT_INFO = 2; +const BCELL_NEXT_AND = 0; +const BCELL_ALT_AND = 1; +const BCELL_EXTRA = 2; +const BCELL_EXTRA_MAX = 0x00FFFFFF; + +const toSegmentInfo = (aL, l, r) => ((r - l) << 24) | (aL + l); +const roundToPageSize = v => (v + PAGE_SIZE-1) & ~(PAGE_SIZE-1); + + +class BidiTrieContainer { + + constructor(extraHandler) { + const len = PAGE_SIZE * 4; + this.buf8 = new Uint8Array(len); + this.buf32 = new Uint32Array(this.buf8.buffer); + this.buf32[TRIE0_SLOT] = TRIE0_START; + this.buf32[TRIE1_SLOT] = this.buf32[TRIE0_SLOT]; + this.buf32[CHAR0_SLOT] = len >>> 1; + this.buf32[CHAR1_SLOT] = this.buf32[CHAR0_SLOT]; + this.haystack = this.buf8.subarray( + HAYSTACK_START, + HAYSTACK_START + HAYSTACK_SIZE + ); + this.extraHandler = extraHandler; + this.textDecoder = null; + this.wasmMemory = null; + + this.lastStored = ''; + this.lastStoredLen = this.lastStoredIndex = 0; + } + + //-------------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------------- + + get haystackLen() { + return this.buf32[HAYSTACK_SIZE_SLOT]; + } + + set haystackLen(v) { + this.buf32[HAYSTACK_SIZE_SLOT] = v; + } + + reset(details) { + if ( + details instanceof Object && + typeof details.byteLength === 'number' && + typeof details.char0 === 'number' + ) { + if ( details.byteLength > this.buf8.byteLength ) { + this.reallocateBuf(details.byteLength); + } + this.buf32[CHAR0_SLOT] = details.char0; + } + this.buf32[TRIE1_SLOT] = this.buf32[TRIE0_SLOT]; + this.buf32[CHAR1_SLOT] = this.buf32[CHAR0_SLOT]; + + this.lastStored = ''; + this.lastStoredLen = this.lastStoredIndex = 0; + } + + createTrie() { + // grow buffer if needed + if ( (this.buf32[CHAR0_SLOT] - this.buf32[TRIE1_SLOT]) < CELL_BYTE_LENGTH ) { + this.growBuf(CELL_BYTE_LENGTH, 0); + } + const iroot = this.buf32[TRIE1_SLOT] >>> 2; + this.buf32[TRIE1_SLOT] += CELL_BYTE_LENGTH; + this.buf32[iroot+CELL_OR] = 0; + this.buf32[iroot+CELL_AND] = 0; + this.buf32[iroot+SEGMENT_INFO] = 0; + return iroot; + } + + matches(icell, ai) { + const buf32 = this.buf32; + const buf8 = this.buf8; + const char0 = buf32[CHAR0_SLOT]; + const aR = buf32[HAYSTACK_SIZE_SLOT]; + let al = ai, x = 0, y = 0; + for (;;) { + x = buf8[al]; + al += 1; + // find matching segment + for (;;) { + y = buf32[icell+SEGMENT_INFO]; + let bl = char0 + (y & 0x00FFFFFF); + if ( buf8[bl] === x ) { + y = (y >>> 24) - 1; + if ( y !== 0 ) { + x = al + y; + if ( x > aR ) { return 0; } + for (;;) { + bl += 1; + if ( buf8[bl] !== buf8[al] ) { return 0; } + al += 1; + if ( al === x ) { break; } + } + } + break; + } + icell = buf32[icell+CELL_OR]; + if ( icell === 0 ) { return 0; } + } + // next segment + icell = buf32[icell+CELL_AND]; + x = buf32[icell+BCELL_EXTRA]; + if ( x <= BCELL_EXTRA_MAX ) { + if ( x !== 0 && this.matchesExtra(ai, al, x) !== 0 ) { + return 1; + } + x = buf32[icell+BCELL_ALT_AND]; + if ( x !== 0 && this.matchesLeft(x, ai, al) !== 0 ) { + return 1; + } + icell = buf32[icell+BCELL_NEXT_AND]; + if ( icell === 0 ) { return 0; } + } + if ( al === aR ) { return 0; } + } + return 0; // eslint-disable-line no-unreachable + } + + matchesLeft(icell, ar, r) { + const buf32 = this.buf32; + const buf8 = this.buf8; + const char0 = buf32[CHAR0_SLOT]; + let x = 0, y = 0; + for (;;) { + if ( ar === 0 ) { return 0; } + ar -= 1; + x = buf8[ar]; + // find first segment with a first-character match + for (;;) { + y = buf32[icell+SEGMENT_INFO]; + let br = char0 + (y & 0x00FFFFFF); + y = (y >>> 24) - 1; + br += y; + if ( buf8[br] === x ) { // all characters in segment must match + if ( y !== 0 ) { + x = ar - y; + if ( x < 0 ) { return 0; } + for (;;) { + ar -= 1; br -= 1; + if ( buf8[ar] !== buf8[br] ) { return 0; } + if ( ar === x ) { break; } + } + } + break; + } + icell = buf32[icell+CELL_OR]; + if ( icell === 0 ) { return 0; } + } + // next segment + icell = buf32[icell+CELL_AND]; + x = buf32[icell+BCELL_EXTRA]; + if ( x <= BCELL_EXTRA_MAX ) { + if ( x !== 0 && this.matchesExtra(ar, r, x) !== 0 ) { + return 1; + } + icell = buf32[icell+BCELL_NEXT_AND]; + if ( icell === 0 ) { return 0; } + } + } + return 0; // eslint-disable-line no-unreachable + } + + matchesExtra(l, r, ix) { + let iu = 0; + if ( ix !== 1 ) { + iu = this.extraHandler(l, r, ix); + if ( iu === 0 ) { return 0; } + } else { + iu = -1; + } + this.buf32[RESULT_IU_SLOT] = iu; + this.buf32[RESULT_L_SLOT] = l; + this.buf32[RESULT_R_SLOT] = r; + return 1; + } + + get $l() { return this.buf32[RESULT_L_SLOT] | 0; } + get $r() { return this.buf32[RESULT_R_SLOT] | 0; } + get $iu() { return this.buf32[RESULT_IU_SLOT] | 0; } + + add(iroot, aL0, n, pivot = 0) { + const aR = n; + if ( aR === 0 ) { return 0; } + // Grow buffer if needed. The characters are already in our character + // data buffer, so we do not need to grow character data buffer. + if ( + (this.buf32[CHAR0_SLOT] - this.buf32[TRIE1_SLOT]) < + MIN_FREE_CELL_BYTE_LENGTH + ) { + this.growBuf(MIN_FREE_CELL_BYTE_LENGTH, 0); + } + const buf32 = this.buf32; + const char0 = buf32[CHAR0_SLOT]; + let icell = iroot; + let aL = char0 + aL0; + // special case: first node in trie + if ( buf32[icell+SEGMENT_INFO] === 0 ) { + buf32[icell+SEGMENT_INFO] = toSegmentInfo(aL0, pivot, aR); + return this.addLeft(icell, aL0, pivot); + } + const buf8 = this.buf8; + let al = pivot; + let inext; + // find a matching cell: move down + for (;;) { + const binfo = buf32[icell+SEGMENT_INFO]; + // length of segment + const bR = binfo >>> 24; + // skip boundary cells + if ( bR === 0 ) { + icell = buf32[icell+BCELL_NEXT_AND]; + continue; + } + let bl = char0 + (binfo & 0x00FFFFFF); + // if first character is no match, move to next descendant + if ( buf8[bl] !== buf8[aL+al] ) { + inext = buf32[icell+CELL_OR]; + if ( inext === 0 ) { + inext = this.addCell(0, 0, toSegmentInfo(aL0, al, aR)); + buf32[icell+CELL_OR] = inext; + return this.addLeft(inext, aL0, pivot); + } + icell = inext; + continue; + } + // 1st character was tested + let bi = 1; + al += 1; + // find 1st mismatch in rest of segment + if ( bR !== 1 ) { + for (;;) { + if ( bi === bR ) { break; } + if ( al === aR ) { break; } + if ( buf8[bl+bi] !== buf8[aL+al] ) { break; } + bi += 1; + al += 1; + } + } + // all segment characters matched + if ( bi === bR ) { + // needle remainder: no + if ( al === aR ) { + return this.addLeft(icell, aL0, pivot); + } + // needle remainder: yes + inext = buf32[icell+CELL_AND]; + if ( buf32[inext+CELL_AND] !== 0 ) { + icell = inext; + continue; + } + // add needle remainder + icell = this.addCell(0, 0, toSegmentInfo(aL0, al, aR)); + buf32[inext+CELL_AND] = icell; + return this.addLeft(icell, aL0, pivot); + } + // some characters matched + // split current segment + bl -= char0; + buf32[icell+SEGMENT_INFO] = bi << 24 | bl; + inext = this.addCell( + buf32[icell+CELL_AND], 0, bR - bi << 24 | bl + bi + ); + buf32[icell+CELL_AND] = inext; + // needle remainder: no = need boundary cell + if ( al === aR ) { + return this.addLeft(icell, aL0, pivot); + } + // needle remainder: yes = need new cell for remaining characters + icell = this.addCell(0, 0, toSegmentInfo(aL0, al, aR)); + buf32[inext+CELL_OR] = icell; + return this.addLeft(icell, aL0, pivot); + } + } + + addLeft(icell, aL0, pivot) { + const buf32 = this.buf32; + const char0 = buf32[CHAR0_SLOT]; + let aL = aL0 + char0; + // fetch boundary cell + let iboundary = buf32[icell+CELL_AND]; + // add boundary cell if none exist + if ( + iboundary === 0 || + buf32[iboundary+SEGMENT_INFO] > BCELL_EXTRA_MAX + ) { + const inext = iboundary; + iboundary = this.allocateCell(); + buf32[icell+CELL_AND] = iboundary; + buf32[iboundary+BCELL_NEXT_AND] = inext; + if ( pivot === 0 ) { return iboundary; } + } + // shortest match with no extra conditions will always win + if ( buf32[iboundary+BCELL_EXTRA] === 1 ) { + return iboundary; + } + // bail out if no left segment + if ( pivot === 0 ) { return iboundary; } + // fetch root cell of left segment + icell = buf32[iboundary+BCELL_ALT_AND]; + if ( icell === 0 ) { + icell = this.allocateCell(); + buf32[iboundary+BCELL_ALT_AND] = icell; + } + // special case: first node in trie + if ( buf32[icell+SEGMENT_INFO] === 0 ) { + buf32[icell+SEGMENT_INFO] = toSegmentInfo(aL0, 0, pivot); + iboundary = this.allocateCell(); + buf32[icell+CELL_AND] = iboundary; + return iboundary; + } + const buf8 = this.buf8; + let ar = pivot, inext; + // find a matching cell: move down + for (;;) { + const binfo = buf32[icell+SEGMENT_INFO]; + // skip boundary cells + if ( binfo <= BCELL_EXTRA_MAX ) { + inext = buf32[icell+CELL_AND]; + if ( inext !== 0 ) { + icell = inext; + continue; + } + iboundary = this.allocateCell(); + buf32[icell+CELL_AND] = + this.addCell(iboundary, 0, toSegmentInfo(aL0, 0, ar)); + // TODO: boundary cell might be last + // add remainder + boundary cell + return iboundary; + } + const bL = char0 + (binfo & 0x00FFFFFF); + const bR = bL + (binfo >>> 24); + let br = bR; + // if first character is no match, move to next descendant + if ( buf8[br-1] !== buf8[aL+ar-1] ) { + inext = buf32[icell+CELL_OR]; + if ( inext === 0 ) { + iboundary = this.allocateCell(); + inext = this.addCell( + iboundary, 0, toSegmentInfo(aL0, 0, ar) + ); + buf32[icell+CELL_OR] = inext; + return iboundary; + } + icell = inext; + continue; + } + // 1st character was tested + br -= 1; + ar -= 1; + // find 1st mismatch in rest of segment + if ( br !== bL ) { + for (;;) { + if ( br === bL ) { break; } + if ( ar === 0 ) { break; } + if ( buf8[br-1] !== buf8[aL+ar-1] ) { break; } + br -= 1; + ar -= 1; + } + } + // all segment characters matched + // a: ...vvvvvvv + // b: vvvvvvv + if ( br === bL ) { + inext = buf32[icell+CELL_AND]; + // needle remainder: no + // a: vvvvvvv + // b: vvvvvvv + // r: 0 & vvvvvvv + if ( ar === 0 ) { + // boundary cell already present + if ( buf32[inext+BCELL_EXTRA] <= BCELL_EXTRA_MAX ) { + return inext; + } + // need boundary cell + iboundary = this.allocateCell(); + buf32[iboundary+CELL_AND] = inext; + buf32[icell+CELL_AND] = iboundary; + return iboundary; + } + // needle remainder: yes + // a: yyyyyyyvvvvvvv + // b: vvvvvvv + else { + if ( inext !== 0 ) { + icell = inext; + continue; + } + // TODO: we should never reach here because there will + // always be a boundary cell. + // eslint-disable-next-line no-debugger + debugger; // jshint ignore:line + // boundary cell + needle remainder + inext = this.addCell(0, 0, 0); + buf32[icell+CELL_AND] = inext; + buf32[inext+CELL_AND] = + this.addCell(0, 0, toSegmentInfo(aL0, 0, ar)); + } + } + // some segment characters matched + // a: ...vvvvvvv + // b: yyyyyyyvvvvvvv + else { + // split current cell + buf32[icell+SEGMENT_INFO] = (bR - br) << 24 | (br - char0); + inext = this.addCell( + buf32[icell+CELL_AND], + 0, + (br - bL) << 24 | (bL - char0) + ); + // needle remainder: no = need boundary cell + // a: vvvvvvv + // b: yyyyyyyvvvvvvv + // r: yyyyyyy & 0 & vvvvvvv + if ( ar === 0 ) { + iboundary = this.allocateCell(); + buf32[icell+CELL_AND] = iboundary; + buf32[iboundary+CELL_AND] = inext; + return iboundary; + } + // needle remainder: yes = need new cell for remaining + // characters + // a: wwwwvvvvvvv + // b: yyyyyyyvvvvvvv + // r: (0 & wwww | yyyyyyy) & vvvvvvv + else { + buf32[icell+CELL_AND] = inext; + iboundary = this.allocateCell(); + buf32[inext+CELL_OR] = this.addCell( + iboundary, 0, toSegmentInfo(aL0, 0, ar) + ); + return iboundary; + } + } + //debugger; // jshint ignore:line + } + } + + getExtra(iboundary) { + return this.buf32[iboundary+BCELL_EXTRA]; + } + + setExtra(iboundary, v) { + this.buf32[iboundary+BCELL_EXTRA] = v; + } + + optimize(shrink = false) { + if ( shrink ) { + this.shrinkBuf(); + } + return { + byteLength: this.buf8.byteLength, + char0: this.buf32[CHAR0_SLOT], + }; + } + + serialize(encoder) { + if ( encoder instanceof Object ) { + return encoder.encode( + this.buf32.buffer, + this.buf32[CHAR1_SLOT] + ); + } + return Array.from( + new Uint32Array( + this.buf32.buffer, + 0, + this.buf32[CHAR1_SLOT] + 3 >>> 2 + ) + ); + } + + unserialize(selfie, decoder) { + const shouldDecode = typeof selfie === 'string'; + let byteLength = shouldDecode + ? decoder.decodeSize(selfie) + : selfie.length << 2; + if ( byteLength === 0 ) { return false; } + this.reallocateBuf(byteLength); + if ( shouldDecode ) { + decoder.decode(selfie, this.buf8.buffer); + } else { + this.buf32.set(selfie); + } + return true; + } + + storeString(s) { + const n = s.length; + if ( n === this.lastStoredLen && s === this.lastStored ) { + return this.lastStoredIndex; + } + this.lastStored = s; + this.lastStoredLen = n; + if ( (this.buf8.length - this.buf32[CHAR1_SLOT]) < n ) { + this.growBuf(0, n); + } + const offset = this.buf32[CHAR1_SLOT]; + this.buf32[CHAR1_SLOT] = offset + n; + const buf8 = this.buf8; + for ( let i = 0; i < n; i++ ) { + buf8[offset+i] = s.charCodeAt(i); + } + return (this.lastStoredIndex = offset - this.buf32[CHAR0_SLOT]); + } + + extractString(i, n) { + if ( this.textDecoder === null ) { + this.textDecoder = new TextDecoder(); + } + const offset = this.buf32[CHAR0_SLOT] + i; + return this.textDecoder.decode( + this.buf8.subarray(offset, offset + n) + ); + } + + // WASMable. + startsWith(haystackLeft, haystackRight, needleLeft, needleLen) { + if ( haystackLeft < 0 || (haystackLeft + needleLen) > haystackRight ) { + return 0; + } + const charCodes = this.buf8; + needleLeft += this.buf32[CHAR0_SLOT]; + const needleRight = needleLeft + needleLen; + while ( charCodes[haystackLeft] === charCodes[needleLeft] ) { + needleLeft += 1; + if ( needleLeft === needleRight ) { return 1; } + haystackLeft += 1; + } + return 0; + } + + // Find the left-most instance of substring in main string + // WASMable. + indexOf(haystackLeft, haystackEnd, needleLeft, needleLen) { + if ( needleLen === 0 ) { return haystackLeft; } + haystackEnd -= needleLen; + if ( haystackEnd < haystackLeft ) { return -1; } + needleLeft += this.buf32[CHAR0_SLOT]; + const needleRight = needleLeft + needleLen; + const charCodes = this.buf8; + for (;;) { + let i = haystackLeft; + let j = needleLeft; + while ( charCodes[i] === charCodes[j] ) { + j += 1; + if ( j === needleRight ) { return haystackLeft; } + i += 1; + } + haystackLeft += 1; + if ( haystackLeft > haystackEnd ) { break; } + } + return -1; + } + + // Find the right-most instance of substring in main string. + // WASMable. + lastIndexOf(haystackBeg, haystackEnd, needleLeft, needleLen) { + if ( needleLen === 0 ) { return haystackBeg; } + let haystackLeft = haystackEnd - needleLen; + if ( haystackLeft < haystackBeg ) { return -1; } + needleLeft += this.buf32[CHAR0_SLOT]; + const needleRight = needleLeft + needleLen; + const charCodes = this.buf8; + for (;;) { + let i = haystackLeft; + let j = needleLeft; + while ( charCodes[i] === charCodes[j] ) { + j += 1; + if ( j === needleRight ) { return haystackLeft; } + i += 1; + } + if ( haystackLeft === haystackBeg ) { break; } + haystackLeft -= 1; + } + return -1; + } + + dumpTrie(iroot) { + for ( const s of this.trieIterator(iroot) ) { + console.log(s); + } + } + + trieIterator(iroot) { + return { + value: undefined, + done: false, + next() { + if ( this.icell === 0 ) { + if ( this.forks.length === 0 ) { + this.value = undefined; + this.done = true; + return this; + } + this.pattern = this.forks.pop(); + this.dir = this.forks.pop(); + this.icell = this.forks.pop(); + } + const buf32 = this.container.buf32; + const buf8 = this.container.buf8; + for (;;) { + const ialt = buf32[this.icell+CELL_OR]; + const v = buf32[this.icell+SEGMENT_INFO]; + const offset = v & 0x00FFFFFF; + let i0 = buf32[CHAR0_SLOT] + offset; + const len = v >>> 24; + for ( let i = 0; i < len; i++ ) { + this.charBuf[i] = buf8[i0+i]; + } + if ( len !== 0 && ialt !== 0 ) { + this.forks.push(ialt, this.dir, this.pattern); + } + const inext = buf32[this.icell+CELL_AND]; + if ( len !== 0 ) { + const s = this.textDecoder.decode( + new Uint8Array(this.charBuf.buffer, 0, len) + ); + if ( this.dir > 0 ) { + this.pattern += s; + } else if ( this.dir < 0 ) { + this.pattern = s + this.pattern; + } + } + this.icell = inext; + if ( len !== 0 ) { continue; } + // boundary cell + if ( ialt !== 0 ) { + if ( inext === 0 ) { + this.icell = ialt; + this.dir = -1; + } else { + this.forks.push(ialt, -1, this.pattern); + } + } + if ( offset !== 0 ) { + this.value = { pattern: this.pattern, iextra: offset }; + return this; + } + } + }, + container: this, + icell: iroot, + charBuf: new Uint8Array(256), + pattern: '', + dir: 1, + forks: [], + textDecoder: new TextDecoder(), + [Symbol.iterator]() { return this; }, + }; + } + + async enableWASM(wasmModuleFetcher, path) { + if ( typeof WebAssembly !== 'object' ) { return false; } + if ( this.wasmMemory instanceof WebAssembly.Memory ) { return true; } + const module = await getWasmModule(wasmModuleFetcher, path); + if ( module instanceof WebAssembly.Module === false ) { return false; } + const memory = new WebAssembly.Memory({ + initial: roundToPageSize(this.buf8.length) >>> 16 + }); + const instance = await WebAssembly.instantiate(module, { + imports: { memory, extraHandler: this.extraHandler } + }); + if ( instance instanceof WebAssembly.Instance === false ) { + return false; + } + this.wasmMemory = memory; + const curPageCount = memory.buffer.byteLength >>> 16; + const newPageCount = roundToPageSize(this.buf8.byteLength) >>> 16; + if ( newPageCount > curPageCount ) { + memory.grow(newPageCount - curPageCount); + } + const buf8 = new Uint8Array(memory.buffer); + buf8.set(this.buf8); + this.buf8 = buf8; + this.buf32 = new Uint32Array(this.buf8.buffer); + this.haystack = this.buf8.subarray( + HAYSTACK_START, + HAYSTACK_START + HAYSTACK_SIZE + ); + this.matches = instance.exports.matches; + this.startsWith = instance.exports.startsWith; + this.indexOf = instance.exports.indexOf; + this.lastIndexOf = instance.exports.lastIndexOf; + return true; + } + + dumpInfo() { + return [ + `Buffer size (Uint8Array): ${this.buf32[CHAR1_SLOT].toLocaleString('en')}`, + `WASM: ${this.wasmMemory === null ? 'disabled' : 'enabled'}`, + ].join('\n'); + } + + //-------------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------------- + + allocateCell() { + let icell = this.buf32[TRIE1_SLOT]; + this.buf32[TRIE1_SLOT] = icell + CELL_BYTE_LENGTH; + icell >>>= 2; + this.buf32[icell+0] = 0; + this.buf32[icell+1] = 0; + this.buf32[icell+2] = 0; + return icell; + } + + addCell(iand, ior, v) { + const icell = this.allocateCell(); + this.buf32[icell+CELL_AND] = iand; + this.buf32[icell+CELL_OR] = ior; + this.buf32[icell+SEGMENT_INFO] = v; + return icell; + } + + growBuf(trieGrow, charGrow) { + const char0 = Math.max( + roundToPageSize(this.buf32[TRIE1_SLOT] + trieGrow), + this.buf32[CHAR0_SLOT] + ); + const char1 = char0 + this.buf32[CHAR1_SLOT] - this.buf32[CHAR0_SLOT]; + const bufLen = Math.max( + roundToPageSize(char1 + charGrow), + this.buf8.length + ); + if ( bufLen > this.buf8.length ) { + this.reallocateBuf(bufLen); + } + if ( char0 !== this.buf32[CHAR0_SLOT] ) { + this.buf8.copyWithin( + char0, + this.buf32[CHAR0_SLOT], + this.buf32[CHAR1_SLOT] + ); + this.buf32[CHAR0_SLOT] = char0; + this.buf32[CHAR1_SLOT] = char1; + } + } + + shrinkBuf() { + const char0 = this.buf32[TRIE1_SLOT] + MIN_FREE_CELL_BYTE_LENGTH; + const char1 = char0 + this.buf32[CHAR1_SLOT] - this.buf32[CHAR0_SLOT]; + const bufLen = char1 + 256; + if ( char0 !== this.buf32[CHAR0_SLOT] ) { + this.buf8.copyWithin( + char0, + this.buf32[CHAR0_SLOT], + this.buf32[CHAR1_SLOT] + ); + this.buf32[CHAR0_SLOT] = char0; + this.buf32[CHAR1_SLOT] = char1; + } + if ( bufLen < this.buf8.length ) { + this.reallocateBuf(bufLen); + } + } + + reallocateBuf(newSize) { + newSize = roundToPageSize(newSize); + if ( newSize === this.buf8.length ) { return; } + if ( this.wasmMemory === null ) { + const newBuf = new Uint8Array(newSize); + newBuf.set( + newBuf.length < this.buf8.length + ? this.buf8.subarray(0, newBuf.length) + : this.buf8 + ); + this.buf8 = newBuf; + } else { + const growBy = + ((newSize + 0xFFFF) >>> 16) - (this.buf8.length >>> 16); + if ( growBy <= 0 ) { return; } + this.wasmMemory.grow(growBy); + this.buf8 = new Uint8Array(this.wasmMemory.buffer); + } + this.buf32 = new Uint32Array(this.buf8.buffer); + this.haystack = this.buf8.subarray( + HAYSTACK_START, + HAYSTACK_START + HAYSTACK_SIZE + ); + } +} + +/******************************************************************************/ + +// Code below is to attempt to load a WASM module which implements: +// +// - BidiTrieContainer.startsWith() +// +// The WASM module is entirely optional, the JS implementations will be +// used should the WASM module be unavailable for whatever reason. + +const getWasmModule = (( ) => { + let wasmModulePromise; + + return async function(wasmModuleFetcher, path) { + if ( wasmModulePromise instanceof Promise ) { + return wasmModulePromise; + } + + if ( typeof WebAssembly !== 'object' ) { return; } + + // Soft-dependency on vAPI so that the code here can be used outside of + // uBO (i.e. tests, benchmarks) + if ( typeof vAPI === 'object' && vAPI.canWASM !== true ) { return; } + + // The wasm module will work only if CPU is natively little-endian, + // as we use native uint32 array in our js code. + const uint32s = new Uint32Array(1); + const uint8s = new Uint8Array(uint32s.buffer); + uint32s[0] = 1; + if ( uint8s[0] !== 1 ) { return; } + + wasmModulePromise = wasmModuleFetcher(`${path}biditrie`).catch(reason => { + console.info(reason); + }); + + return wasmModulePromise; + }; +})(); + +/******************************************************************************/ + +export default BidiTrieContainer; diff --git a/src/js/broadcast.js b/src/js/broadcast.js new file mode 100644 index 0000000..0bef46c --- /dev/null +++ b/src/js/broadcast.js @@ -0,0 +1,75 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ + +// Broadcast a message to all uBO contexts + +let broadcastChannel; + +export function broadcast(message) { + if ( broadcastChannel === undefined ) { + broadcastChannel = new self.BroadcastChannel('uBO'); + } + broadcastChannel.postMessage(message); +} + +/******************************************************************************/ + +// Broadcast a message to all uBO contexts and all uBO's content scripts + +export async function broadcastToAll(message) { + broadcast(message); + const tabs = await vAPI.tabs.query({ + discarded: false, + }); + const bcmessage = Object.assign({ broadcast: true }, message); + for ( const tab of tabs ) { + browser.tabs.sendMessage(tab.id, bcmessage); + } +} + +/******************************************************************************/ + +export function onBroadcast(listener) { + const bc = new self.BroadcastChannel('uBO'); + bc.onmessage = ev => listener(ev.data || {}); + return bc; +} + +/******************************************************************************/ + +export function filteringBehaviorChanged(details = {}) { + if ( typeof details.direction !== 'number' || details.direction >= 0 ) { + filteringBehaviorChanged.throttle.offon(727); + } + broadcast(Object.assign({ what: 'filteringBehaviorChanged' }, details)); +} + +filteringBehaviorChanged.throttle = vAPI.defer.create(( ) => { + vAPI.net.handlerBehaviorChanged(); +}); + +/******************************************************************************/ diff --git a/src/js/cachestorage.js b/src/js/cachestorage.js new file mode 100644 index 0000000..ef056af --- /dev/null +++ b/src/js/cachestorage.js @@ -0,0 +1,533 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2016-present The uBlock Origin authors + + 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 +*/ + +/* global browser, IDBDatabase, indexedDB */ + +'use strict'; + +/******************************************************************************/ + +import lz4Codec from './lz4.js'; +import µb from './background.js'; +import webext from './webext.js'; + +/******************************************************************************/ + +// The code below has been originally manually imported from: +// Commit: https://github.com/nikrolls/uBlock-Edge/commit/d1538ea9bea89d507219d3219592382eee306134 +// Commit date: 29 October 2016 +// Commit author: https://github.com/nikrolls +// Commit message: "Implement cacheStorage using IndexedDB" + +// The original imported code has been subsequently modified as it was not +// compatible with Firefox. +// (a Promise thing, see https://github.com/dfahlander/Dexie.js/issues/317) +// Furthermore, code to migrate from browser.storage.local to vAPI.storage +// has been added, for seamless migration of cache-related entries into +// indexedDB. + +// https://bugzilla.mozilla.org/show_bug.cgi?id=1371255 +// Firefox-specific: we use indexedDB because browser.storage.local() has +// poor performance in Firefox. +// https://github.com/uBlockOrigin/uBlock-issues/issues/328 +// Use IndexedDB for Chromium as well, to take advantage of LZ4 +// compression. +// https://github.com/uBlockOrigin/uBlock-issues/issues/399 +// Revert Chromium support of IndexedDB, use advanced setting to force +// IndexedDB. +// https://github.com/uBlockOrigin/uBlock-issues/issues/409 +// Allow forcing the use of webext storage on Firefox. + +const STORAGE_NAME = 'uBlock0CacheStorage'; + +// Default to webext storage. +const storageLocal = webext.storage.local; + +let storageReadyResolve; +const storageReadyPromise = new Promise(resolve => { + storageReadyResolve = resolve; +}); + +const cacheStorage = { + name: 'browser.storage.local', + get(...args) { + return storageReadyPromise.then(( ) => + storageLocal.get(...args).catch(reason => { + console.log(reason); + }) + ); + }, + set(...args) { + return storageReadyPromise.then(( ) => + storageLocal.set(...args).catch(reason => { + console.log(reason); + }) + ); + }, + remove(...args) { + return storageReadyPromise.then(( ) => + storageLocal.remove(...args).catch(reason => { + console.log(reason); + }) + ); + }, + clear(...args) { + return storageReadyPromise.then(( ) => + storageLocal.clear(...args).catch(reason => { + console.log(reason); + }) + ); + }, + select: function(selectedBackend) { + let actualBackend = selectedBackend; + if ( actualBackend === undefined || actualBackend === 'unset' ) { + actualBackend = vAPI.webextFlavor.soup.has('firefox') + ? 'indexedDB' + : 'browser.storage.local'; + } + if ( actualBackend === 'indexedDB' ) { + return selectIDB().then(success => { + if ( success || selectedBackend === 'indexedDB' ) { + clearWebext(); + storageReadyResolve(); + return 'indexedDB'; + } + clearIDB(); + storageReadyResolve(); + return 'browser.storage.local'; + }); + } + if ( actualBackend === 'browser.storage.local' ) { + clearIDB(); + } + storageReadyResolve(); + return Promise.resolve('browser.storage.local'); + + }, + error: undefined +}; + +// Not all platforms support getBytesInUse +if ( storageLocal.getBytesInUse instanceof Function ) { + cacheStorage.getBytesInUse = function(...args) { + return storageLocal.getBytesInUse(...args).catch(reason => { + console.log(reason); + }); + }; +} + +// Reassign API entries to that of indexedDB-based ones +const selectIDB = async function() { + let db; + let dbPromise; + + const noopfn = function () { + }; + + const disconnect = function() { + dbTimer.off(); + if ( db instanceof IDBDatabase ) { + db.close(); + db = undefined; + } + }; + + const dbTimer = vAPI.defer.create(( ) => { + disconnect(); + }); + + const keepAlive = function() { + dbTimer.offon(Math.max( + µb.hiddenSettings.autoUpdateAssetFetchPeriod * 2 * 1000, + 180000 + )); + }; + + // https://github.com/gorhill/uBlock/issues/3156 + // I have observed that no event was fired in Tor Browser 7.0.7 + + // medium security level after the request to open the database was + // created. When this occurs, I have also observed that the `error` + // property was already set, so this means uBO can detect here whether + // the database can be opened successfully. A try-catch block is + // necessary when reading the `error` property because we are not + // allowed to read this property outside of event handlers in newer + // implementation of IDBRequest (my understanding). + + const getDb = function() { + keepAlive(); + if ( db !== undefined ) { + return Promise.resolve(db); + } + if ( dbPromise !== undefined ) { + return dbPromise; + } + dbPromise = new Promise(resolve => { + let req; + try { + req = indexedDB.open(STORAGE_NAME, 1); + if ( req.error ) { + console.log(req.error); + req = undefined; + } + } catch(ex) { + } + if ( req === undefined ) { + db = null; + dbPromise = undefined; + return resolve(null); + } + req.onupgradeneeded = function(ev) { + // https://github.com/uBlockOrigin/uBlock-issues/issues/2725 + // If context Firefox + incognito mode, fall back to + // browser.storage.local for cache storage purpose. + if ( + vAPI.webextFlavor.soup.has('firefox') && + browser.extension.inIncognitoContext === true + ) { + return req.onerror(); + } + if ( ev.oldVersion === 1 ) { return; } + try { + const db = ev.target.result; + db.createObjectStore(STORAGE_NAME, { keyPath: 'key' }); + } catch(ex) { + req.onerror(); + } + }; + req.onsuccess = function(ev) { + if ( resolve === undefined ) { return; } + req = undefined; + db = ev.target.result; + dbPromise = undefined; + resolve(db); + resolve = undefined; + }; + req.onerror = req.onblocked = function() { + if ( resolve === undefined ) { return; } + req = undefined; + console.log(this.error); + db = null; + dbPromise = undefined; + resolve(null); + resolve = undefined; + }; + vAPI.defer.once(5000).then(( ) => { + if ( resolve === undefined ) { return; } + db = null; + dbPromise = undefined; + resolve(null); + resolve = undefined; + }); + }); + return dbPromise; + }; + + const fromBlob = function(data) { + if ( data instanceof Blob === false ) { + return Promise.resolve(data); + } + return new Promise(resolve => { + const blobReader = new FileReader(); + blobReader.onloadend = ev => { + resolve(new Uint8Array(ev.target.result)); + }; + blobReader.readAsArrayBuffer(data); + }); + }; + + const toBlob = function(data) { + const value = data instanceof Uint8Array + ? new Blob([ data ]) + : data; + return Promise.resolve(value); + }; + + const compress = function(store, key, data) { + return lz4Codec.encode(data, toBlob).then(value => { + store.push({ key, value }); + }); + }; + + const decompress = function(store, key, data) { + return lz4Codec.decode(data, fromBlob).then(data => { + store[key] = data; + }); + }; + + const getFromDb = async function(keys, keyvalStore, callback) { + if ( typeof callback !== 'function' ) { return; } + if ( keys.length === 0 ) { return callback(keyvalStore); } + const promises = []; + const gotOne = function() { + if ( typeof this.result !== 'object' ) { return; } + const { key, value } = this.result; + keyvalStore[key] = value; + if ( value instanceof Blob === false ) { return; } + promises.push(decompress(keyvalStore, key, value)); + }; + try { + const db = await getDb(); + if ( !db ) { return callback(); } + const transaction = db.transaction(STORAGE_NAME, 'readonly'); + transaction.oncomplete = + transaction.onerror = + transaction.onabort = ( ) => { + Promise.all(promises).then(( ) => { + callback(keyvalStore); + }); + }; + const table = transaction.objectStore(STORAGE_NAME); + for ( const key of keys ) { + const req = table.get(key); + req.onsuccess = gotOne; + req.onerror = noopfn; + } + } + catch(reason) { + console.info(`cacheStorage.getFromDb() failed: ${reason}`); + callback(); + } + }; + + const visitAllFromDb = async function(visitFn) { + const db = await getDb(); + if ( !db ) { return visitFn(); } + const transaction = db.transaction(STORAGE_NAME, 'readonly'); + transaction.oncomplete = + transaction.onerror = + transaction.onabort = ( ) => visitFn(); + const table = transaction.objectStore(STORAGE_NAME); + const req = table.openCursor(); + req.onsuccess = function(ev) { + let cursor = ev.target && ev.target.result; + if ( !cursor ) { return; } + let entry = cursor.value; + visitFn(entry); + cursor.continue(); + }; + }; + + const getAllFromDb = function(callback) { + if ( typeof callback !== 'function' ) { return; } + const promises = []; + const keyvalStore = {}; + visitAllFromDb(entry => { + if ( entry === undefined ) { + Promise.all(promises).then(( ) => { + callback(keyvalStore); + }); + return; + } + const { key, value } = entry; + keyvalStore[key] = value; + if ( entry.value instanceof Blob === false ) { return; } + promises.push(decompress(keyvalStore, key, value)); + }).catch(reason => { + console.info(`cacheStorage.getAllFromDb() failed: ${reason}`); + callback(); + }); + }; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/141 + // Mind that IDBDatabase.transaction() and IDBObjectStore.put() + // can throw: + // https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/transaction + // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/put + + const putToDb = async function(keyvalStore, callback) { + if ( typeof callback !== 'function' ) { + callback = noopfn; + } + const keys = Object.keys(keyvalStore); + if ( keys.length === 0 ) { return callback(); } + const promises = [ getDb() ]; + const entries = []; + const dontCompress = + µb.hiddenSettings.cacheStorageCompression !== true; + for ( const key of keys ) { + const value = keyvalStore[key]; + const isString = typeof value === 'string'; + if ( isString === false || dontCompress ) { + entries.push({ key, value }); + continue; + } + promises.push(compress(entries, key, value)); + } + const finish = ( ) => { + if ( callback === undefined ) { return; } + let cb = callback; + callback = undefined; + cb(); + }; + try { + const results = await Promise.all(promises); + const db = results[0]; + if ( !db ) { return callback(); } + const transaction = db.transaction( + STORAGE_NAME, + 'readwrite' + ); + transaction.oncomplete = + transaction.onerror = + transaction.onabort = finish; + const table = transaction.objectStore(STORAGE_NAME); + for ( const entry of entries ) { + table.put(entry); + } + } catch (ex) { + finish(); + } + }; + + const deleteFromDb = async function(input, callback) { + if ( typeof callback !== 'function' ) { + callback = noopfn; + } + const keys = Array.isArray(input) ? input.slice() : [ input ]; + if ( keys.length === 0 ) { return callback(); } + const finish = ( ) => { + if ( callback === undefined ) { return; } + let cb = callback; + callback = undefined; + cb(); + }; + try { + const db = await getDb(); + if ( !db ) { return callback(); } + const transaction = db.transaction(STORAGE_NAME, 'readwrite'); + transaction.oncomplete = + transaction.onerror = + transaction.onabort = finish; + const table = transaction.objectStore(STORAGE_NAME); + for ( const key of keys ) { + table.delete(key); + } + } catch (ex) { + finish(); + } + }; + + const clearDb = async function(callback) { + if ( typeof callback !== 'function' ) { + callback = noopfn; + } + try { + const db = await getDb(); + if ( !db ) { return callback(); } + const transaction = db.transaction(STORAGE_NAME, 'readwrite'); + transaction.oncomplete = + transaction.onerror = + transaction.onabort = ( ) => { + callback(); + }; + transaction.objectStore(STORAGE_NAME).clear(); + } + catch(reason) { + console.info(`cacheStorage.clearDb() failed: ${reason}`); + callback(); + } + }; + + await getDb(); + if ( !db ) { return false; } + + cacheStorage.name = 'indexedDB'; + cacheStorage.get = function get(keys) { + return storageReadyPromise.then(( ) => + new Promise(resolve => { + if ( keys === null ) { + return getAllFromDb(bin => resolve(bin)); + } + let toRead, output = {}; + if ( typeof keys === 'string' ) { + toRead = [ keys ]; + } else if ( Array.isArray(keys) ) { + toRead = keys; + } else /* if ( typeof keys === 'object' ) */ { + toRead = Object.keys(keys); + output = keys; + } + getFromDb(toRead, output, bin => resolve(bin)); + }) + ); + }; + cacheStorage.set = function set(keys) { + return storageReadyPromise.then(( ) => + new Promise(resolve => { + putToDb(keys, details => resolve(details)); + }) + ); + }; + cacheStorage.remove = function remove(keys) { + return storageReadyPromise.then(( ) => + new Promise(resolve => { + deleteFromDb(keys, ( ) => resolve()); + }) + ); + }; + cacheStorage.clear = function clear() { + return storageReadyPromise.then(( ) => + new Promise(resolve => { + clearDb(( ) => resolve()); + }) + ); + }; + cacheStorage.getBytesInUse = function getBytesInUse() { + return Promise.resolve(0); + }; + return true; +}; + +// https://github.com/uBlockOrigin/uBlock-issues/issues/328 +// Delete cache-related entries from webext storage. +const clearWebext = async function() { + let bin; + try { + bin = await webext.storage.local.get('assetCacheRegistry'); + } catch(ex) { + console.error(ex); + } + if ( bin instanceof Object === false ) { return; } + if ( bin.assetCacheRegistry instanceof Object === false ) { return; } + const toRemove = [ + 'assetCacheRegistry', + 'assetSourceRegistry', + ]; + for ( const key in bin.assetCacheRegistry ) { + if ( bin.assetCacheRegistry.hasOwnProperty(key) ) { + toRemove.push('cache/' + key); + } + } + webext.storage.local.remove(toRemove); +}; + +const clearIDB = function() { + try { + indexedDB.deleteDatabase(STORAGE_NAME); + } catch(ex) { + } +}; + +/******************************************************************************/ + +export default cacheStorage; + +/******************************************************************************/ diff --git a/src/js/click2load.js b/src/js/click2load.js new file mode 100644 index 0000000..42b7525 --- /dev/null +++ b/src/js/click2load.js @@ -0,0 +1,60 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } + +const url = new URL(self.location.href); +const actualURL = url.searchParams.get('url'); +const frameURL = url.searchParams.get('aliasURL') || actualURL; +const frameURLElem = document.getElementById('frameURL'); + +frameURLElem.children[0].textContent = actualURL; + +frameURLElem.children[1].href = frameURL; +frameURLElem.children[1].title = frameURL; + +document.body.setAttribute('title', actualURL); + +document.body.addEventListener('click', ev => { + if ( ev.isTrusted === false ) { return; } + if ( ev.target.closest('#frameURL') !== null ) { return; } + vAPI.messaging.send('default', { + what: 'clickToLoad', + frameURL, + }).then(ok => { + if ( ok ) { + self.location.replace(frameURL); + } + }); +}); + +/******************************************************************************/ + +})(); diff --git a/src/js/cloud-ui.js b/src/js/cloud-ui.js new file mode 100644 index 0000000..228f114 --- /dev/null +++ b/src/js/cloud-ui.js @@ -0,0 +1,238 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-2018 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 +*/ + +/* global faIconsInit */ + +'use strict'; + +import { i18n, i18n$ } from './i18n.js'; +import { dom, qs$ } from './dom.js'; +import { faIconsInit } from './fa-icons.js'; + +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +self.cloud = { + options: {}, + datakey: '', + data: undefined, + onPush: null, + onPull: null, +}; + +/******************************************************************************/ + +const widget = qs$('#cloudWidget'); +if ( widget === null ) { return; } + +self.cloud.datakey = dom.attr(widget, 'data-cloud-entry') || ''; +if ( self.cloud.datakey === '' ) { return; } + +/******************************************************************************/ + +const fetchStorageUsed = async function() { + let elem = qs$(widget, '#cloudCapacity'); + if ( dom.cl.has(elem, 'hide') ) { return; } + const result = await vAPI.messaging.send('cloudWidget', { + what: 'cloudUsed', + datakey: self.cloud.datakey, + }); + if ( result instanceof Object === false ) { + dom.cl.add(elem, 'hide'); + return; + } + const units = ' ' + i18n$('genericBytes'); + elem.title = result.max.toLocaleString() + units; + const total = (result.total / result.max * 100).toFixed(1); + elem = elem.firstElementChild; + elem.style.width = `${total}%`; + elem.title = result.total.toLocaleString() + units; + const used = (result.used / result.total * 100).toFixed(1); + elem = elem.firstElementChild; + elem.style.width = `${used}%`; + elem.title = result.used.toLocaleString() + units; +}; + +/******************************************************************************/ + +const fetchCloudData = async function() { + const info = qs$(widget, '#cloudInfo'); + + const entry = await vAPI.messaging.send('cloudWidget', { + what: 'cloudPull', + datakey: self.cloud.datakey, + }); + + const hasData = entry instanceof Object; + if ( hasData === false ) { + dom.attr('#cloudPull', 'disabled', ''); + dom.attr('#cloudPullAndMerge', 'disabled', ''); + info.textContent = '...\n...'; + return entry; + } + + self.cloud.data = entry.data; + + dom.attr('#cloudPull', 'disabled', null); + dom.attr('#cloudPullAndMerge', 'disabled', null); + + const timeOptions = { + weekday: 'short', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + second: 'numeric', + timeZoneName: 'short' + }; + + const time = new Date(entry.tstamp); + info.textContent = + entry.source + '\n' + + time.toLocaleString('fullwide', timeOptions); +}; + +/******************************************************************************/ + +const pushData = async function() { + if ( typeof self.cloud.onPush !== 'function' ) { return; } + + const error = await vAPI.messaging.send('cloudWidget', { + what: 'cloudPush', + datakey: self.cloud.datakey, + data: self.cloud.onPush(), + }); + const failed = typeof error === 'string'; + dom.cl.toggle('#cloudPush', 'error', failed); + dom.text('#cloudError', failed ? error : ''); + if ( failed ) { return; } + fetchCloudData(); + fetchStorageUsed(); +}; + +/******************************************************************************/ + +const pullData = function() { + if ( typeof self.cloud.onPull === 'function' ) { + self.cloud.onPull(self.cloud.data, false); + } + dom.cl.remove('#cloudPush', 'error'); + dom.text('#cloudError', ''); +}; + +/******************************************************************************/ + +const pullAndMergeData = function() { + if ( typeof self.cloud.onPull === 'function' ) { + self.cloud.onPull(self.cloud.data, true); + } +}; + +/******************************************************************************/ + +const openOptions = function() { + const input = qs$('#cloudDeviceName'); + input.value = self.cloud.options.deviceName; + dom.attr(input, 'placeholder', self.cloud.options.defaultDeviceName); + dom.cl.add('#cloudOptions', 'show'); +}; + +/******************************************************************************/ + +const closeOptions = function(ev) { + const root = qs$('#cloudOptions'); + if ( ev.target !== root ) { return; } + dom.cl.remove(root, 'show'); +}; + +/******************************************************************************/ + +const submitOptions = async function() { + dom.cl.remove('#cloudOptions', 'show'); + + const options = await vAPI.messaging.send('cloudWidget', { + what: 'cloudSetOptions', + options: { + deviceName: qs$('#cloudDeviceName').value + }, + }); + if ( options instanceof Object ) { + self.cloud.options = options; + } +}; + +/******************************************************************************/ + +const onInitialize = function(options) { + if ( options instanceof Object === false ) { return; } + if ( options.enabled !== true ) { return; } + self.cloud.options = options; + + const xhr = new XMLHttpRequest(); + xhr.open('GET', 'cloud-ui.html', true); + xhr.overrideMimeType('text/html;charset=utf-8'); + xhr.responseType = 'text'; + xhr.onload = function() { + this.onload = null; + const parser = new DOMParser(), + parsed = parser.parseFromString(this.responseText, 'text/html'), + fromParent = parsed.body; + while ( fromParent.firstElementChild !== null ) { + widget.appendChild( + document.adoptNode(fromParent.firstElementChild) + ); + } + + faIconsInit(widget); + + i18n.render(widget); + dom.cl.remove(widget, 'hide'); + + dom.on('#cloudPush', 'click', ( ) => { pushData(); }); + dom.on('#cloudPull', 'click', pullData); + dom.on('#cloudPullAndMerge', 'click', pullAndMergeData); + dom.on('#cloudCog', 'click', openOptions); + dom.on('#cloudOptions', 'click', closeOptions); + dom.on('#cloudOptionsSubmit', 'click', ( ) => { submitOptions(); }); + + fetchCloudData().then(result => { + if ( typeof result !== 'string' ) { return; } + dom.cl.add('#cloudPush', 'error'); + dom.text('#cloudError', result); + }); + fetchStorageUsed(); + }; + xhr.send(); +}; + +vAPI.messaging.send('cloudWidget', { + what: 'cloudGetOptions', +}).then(options => { + onInitialize(options); +}); + +/******************************************************************************/ + +})(); diff --git a/src/js/code-viewer.js b/src/js/code-viewer.js new file mode 100644 index 0000000..f11289a --- /dev/null +++ b/src/js/code-viewer.js @@ -0,0 +1,311 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2023-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 +*/ + +/* globals CodeMirror, uBlockDashboard, beautifier */ + +'use strict'; + +/******************************************************************************/ + +import { dom, qs$ } from './dom.js'; +import { getActualTheme } from './theme.js'; + +/******************************************************************************/ + +const urlToDocMap = new Map(); +const params = new URLSearchParams(document.location.search); +let currentURL = ''; + +const cmEditor = new CodeMirror(qs$('#content'), { + autofocus: true, + gutters: [ 'CodeMirror-linenumbers' ], + lineNumbers: true, + lineWrapping: true, + matchBrackets: true, + styleActiveLine: { + nonEmpty: true, + }, +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +vAPI.messaging.send('dom', { what: 'uiStyles' }).then(response => { + if ( typeof response !== 'object' || response === null ) { return; } + if ( getActualTheme(response.uiTheme) === 'dark' ) { + dom.cl.add('#content .cm-s-default', 'cm-s-night'); + dom.cl.remove('#content .cm-s-default', 'cm-s-default'); + } +}); + +// Convert resource URLs into clickable links to code viewer +cmEditor.addOverlay({ + re: /\b(?:href|src)=["']([^"']+)["']/g, + match: null, + token: function(stream) { + if ( stream.sol() ) { + this.re.lastIndex = 0; + this.match = this.re.exec(stream.string); + } + if ( this.match === null ) { + stream.skipToEnd(); + return null; + } + const end = this.re.lastIndex - 1; + const beg = end - this.match[1].length; + if ( stream.pos < beg ) { + stream.pos = beg; + return null; + } + if ( stream.pos < end ) { + stream.pos = end; + return 'href'; + } + if ( stream.pos < this.re.lastIndex ) { + stream.pos = this.re.lastIndex; + this.match = this.re.exec(stream.string); + return null; + } + stream.skipToEnd(); + return null; + }, +}); + +urlToDocMap.set('', cmEditor.getDoc()); + +/******************************************************************************/ + +async function fetchResource(url) { + let response, text; + const fetchOptions = { + method: 'GET', + referrer: '', + }; + if ( urlToDocMap.has(url) ) { + fetchOptions.cache = 'reload'; + } + try { + response = await fetch(url, fetchOptions); + text = await response.text(); + } catch(reason) { + text = String(reason); + } + let mime = response && response.headers.get('Content-Type') || ''; + mime = mime.replace(/\s*;.*$/, '').trim(); + const beautifierOptions = { + end_with_newline: true, + indent_size: 3, + js: { + max_preserve_newlines: 3, + } + }; + switch ( mime ) { + case 'text/css': + text = beautifier.css(text, beautifierOptions); + break; + case 'text/html': + case 'application/xhtml+xml': + case 'application/xml': + case 'image/svg+xml': + text = beautifier.html(text, beautifierOptions); + break; + case 'text/javascript': + case 'application/javascript': + case 'application/x-javascript': + text = beautifier.js(text, beautifierOptions); + break; + case 'application/json': + text = beautifier.js(text, beautifierOptions); + break; + default: + break; + } + return { mime, text }; +} + +/******************************************************************************/ + +function addPastURLs(url) { + const list = qs$('#pastURLs'); + let current; + for ( let i = 0; i < list.children.length; i++ ) { + const span = list.children[i]; + dom.cl.remove(span, 'selected'); + if ( span.textContent !== url ) { continue; } + current = span; + } + if ( url === '' ) { return; } + if ( current === undefined ) { + current = document.createElement('span'); + current.textContent = url; + list.prepend(current); + } + dom.cl.add(current, 'selected'); +} + +/******************************************************************************/ + +function setInputURL(url) { + const input = qs$('#header input[type="url"]'); + if ( url === input.value ) { return; } + dom.attr(input, 'value', url); + input.value = url; +} + +/******************************************************************************/ + +async function setURL(resourceURL) { + // For convenience, remove potentially existing quotes around the URL + if ( /^(["']).+\1$/.test(resourceURL) ) { + resourceURL = resourceURL.slice(1, -1); + } + let afterURL; + if ( resourceURL !== '' ) { + try { + const url = new URL(resourceURL, currentURL || undefined); + url.hash = ''; + afterURL = url.href; + } catch(ex) { + } + if ( afterURL === undefined ) { return; } + } else { + afterURL = ''; + } + if ( afterURL !== '' && /^https?:\/\/./.test(afterURL) === false ) { + return; + } + if ( afterURL === currentURL ) { + if ( afterURL !== resourceURL ) { + setInputURL(afterURL); + } + return; + } + let afterDoc = urlToDocMap.get(afterURL); + if ( afterDoc === undefined ) { + const r = await fetchResource(afterURL) || { mime: '', text: '' }; + afterDoc = new CodeMirror.Doc(r.text, r.mime || ''); + urlToDocMap.set(afterURL, afterDoc); + } + swapDoc(afterDoc); + currentURL = afterURL; + setInputURL(afterURL); + const a = qs$('.cm-search-widget .sourceURL'); + dom.attr(a, 'href', afterURL); + dom.attr(a, 'title', afterURL); + addPastURLs(afterURL); + // For unknown reasons, calling focus() synchronously does not work... + vAPI.defer.once(1).then(( ) => { cmEditor.focus(); }); +} + +/******************************************************************************/ + +function removeURL(url) { + if ( url === '' ) { return; } + const list = qs$('#pastURLs'); + let foundAt = -1; + for ( let i = 0; i < list.children.length; i++ ) { + const span = list.children[i]; + if ( span.textContent !== url ) { continue; } + foundAt = i; + } + if ( foundAt === -1 ) { return; } + list.children[foundAt].remove(); + if ( foundAt >= list.children.length ) { + foundAt = list.children.length - 1; + } + const afterURL = foundAt !== -1 + ? list.children[foundAt].textContent + : ''; + setURL(afterURL); + urlToDocMap.delete(url); +} + +/******************************************************************************/ + +function swapDoc(doc) { + const r = cmEditor.swapDoc(doc); + if ( self.searchThread ) { + self.searchThread.setHaystack(cmEditor.getValue()); + } + const input = qs$('.cm-search-widget-input input[type="search"]'); + if ( input.value !== '' ) { + qs$('.cm-search-widget').dispatchEvent(new Event('input')); + } + return r; +} + +/******************************************************************************/ + +async function start() { + await setURL(params.get('url')); + + dom.on('#header input[type="url"]', 'change', ev => { + setURL(ev.target.value); + }); + + dom.on('#reloadURL', 'click', ( ) => { + const input = qs$('#header input[type="url"]'); + const url = input.value; + const beforeDoc = swapDoc(new CodeMirror.Doc('', '')); + fetchResource(url).then(r => { + if ( urlToDocMap.has(url) === false ) { return; } + const afterDoc = r !== undefined + ? new CodeMirror.Doc(r.text, r.mime || '') + : beforeDoc; + urlToDocMap.set(url, afterDoc); + if ( currentURL !== url ) { return; } + swapDoc(afterDoc); + }); + }); + + dom.on('#removeURL', 'click', ( ) => { + removeURL(qs$('#header input[type="url"]').value); + }); + + dom.on('#pastURLs', 'mousedown', 'span', ev => { + setURL(ev.target.textContent); + }); + + dom.on('#content', 'click', '.cm-href', ev => { + const target = ev.target; + const urlParts = [ target.textContent ]; + let previous = target; + for (;;) { + previous = previous.previousSibling; + if ( previous === null ) { break; } + if ( previous.nodeType !== 1 ) { break; } + if ( previous.classList.contains('cm-href') === false ) { break; } + urlParts.unshift(previous.textContent); + } + let next = target; + for (;;) { + next = next.nextSibling; + if ( next === null ) { break; } + if ( next.nodeType !== 1 ) { break; } + if ( next.classList.contains('cm-href') === false ) { break; } + urlParts.push(next.textContent); + } + setURL(urlParts.join('')); + }); +} + +start(); + +/******************************************************************************/ diff --git a/src/js/codemirror/search-thread.js b/src/js/codemirror/search-thread.js new file mode 100644 index 0000000..3a4416f --- /dev/null +++ b/src/js/codemirror/search-thread.js @@ -0,0 +1,199 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2020-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 +*/ + +'use strict'; + +/******************************************************************************/ + +(( ) => { +// >>>>> start of local scope + +/******************************************************************************/ + +// Worker context + +if ( + self.WorkerGlobalScope instanceof Object && + self instanceof self.WorkerGlobalScope +) { + let content = ''; + + const doSearch = function(details) { + const reEOLs = /\n\r|\r\n|\n|\r/g; + const t1 = Date.now() + 750; + + let reSearch; + try { + reSearch = new RegExp(details.pattern, details.flags); + } catch(ex) { + return; + } + + const response = []; + const maxOffset = content.length; + let iLine = 0; + let iOffset = 0; + let size = 0; + while ( iOffset < maxOffset ) { + // Find next match + const match = reSearch.exec(content); + if ( match === null ) { break; } + // Find number of line breaks between last and current match. + reEOLs.lastIndex = 0; + const eols = content.slice(iOffset, match.index).match(reEOLs); + if ( Array.isArray(eols) ) { + iLine += eols.length; + } + // Store line + response.push(iLine); + size += 1; + // Find next line break. + reEOLs.lastIndex = reSearch.lastIndex; + const eol = reEOLs.exec(content); + iOffset = eol !== null + ? reEOLs.lastIndex + : content.length; + reSearch.lastIndex = iOffset; + iLine += 1; + // Quit if this takes too long + if ( (size & 0x3FF) === 0 && Date.now() >= t1 ) { break; } + } + + return response; + }; + + self.onmessage = function(e) { + const msg = e.data; + + switch ( msg.what ) { + case 'setHaystack': + content = msg.content; + break; + + case 'doSearch': + const response = doSearch(msg); + self.postMessage({ id: msg.id, response }); + break; + } + }; + + return; +} + +/******************************************************************************/ + +// Main context + +{ + const workerTTL = { min: 5 }; + const pendingResponses = new Map(); + const workerTTLTimer = vAPI.defer.create(( ) => { + shutdown(); + }); + + let worker; + let messageId = 1; + + const onWorkerMessage = function(e) { + const msg = e.data; + const resolver = pendingResponses.get(msg.id); + if ( resolver === undefined ) { return; } + pendingResponses.delete(msg.id); + resolver(msg.response); + }; + + const cancelPendingTasks = function() { + for ( const resolver of pendingResponses.values() ) { + resolver(); + } + pendingResponses.clear(); + }; + + const destroy = function() { + shutdown(); + self.searchThread = undefined; + }; + + const shutdown = function() { + if ( worker === undefined ) { return; } + workerTTLTimer.off(); + worker.terminate(); + worker.onmessage = undefined; + worker = undefined; + cancelPendingTasks(); + }; + + const init = function() { + if ( self.searchThread instanceof Object === false ) { return; } + if ( worker === undefined ) { + worker = new Worker('js/codemirror/search-thread.js'); + worker.onmessage = onWorkerMessage; + } + workerTTLTimer.offon(workerTTL); + }; + + const needHaystack = function() { + return worker instanceof Object === false; + }; + + const setHaystack = function(content) { + init(); + worker.postMessage({ what: 'setHaystack', content }); + }; + + const search = function(query, overwrite = true) { + init(); + if ( worker instanceof Object === false ) { + return Promise.resolve(); + } + if ( overwrite ) { + cancelPendingTasks(); + } + const id = messageId++; + worker.postMessage({ + what: 'doSearch', + id, + pattern: query.source, + flags: query.flags, + isRE: query instanceof RegExp + }); + return new Promise(resolve => { + pendingResponses.set(id, resolve); + }); + }; + + self.addEventListener( + 'beforeunload', + ( ) => { destroy(); }, + { once: true } + ); + + self.searchThread = { needHaystack, setHaystack, search, shutdown }; +} + +/******************************************************************************/ + +// <<<<< end of local scope +})(); + +/******************************************************************************/ + +void 0; diff --git a/src/js/codemirror/search.js b/src/js/codemirror/search.js new file mode 100644 index 0000000..477e9cc --- /dev/null +++ b/src/js/codemirror/search.js @@ -0,0 +1,504 @@ +// The following code is heavily based on the standard CodeMirror +// search addon found at: https://codemirror.net/addon/search/search.js +// I added/removed and modified code in order to get a closer match to a +// browser's built-in find-in-page feature which are just enough for +// uBlock Origin. +// +// This file was originally wholly imported from: +// https://github.com/codemirror/CodeMirror/blob/3e1bb5fff682f8f6cbfaef0e56c61d62403d4798/addon/search/search.js +// +// And has been modified over time to better suit uBO's usage and coding style: +// https://github.com/gorhill/uBlock/commits/master/src/js/codemirror/search.js +// +// The original copyright notice is reproduced below: + +// ===== +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// Define search commands. Depends on dialog.js or another +// implementation of the openDialog method. + +// Replace works a little oddly -- it will do the replace on the next +// Ctrl-G (or whatever is bound to findNext) press. You prevent a +// replace by making sure the match is no longer selected when hitting +// Ctrl-G. +// ===== + +'use strict'; + +import { dom, qs$ } from '../dom.js'; +import { i18n$ } from '../i18n.js'; + +{ + const CodeMirror = self.CodeMirror; + + const searchOverlay = function(query, caseInsensitive) { + if ( typeof query === 'string' ) + query = new RegExp( + query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), + caseInsensitive ? 'gi' : 'g' + ); + else if ( !query.global ) + query = new RegExp(query.source, query.ignoreCase ? 'gi' : 'g'); + + return { + token: function(stream) { + query.lastIndex = stream.pos; + const match = query.exec(stream.string); + if ( match && match.index === stream.pos ) { + stream.pos += match[0].length || 1; + return 'searching'; + } else if ( match ) { + stream.pos = match.index; + } else { + stream.skipToEnd(); + } + } + }; + }; + + const searchWidgetKeydownHandler = function(cm, ev) { + const keyName = CodeMirror.keyName(ev); + if ( !keyName ) { return; } + CodeMirror.lookupKey( + keyName, + cm.getOption('keyMap'), + function(command) { + if ( widgetCommandHandler(cm, command) ) { + ev.preventDefault(); + ev.stopPropagation(); + } + } + ); + }; + + const searchWidgetInputHandler = function(cm, ev) { + const state = getSearchState(cm); + if ( ev.isTrusted !== true ) { + if ( state.queryText === '' ) { + clearSearch(cm); + } else { + cm.operation(function() { + startSearch(cm, state); + }); + } + return; + } + if ( queryTextFromSearchWidget(cm) === state.queryText ) { return; } + state.queryTimer.offon(350); + }; + + const searchWidgetClickHandler = function(cm, ev) { + const tcl = ev.target.classList; + if ( tcl.contains('cm-search-widget-up') ) { + findNext(cm, -1); + } else if ( tcl.contains('cm-search-widget-down') ) { + findNext(cm, 1); + } else if ( tcl.contains('cm-linter-widget-up') ) { + findNextError(cm, -1); + } else if ( tcl.contains('cm-linter-widget-down') ) { + findNextError(cm, 1); + } + if ( ev.target.localName !== 'input' ) { + ev.preventDefault(); + } else { + ev.stopImmediatePropagation(); + } + }; + + const queryTextFromSearchWidget = function(cm) { + return getSearchState(cm).widget.querySelector('input[type="search"]').value; + }; + + const queryTextToSearchWidget = function(cm, q) { + const input = getSearchState(cm).widget.querySelector('input[type="search"]'); + if ( typeof q === 'string' && q !== input.value ) { + input.value = q; + } + input.setSelectionRange(0, input.value.length); + input.focus(); + }; + + const SearchState = function(cm) { + this.query = null; + this.panel = null; + const widgetParent = document.querySelector('.cm-search-widget-template').cloneNode(true); + this.widget = widgetParent.children[0]; + this.widget.addEventListener('keydown', searchWidgetKeydownHandler.bind(null, cm)); + this.widget.addEventListener('input', searchWidgetInputHandler.bind(null, cm)); + this.widget.addEventListener('mousedown', searchWidgetClickHandler.bind(null, cm)); + if ( typeof cm.addPanel === 'function' ) { + this.panel = cm.addPanel(this.widget); + } + this.queryText = ''; + this.dirty = true; + this.lines = []; + cm.on('changes', (cm, changes) => { + for ( const change of changes ) { + if ( change.text.length !== 0 || change.removed !== 0 ) { + this.dirty = true; + break; + } + } + }); + cm.on('cursorActivity', cm => { + updateCount(cm); + }); + this.queryTimer = vAPI.defer.create(( ) => { + findCommit(cm, 0); + }); + }; + + // We want the search widget to behave as if the focus was on the + // CodeMirror editor. + + const reSearchCommands = /^(?:find|findNext|findPrev|newlineAndIndent)$/; + + const widgetCommandHandler = function(cm, command) { + if ( reSearchCommands.test(command) === false ) { return false; } + const queryText = queryTextFromSearchWidget(cm); + if ( command === 'find' ) { + queryTextToSearchWidget(cm); + return true; + } + if ( queryText.length !== 0 ) { + findNext(cm, command === 'findPrev' ? -1 : 1); + } + return true; + }; + + const getSearchState = function(cm) { + return cm.state.search || (cm.state.search = new SearchState(cm)); + }; + + const queryCaseInsensitive = function(query) { + return typeof query === 'string' && query === query.toLowerCase(); + }; + + // Heuristic: if the query string is all lowercase, do a case insensitive search. + const getSearchCursor = function(cm, query, pos) { + return cm.getSearchCursor( + query, + pos, + { caseFold: queryCaseInsensitive(query), multiline: false } + ); + }; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/658 + // Modified to backslash-escape ONLY widely-used control characters. + const parseString = function(string) { + return string.replace(/\\[nrt\\]/g, match => { + if ( match === '\\n' ) { return '\n'; } + if ( match === '\\r' ) { return '\r'; } + if ( match === '\\t' ) { return '\t'; } + if ( match === '\\\\' ) { return '\\'; } + return match; + }); + }; + + const reEscape = /[.*+\-?^${}()|[\]\\]/g; + + // Must always return a RegExp object. + // + // Assume case-sensitivity if there is at least one uppercase in plain + // query text. + const parseQuery = function(query) { + let flags = 'i'; + let reParsed = query.match(/^\/(.+)\/([iu]*)$/); + if ( reParsed !== null ) { + try { + const re = new RegExp(reParsed[1], reParsed[2]); + query = re.source; + flags = re.flags; + } + catch (e) { + reParsed = null; + } + } + if ( reParsed === null ) { + if ( /[A-Z]/.test(query) ) { flags = ''; } + query = parseString(query).replace(reEscape, '\\$&'); + } + if ( typeof query === 'string' ? query === '' : query.test('') ) { + query = 'x^'; + } + return new RegExp(query, 'gm' + flags); + }; + + let intlNumberFormat; + + const formatNumber = function(n) { + if ( intlNumberFormat === undefined ) { + intlNumberFormat = null; + if ( Intl.NumberFormat instanceof Function ) { + const intl = new Intl.NumberFormat(undefined, { + notation: 'compact', + maximumSignificantDigits: 3 + }); + if ( + intl.resolvedOptions instanceof Function && + intl.resolvedOptions().hasOwnProperty('notation') + ) { + intlNumberFormat = intl; + } + } + } + return n > 10000 && intlNumberFormat instanceof Object + ? intlNumberFormat.format(n) + : n.toLocaleString(); + }; + + const updateCount = function(cm) { + const state = getSearchState(cm); + const lines = state.lines; + const current = cm.getCursor().line; + let l = 0; + let r = lines.length; + let i = -1; + while ( l < r ) { + i = l + r >>> 1; + const candidate = lines[i]; + if ( current === candidate ) { break; } + if ( current < candidate ) { + r = i; + } else /* if ( current > candidate ) */ { + l = i + 1; + } + } + let text = ''; + if ( i !== -1 ) { + text = formatNumber(i + 1); + if ( lines[i] !== current ) { + text = '~' + text; + } + text = text + '\xA0/\xA0'; + } + const count = lines.length; + text += formatNumber(count); + const span = state.widget.querySelector('.cm-search-widget-count'); + span.textContent = text; + span.title = count.toLocaleString(); + }; + + const startSearch = function(cm, state) { + state.query = parseQuery(state.queryText); + if ( state.overlay !== undefined ) { + cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); + } + state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); + cm.addOverlay(state.overlay); + if ( state.dirty || self.searchThread.needHaystack() ) { + self.searchThread.setHaystack(cm.getValue()); + state.dirty = false; + } + self.searchThread.search(state.query).then(lines => { + if ( Array.isArray(lines) === false ) { return; } + state.lines = lines; + const count = lines.length; + updateCount(cm); + if ( state.annotate !== undefined ) { + state.annotate.clear(); + state.annotate = undefined; + } + if ( count === 0 ) { return; } + state.annotate = cm.annotateScrollbar('CodeMirror-search-match'); + const annotations = []; + let lineBeg = -1; + let lineEnd = -1; + for ( const line of lines ) { + if ( lineBeg === -1 ) { + lineBeg = line; + lineEnd = line + 1; + continue; + } else if ( line === lineEnd ) { + lineEnd = line + 1; + continue; + } + annotations.push({ + from: { line: lineBeg, ch: 0 }, + to: { line: lineEnd, ch: 0 } + }); + lineBeg = -1; + } + if ( lineBeg !== -1 ) { + annotations.push({ + from: { line: lineBeg, ch: 0 }, + to: { line: lineEnd, ch: 0 } + }); + } + state.annotate.update(annotations); + }); + state.widget.setAttribute('data-query', state.queryText); + // Ensure the caret is visible + const input = state.widget.querySelector('.cm-search-widget-input input'); + input.selectionStart = input.selectionStart; + }; + + const findNext = function(cm, dir, callback) { + cm.operation(function() { + const state = getSearchState(cm); + if ( !state.query ) { return; } + let cursor = getSearchCursor( + cm, + state.query, + dir <= 0 ? cm.getCursor('from') : cm.getCursor('to') + ); + const previous = dir < 0; + if (!cursor.find(previous)) { + cursor = getSearchCursor( + cm, + state.query, + previous + ? CodeMirror.Pos(cm.lastLine()) + : CodeMirror.Pos(cm.firstLine(), 0) + ); + if (!cursor.find(previous)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + const { clientHeight } = cm.getScrollInfo(); + cm.scrollIntoView( + { from: cursor.from(), to: cursor.to() }, + clientHeight >>> 1 + ); + if (callback) callback(cursor.from(), cursor.to()); + }); + }; + + const findNextError = function(cm, dir) { + const doc = cm.getDoc(); + const cursor = cm.getCursor('from'); + const cursorLine = cursor.line; + const start = dir < 0 ? 0 : cursorLine + 1; + const end = dir < 0 ? cursorLine : doc.lineCount(); + let found = -1; + doc.eachLine(start, end, lineHandle => { + const markers = lineHandle.gutterMarkers || null; + if ( markers === null ) { return; } + const marker = markers['CodeMirror-lintgutter']; + if ( marker === undefined ) { return; } + if ( marker.dataset.error !== 'y' ) { return; } + const line = lineHandle.lineNo(); + if ( dir < 0 ) { + found = line; + return; + } + found = line; + return true; + }); + if ( found === -1 || found === cursorLine ) { return; } + cm.getDoc().setCursor(found); + const { clientHeight } = cm.getScrollInfo(); + cm.scrollIntoView({ line: found, ch: 0 }, clientHeight >>> 1); + }; + + const clearSearch = function(cm, hard) { + cm.operation(function() { + const state = getSearchState(cm); + if ( state.query ) { + state.query = state.queryText = null; + } + state.lines = []; + if ( state.overlay !== undefined ) { + cm.removeOverlay(state.overlay); + state.overlay = undefined; + } + if ( state.annotate ) { + state.annotate.clear(); + state.annotate = undefined; + } + state.widget.removeAttribute('data-query'); + if ( hard ) { + state.panel.clear(); + state.panel = null; + state.widget = null; + cm.state.search = null; + } + }); + }; + + const findCommit = function(cm, dir) { + const state = getSearchState(cm); + state.queryTimer.off(); + const queryText = queryTextFromSearchWidget(cm); + if ( queryText === state.queryText ) { return; } + state.queryText = queryText; + if ( state.queryText === '' ) { + clearSearch(cm); + } else { + cm.operation(function() { + startSearch(cm, state); + findNext(cm, dir); + }); + } + }; + + const findCommand = function(cm) { + let queryText = cm.getSelection() || undefined; + if ( !queryText ) { + const word = cm.findWordAt(cm.getCursor()); + queryText = cm.getRange(word.anchor, word.head); + if ( /^\W|\W$/.test(queryText) ) { + queryText = undefined; + } + cm.setCursor(word.anchor); + } + queryTextToSearchWidget(cm, queryText); + findCommit(cm, 1); + }; + + const findNextCommand = function(cm) { + const state = getSearchState(cm); + if ( state.query ) { return findNext(cm, 1); } + }; + + const findPrevCommand = function(cm) { + const state = getSearchState(cm); + if ( state.query ) { return findNext(cm, -1); } + }; + + { + const searchWidgetTemplate = + ''; + const domParser = new DOMParser(); + const doc = domParser.parseFromString(searchWidgetTemplate, 'text/html'); + const widgetTemplate = document.adoptNode(doc.body.firstElementChild); + document.body.appendChild(widgetTemplate); + } + + CodeMirror.commands.find = findCommand; + CodeMirror.commands.findNext = findNextCommand; + CodeMirror.commands.findPrev = findPrevCommand; + + CodeMirror.defineInitHook(function(cm) { + getSearchState(cm); + cm.on('linterDone', details => { + const linterWidget = qs$('.cm-linter-widget'); + const count = details.errorCount; + if ( linterWidget.dataset.lint === `${count}` ) { return; } + linterWidget.dataset.lint = `${count}`; + dom.text( + qs$(linterWidget, '.cm-linter-widget-count'), + i18n$('linterMainReport').replace('{{count}}', count.toLocaleString()) + ); + }); + }); +} diff --git a/src/js/codemirror/ubo-dynamic-filtering.js b/src/js/codemirror/ubo-dynamic-filtering.js new file mode 100644 index 0000000..d0709a4 --- /dev/null +++ b/src/js/codemirror/ubo-dynamic-filtering.js @@ -0,0 +1,239 @@ +/******************************************************************************* + + 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 +*/ + +/* global CodeMirror */ + +'use strict'; + +CodeMirror.defineMode('ubo-dynamic-filtering', ( ) => { + + const validSwitches = new Set([ + 'no-strict-blocking:', + 'no-popups:', + 'no-cosmetic-filtering:', + 'no-remote-fonts:', + 'no-large-media:', + 'no-csp-reports:', + 'no-scripting:', + ]); + const validSwitcheStates = new Set([ + 'true', + 'false', + ]); + const validHnRuleTypes = new Set([ + '*', + '3p', + 'image', + 'inline-script', + '1p-script', + '3p-script', + '3p-frame', + ]); + const invalidURLRuleTypes = new Set([ + 'doc', + 'main_frame', + ]); + const validActions = new Set([ + 'block', + 'allow', + 'noop', + ]); + const hnValidator = new URL(self.location.href); + const reBadHn = /[%]|^\.|\.$/; + const slices = []; + let sliceIndex = 0; + let sliceCount = 0; + let hostnameToDomainMap = new Map(); + let psl; + + const isValidHostname = hnin => { + if ( hnin === '*' ) { return true; } + hnValidator.hostname = '_'; + try { + hnValidator.hostname = hnin; + } catch(_) { + return false; + } + const hnout = hnValidator.hostname; + return hnout !== '_' && hnout !== '' && reBadHn.test(hnout) === false; + }; + + const addSlice = (len, style = null) => { + let i = sliceCount; + if ( i === slices.length ) { + slices[i] = { len: 0, style: null }; + } + const entry = slices[i]; + entry.len = len; + entry.style = style; + sliceCount += 1; + }; + + const addMatchSlice = (match, style = null) => { + const len = match !== null ? match[0].length : 0; + addSlice(len, style); + return match !== null ? match.input.slice(len) : ''; + }; + + const addMatchHnSlices = (match, style = null) => { + const hn = match[0]; + if ( hn === '*' ) { + return addMatchSlice(match, style); + } + let dn = hostnameToDomainMap.get(hn) || ''; + if ( dn === '' && psl !== undefined ) { + dn = /(\d|\])$/.test(hn) ? hn : (psl.getDomain(hn) || hn); + } + const entityBeg = hn.length - dn.length; + if ( entityBeg !== 0 ) { + addSlice(entityBeg, style); + } + let entityEnd = dn.indexOf('.'); + if ( entityEnd === -1 ) { entityEnd = dn.length; } + addSlice(entityEnd, style !== null ? `${style} strong` : 'strong'); + if ( entityEnd < dn.length ) { + addSlice(dn.length - entityEnd, style); + } + return match.input.slice(hn.length); + }; + + const makeSlices = (stream, opts) => { + sliceIndex = 0; + sliceCount = 0; + let { string } = stream; + if ( string === '...' ) { return; } + const { sortType } = opts; + const reNotToken = /^\s+/; + const reToken = /^\S+/; + const tokens = []; + // leading whitespaces + let match = reNotToken.exec(string); + if ( match !== null ) { + string = addMatchSlice(match); + } + // first token + match = reToken.exec(string); + if ( match === null ) { return; } + tokens.push(match[0]); + // hostname or switch + const isSwitchRule = validSwitches.has(match[0]); + if ( isSwitchRule ) { + string = addMatchSlice(match, sortType === 0 ? 'sortkey' : null); + } else if ( isValidHostname(match[0]) ) { + if ( sortType === 1 ) { + string = addMatchHnSlices(match, 'sortkey'); + } else { + string = addMatchHnSlices(match, null); + } + } else { + string = addMatchSlice(match, 'error'); + } + // whitespaces before second token + match = reNotToken.exec(string); + if ( match === null ) { return; } + string = addMatchSlice(match); + // second token + match = reToken.exec(string); + if ( match === null ) { return; } + tokens.push(match[0]); + // hostname or url + const isURLRule = isSwitchRule === false && match[0].indexOf('://') > 0; + if ( isURLRule ) { + string = addMatchSlice(match, sortType === 2 ? 'sortkey' : null); + } else if ( isValidHostname(match[0]) === false ) { + string = addMatchSlice(match, 'error'); + } else if ( sortType === 1 && isSwitchRule || sortType === 2 ) { + string = addMatchHnSlices(match, 'sortkey'); + } else { + string = addMatchHnSlices(match, null); + } + // whitespaces before third token + match = reNotToken.exec(string); + if ( match === null ) { return; } + string = addMatchSlice(match); + // third token + match = reToken.exec(string); + if ( match === null ) { return; } + tokens.push(match[0]); + // rule type or switch state + if ( isSwitchRule ) { + string = validSwitcheStates.has(match[0]) + ? addMatchSlice(match, match[0] === 'true' ? 'blockrule' : 'allowrule') + : addMatchSlice(match, 'error'); + } else if ( isURLRule ) { + string = invalidURLRuleTypes.has(match[0]) + ? addMatchSlice(match, 'error') + : addMatchSlice(match); + } else if ( tokens[1] === '*' ) { + string = validHnRuleTypes.has(match[0]) + ? addMatchSlice(match) + : addMatchSlice(match, 'error'); + } else { + string = match[0] === '*' + ? addMatchSlice(match) + : addMatchSlice(match, 'error'); + } + // whitespaces before fourth token + match = reNotToken.exec(string); + if ( match === null ) { return; } + string = addMatchSlice(match); + // fourth token + match = reToken.exec(string); + if ( match === null ) { return; } + tokens.push(match[0]); + string = isSwitchRule || validActions.has(match[0]) === false + ? addMatchSlice(match, 'error') + : addMatchSlice(match, `${match[0]}rule`); + // whitespaces before end of line + match = reNotToken.exec(string); + if ( match === null ) { return; } + string = addMatchSlice(match); + // any token beyond fourth token is invalid + match = reToken.exec(string); + if ( match !== null ) { + string = addMatchSlice(null, 'error'); + } + }; + + const token = function(stream) { + if ( stream.sol() ) { + makeSlices(stream, this); + } + if ( sliceIndex >= sliceCount ) { + stream.skipToEnd(stream); + return null; + } + const { len, style } = slices[sliceIndex++]; + if ( len === 0 ) { + stream.skipToEnd(); + } else { + stream.pos += len; + } + return style; + }; + + return { + token, + sortType: 1, + setHostnameToDomainMap: a => { hostnameToDomainMap = a; }, + setPSL: a => { psl = a; }, + }; +}); diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js new file mode 100644 index 0000000..ac1b048 --- /dev/null +++ b/src/js/codemirror/ubo-static-filtering.js @@ -0,0 +1,1200 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2018-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 +*/ + +/* global CodeMirror */ + +'use strict'; + +/******************************************************************************/ + +import * as sfp from '../static-filtering-parser.js'; +import { dom, qs$ } from '../dom.js'; + +/******************************************************************************/ + +const redirectNames = new Map(); +const scriptletNames = new Map(); +const preparseDirectiveEnv = []; +const preparseDirectiveHints = []; +const originHints = []; +let hintHelperRegistered = false; + +/******************************************************************************/ + +CodeMirror.defineOption('trustedSource', false, (cm, state) => { + if ( typeof state !== 'boolean' ) { return; } + self.dispatchEvent(new CustomEvent('trustedSource', { + detail: state, + })); +}); + +CodeMirror.defineOption('trustedScriptletTokens', undefined, (cm, tokens) => { + if ( tokens === undefined || tokens === null ) { return; } + if ( typeof tokens[Symbol.iterator] !== 'function' ) { return; } + self.dispatchEvent(new CustomEvent('trustedScriptletTokens', { + detail: new Set(tokens), + })); +}); + +/******************************************************************************/ + +CodeMirror.defineMode('ubo-static-filtering', function() { + const astParser = new sfp.AstFilterParser({ + interactive: true, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); + const astWalker = astParser.getWalker(); + let currentWalkerNode = 0; + let lastNetOptionType = 0; + + const redirectTokenStyle = node => { + const rawToken = astParser.getNodeString(node || currentWalkerNode); + const { token } = sfp.parseRedirectValue(rawToken); + return redirectNames.has(token) ? 'value' : 'value warning'; + }; + + const nodeHasError = node => { + return astParser.getNodeFlags( + node || currentWalkerNode, sfp.NODE_FLAG_ERROR + ) !== 0; + }; + + const colorFromAstNode = function() { + if ( astParser.nodeIsEmptyString(currentWalkerNode) ) { return '+'; } + if ( nodeHasError() ) { return 'error'; } + const nodeType = astParser.getNodeType(currentWalkerNode); + switch ( nodeType ) { + case sfp.NODE_TYPE_WHITESPACE: + return ''; + case sfp.NODE_TYPE_COMMENT: + if ( astWalker.canGoDown() ) { break; } + return 'comment'; + case sfp.NODE_TYPE_COMMENT_URL: + return 'comment link'; + case sfp.NODE_TYPE_IGNORE: + return 'comment'; + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE: + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_VALUE: + return 'directive'; + case sfp.NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE: { + const raw = astParser.getNodeString(currentWalkerNode); + const state = sfp.utils.preparser.evaluateExpr(raw, preparseDirectiveEnv); + return state ? 'positive strong' : 'negative strong'; + } + case sfp.NODE_TYPE_EXT_OPTIONS_ANCHOR: + return astParser.getFlags(sfp.AST_FLAG_IS_EXCEPTION) + ? 'tag strong' + : 'def strong'; + case sfp.NODE_TYPE_EXT_DECORATION: + return 'def'; + case sfp.NODE_TYPE_EXT_PATTERN_RAW: + if ( astWalker.canGoDown() ) { break; } + return 'variable'; + case sfp.NODE_TYPE_EXT_PATTERN_COSMETIC: + case sfp.NODE_TYPE_EXT_PATTERN_HTML: + return 'variable'; + case sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER: + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET: + if ( astWalker.canGoDown() ) { break; } + return 'variable'; + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: { + const token = astParser.getNodeString(currentWalkerNode); + if ( scriptletNames.has(token) === false ) { + return 'warning'; + } + return 'variable'; + } + case sfp.NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG: + return 'variable'; + case sfp.NODE_TYPE_NET_EXCEPTION: + return 'tag strong'; + case sfp.NODE_TYPE_NET_PATTERN: + if ( astWalker.canGoDown() ) { break; } + if ( astParser.isRegexPattern() ) { + if ( astParser.getNodeFlags(currentWalkerNode, sfp.NODE_FLAG_PATTERN_UNTOKENIZABLE) !== 0 ) { + return 'variable warning'; + } + return 'variable notice'; + } + return 'variable'; + case sfp.NODE_TYPE_NET_PATTERN_PART: + return 'variable'; + case sfp.NODE_TYPE_NET_PATTERN_PART_SPECIAL: + return 'keyword strong'; + case sfp.NODE_TYPE_NET_PATTERN_PART_UNICODE: + return 'variable 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 'keyword strong'; + case sfp.NODE_TYPE_NET_OPTIONS_ANCHOR: + case sfp.NODE_TYPE_NET_OPTION_SEPARATOR: + lastNetOptionType = 0; + return 'def strong'; + case sfp.NODE_TYPE_NET_OPTION_NAME_UNKNOWN: + lastNetOptionType = 0; + return '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_HEADER: + 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_SCRIPT: + case sfp.NODE_TYPE_NET_OPTION_NAME_SHIDE: + case sfp.NODE_TYPE_NET_OPTION_NAME_TO: + case sfp.NODE_TYPE_NET_OPTION_NAME_XHR: + case sfp.NODE_TYPE_NET_OPTION_NAME_WEBRTC: + case sfp.NODE_TYPE_NET_OPTION_NAME_WEBSOCKET: + lastNetOptionType = nodeType; + return 'def'; + case sfp.NODE_TYPE_NET_OPTION_ASSIGN: + return 'def'; + case sfp.NODE_TYPE_NET_OPTION_VALUE: + if ( astWalker.canGoDown() ) { break; } + switch ( lastNetOptionType ) { + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECT: + case sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE: + return redirectTokenStyle(); + default: + break; + } + return 'value'; + case sfp.NODE_TYPE_OPTION_VALUE_NOT: + return 'keyword strong'; + case sfp.NODE_TYPE_OPTION_VALUE_DOMAIN: + return 'value'; + case sfp.NODE_TYPE_OPTION_VALUE_SEPARATOR: + return 'def'; + default: + break; + } + return '+'; + }; + + self.addEventListener('trustedSource', ev => { + astParser.options.trustedSource = ev.detail; + }); + + self.addEventListener('trustedScriptletTokens', ev => { + astParser.options.trustedScriptletTokens = ev.detail; + }); + + return { + lineComment: '!', + token: function(stream) { + if ( stream.sol() ) { + astParser.parse(stream.string); + if ( astParser.getFlags(sfp.AST_FLAG_UNSUPPORTED) !== 0 ) { + stream.skipToEnd(); + return 'error'; + } + if ( astParser.getType() === sfp.AST_TYPE_NONE ) { + stream.skipToEnd(); + return 'comment'; + } + currentWalkerNode = astWalker.reset(); + } else if ( nodeHasError() ) { + currentWalkerNode = astWalker.right(); + } else { + currentWalkerNode = astWalker.next(); + } + let style = ''; + while ( currentWalkerNode !== 0 ) { + style = colorFromAstNode(stream); + if ( style !== '+' ) { break; } + currentWalkerNode = astWalker.next(); + } + if ( style === '+' ) { + stream.skipToEnd(); + return null; + } + stream.pos = astParser.getNodeStringEnd(currentWalkerNode); + if ( astParser.isNetworkFilter() ) { + return style ? `line-cm-net ${style}` : 'line-cm-net'; + } + if ( astParser.isExtendedFilter() ) { + let flavor = ''; + if ( astParser.isCosmeticFilter() ) { + flavor = 'line-cm-ext-dom'; + } else if ( astParser.isScriptletFilter() ) { + flavor = 'line-cm-ext-js'; + } else if ( astParser.isHtmlFilter() ) { + flavor = 'line-cm-ext-html'; + } + if ( flavor !== '' ) { + style = `${flavor} ${style}`; + } + } + style = style.trim(); + return style !== '' ? style : null; + }, + parser: astParser, + }; +}); + +/******************************************************************************/ + +// Following code is for auto-completion. Reference: +// https://codemirror.net/demo/complete.html + +CodeMirror.defineOption('uboHints', null, (cm, hints) => { + if ( hints instanceof Object === false ) { return; } + if ( Array.isArray(hints.redirectResources) ) { + for ( const [ name, desc ] of hints.redirectResources ) { + const displayText = desc.aliasOf !== '' + ? `${name} (${desc.aliasOf})` + : ''; + if ( desc.canRedirect ) { + redirectNames.set(name, displayText); + } + if ( desc.canInject && name.endsWith('.js') ) { + scriptletNames.set(name.slice(0, -3), displayText); + } + } + } + if ( Array.isArray(hints.preparseDirectiveEnv)) { + preparseDirectiveEnv.length = 0; + preparseDirectiveEnv.push(...hints.preparseDirectiveEnv); + } + if ( Array.isArray(hints.preparseDirectiveHints)) { + preparseDirectiveHints.push(...hints.preparseDirectiveHints); + } + if ( Array.isArray(hints.originHints) ) { + originHints.length = 0; + for ( const hint of hints.originHints ) { + originHints.push(hint); + } + } + if ( hintHelperRegistered ) { return; } + hintHelperRegistered = true; + initHints(); +}); + +function initHints() { + const astParser = new sfp.AstFilterParser({ + interactive: true, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); + const proceduralOperatorNames = new Map( + Array.from(sfp.proceduralOperatorTokens) + .filter(item => (item[1] & 0b01) !== 0) + ); + const excludedHints = new Set([ + 'genericblock', + 'object-subrequest', + 'rewrite', + 'webrtc', + ]); + + const pickBestHints = function(cursor, seedLeft, seedRight, hints) { + const seed = (seedLeft + seedRight).trim(); + const out = []; + // First, compare against whole seed + for ( const hint of hints ) { + const text = hint instanceof Object + ? hint.displayText || hint.text + : hint; + if ( text.startsWith(seed) === false ) { continue; } + out.push(hint); + } + if ( out.length !== 0 ) { + return { + from: { line: cursor.line, ch: cursor.ch - seedLeft.length }, + to: { line: cursor.line, ch: cursor.ch + seedRight.length }, + list: out, + }; + } + // If no match, try again with a different heuristic: valid hints are + // those matching left seed, not matching right seed but right seed is + // found to be a valid hint. This is to take care of cases like: + // + // *$script,redomain=example.org + // ^ + // + cursor position + // + // In such case, [ redirect=, redirect-rule= ] should be returned + // as valid hints. + for ( const hint of hints ) { + const text = hint instanceof Object + ? hint.displayText || hint.text + : hint; + if ( seedLeft.length === 0 ) { continue; } + if ( text.startsWith(seedLeft) === false ) { continue; } + if ( hints.includes(seedRight) === false ) { continue; } + out.push(hint); + } + if ( out.length !== 0 ) { + return { + from: { line: cursor.line, ch: cursor.ch - seedLeft.length }, + to: { line: cursor.line, ch: cursor.ch }, + list: out, + }; + } + // If no match, try again with a different heuristic: valid hints are + // those containing seed as a substring. This is to take care of cases + // like: + // + // *$script,redirect=gif + // ^ + // + cursor position + // + // In such case, [ 1x1.gif, 1x1-transparent.gif ] should be returned + // as valid hints. + for ( const hint of hints ) { + const text = hint instanceof Object + ? hint.displayText || hint.text + : hint; + if ( seedLeft.length === 1 ) { + if ( text.startsWith(seedLeft) === false ) { continue; } + } else if ( text.includes(seed) === false ) { continue; } + out.push(hint); + } + if ( out.length !== 0 ) { + return { + from: { line: cursor.line, ch: cursor.ch - seedLeft.length }, + to: { line: cursor.line, ch: cursor.ch + seedRight.length }, + list: out, + }; + } + // If still no match, try again with a different heuristic: valid hints + // are those containing left seed as a substring. This is to take care + // of cases like: + // + // *$script,redirect=gifdomain=example.org + // ^ + // + cursor position + // + // In such case, [ 1x1.gif, 1x1-transparent.gif ] should be returned + // as valid hints. + for ( const hint of hints ) { + const text = hint instanceof Object + ? hint.displayText || hint.text + : hint; + if ( text.includes(seedLeft) === false ) { continue; } + out.push(hint); + } + if ( out.length !== 0 ) { + return { + from: { line: cursor.line, ch: cursor.ch - seedLeft.length }, + to: { line: cursor.line, ch: cursor.ch }, + list: out, + }; + } + }; + + const getOriginHints = function(cursor, line, suffix = '') { + const beg = cursor.ch; + const matchLeft = /[^,|=~]*$/.exec(line.slice(0, beg)); + const matchRight = /^[^#,|]*/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + const hints = []; + for ( const text of originHints ) { + hints.push(text + suffix); + } + return pickBestHints(cursor, matchLeft[0], matchRight[0], hints); + }; + + const getNetPatternHints = function(cursor, line) { + if ( /\|\|[\w.-]*$/.test(line.slice(0, cursor.ch)) ) { + return getOriginHints(cursor, line, '^'); + } + // Maybe a static extended filter is meant to be crafted. + if ( /[^\w\x80-\xF4#,.-]/.test(line) === false ) { + return getOriginHints(cursor, line); + } + }; + + const getNetOptionHints = function(cursor, seedLeft, seedRight) { + const isNegated = seedLeft.startsWith('~'); + if ( isNegated ) { + seedLeft = seedLeft.slice(1); + } + const assignPos = seedRight.indexOf('='); + if ( assignPos !== -1 ) { seedRight = seedRight.slice(0, assignPos); } + const isException = astParser.isException(); + const hints = []; + for ( let [ text, desc ] of sfp.netOptionTokenDescriptors ) { + if ( excludedHints.has(text) ) { continue; } + if ( isNegated && desc.canNegate !== true ) { continue; } + if ( isException ) { + if ( desc.blockOnly ) { continue; } + } else { + if ( desc.allowOnly ) { continue; } + if ( (assignPos === -1) && desc.mustAssign ) { + text += '='; + } + } + hints.push(text); + } + return pickBestHints(cursor, seedLeft, seedRight, hints); + }; + + const getNetRedirectHints = function(cursor, seedLeft, seedRight) { + const hints = []; + for ( const text of redirectNames.keys() ) { + if ( text.startsWith('abp-resource:') ) { continue; } + hints.push(text); + } + return pickBestHints(cursor, seedLeft, seedRight, hints); + }; + + const getNetHints = function(cursor, line) { + const patternNode = astParser.getBranchFromType(sfp.NODE_TYPE_NET_PATTERN_RAW); + if ( patternNode === 0 ) { return; } + const patternEnd = astParser.getNodeStringEnd(patternNode); + const beg = cursor.ch; + if ( beg <= patternEnd ) { + return getNetPatternHints(cursor, line); + } + const lineBefore = line.slice(0, beg); + const lineAfter = line.slice(beg); + let matchLeft = /[^$,]*$/.exec(lineBefore); + let matchRight = /^[^,]*/.exec(lineAfter); + if ( matchLeft === null || matchRight === null ) { return; } + const assignPos = matchLeft[0].indexOf('='); + if ( assignPos === -1 ) { + return getNetOptionHints(cursor, matchLeft[0], matchRight[0]); + } + if ( /^(redirect(-rule)?|rewrite)=/.test(matchLeft[0]) ) { + return getNetRedirectHints( + cursor, + matchLeft[0].slice(assignPos + 1), + matchRight[0] + ); + } + if ( /^(domain|from)=/.test(matchLeft[0]) ) { + return getOriginHints(cursor, line); + } + }; + + const getExtSelectorHints = function(cursor, line) { + const beg = cursor.ch; + // Special selector case: `^responseheader` + { + const match = /#\^([a-z]+)$/.exec(line.slice(0, beg)); + if ( + match !== null && + 'responseheader'.startsWith(match[1]) && + line.slice(beg) === '' + ) { + return pickBestHints( + cursor, + match[1], + '', + [ 'responseheader()' ] + ); + } + } + // Procedural operators + const matchLeft = /#\^?.*:([^:]*)$/.exec(line.slice(0, beg)); + const matchRight = /^([a-z-]*)\(?/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + const isStaticDOM = matchLeft[0].indexOf('^') !== -1; + const hints = []; + for ( let [ text, bits ] of proceduralOperatorNames ) { + if ( isStaticDOM && (bits & 0b10) !== 0 ) { continue; } + hints.push(text); + } + return pickBestHints(cursor, matchLeft[1], matchRight[1], hints); + }; + + const getExtHeaderHints = function(cursor, line) { + const beg = cursor.ch; + const matchLeft = /#\^responseheader\((.*)$/.exec(line.slice(0, beg)); + const matchRight = /^([^)]*)/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + const hints = []; + for ( const hint of sfp.removableHTTPHeaders ) { + hints.push(hint); + } + return pickBestHints(cursor, matchLeft[1], matchRight[1], hints); + }; + + const getExtScriptletHints = function(cursor, line) { + const beg = cursor.ch; + const matchLeft = /#\+\js\(([^,]*)$/.exec(line.slice(0, beg)); + const matchRight = /^([^,)]*)/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + const hints = []; + for ( const [ text, displayText ] of scriptletNames ) { + const hint = { text }; + if ( displayText !== '' ) { + hint.displayText = displayText; + } + hints.push(hint); + } + return pickBestHints(cursor, matchLeft[1], matchRight[1], hints); + }; + + const getCommentHints = function(cursor, line) { + const beg = cursor.ch; + if ( line.startsWith('!#if ') ) { + const matchLeft = /^!#if !?(\w*)$/.exec(line.slice(0, beg)); + const matchRight = /^\w*/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + return pickBestHints( + cursor, + matchLeft[1], + matchRight[0], + preparseDirectiveHints + ); + } + if ( line.startsWith('!#') && line !== '!#endif' ) { + const matchLeft = /^!#(\w*)$/.exec(line.slice(0, beg)); + const matchRight = /^\w*/.exec(line.slice(beg)); + if ( matchLeft === null || matchRight === null ) { return; } + const hints = [ 'if ', 'endif\n', 'include ' ]; + return pickBestHints(cursor, matchLeft[1], matchRight[0], hints); + } + }; + + CodeMirror.registerHelper('hint', 'ubo-static-filtering', function(cm) { + const cursor = cm.getCursor(); + const line = cm.getLine(cursor.line); + astParser.parse(line); + if ( astParser.isExtendedFilter() ) { + const anchorNode = astParser.getBranchFromType(sfp.NODE_TYPE_EXT_OPTIONS_ANCHOR); + if ( anchorNode === 0 ) { return; } + let hints; + if ( cursor.ch <= astParser.getNodeStringBeg(anchorNode) ) { + hints = getOriginHints(cursor, line); + } else if ( astParser.isScriptletFilter() ) { + hints = getExtScriptletHints(cursor, line); + } else if ( astParser.isResponseheaderFilter() ) { + hints = getExtHeaderHints(cursor, line); + } else { + hints = getExtSelectorHints(cursor, line); + } + return hints; + } + if ( astParser.isNetworkFilter() ) { + return getNetHints(cursor, line); + } + if ( astParser.isComment() ) { + return getCommentHints(cursor, line); + } + return getOriginHints(cursor, line); + }); +} + +/******************************************************************************/ + +CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { + const foldIfEndif = function(startLineNo, startLine, cm) { + const lastLineNo = cm.lastLine(); + let endLineNo = startLineNo; + let depth = 1; + while ( endLineNo < lastLineNo ) { + endLineNo += 1; + const line = cm.getLine(endLineNo); + if ( line.startsWith('!#endif') ) { + depth -= 1; + if ( depth === 0 ) { + return { + from: CodeMirror.Pos(startLineNo, startLine.length), + to: CodeMirror.Pos(endLineNo, 0) + }; + } + } + if ( line.startsWith('!#if') ) { + depth += 1; + } + } + }; + + const foldInclude = function(startLineNo, startLine, cm) { + const lastLineNo = cm.lastLine(); + let endLineNo = startLineNo + 1; + if ( endLineNo >= lastLineNo ) { return; } + if ( cm.getLine(endLineNo).startsWith('! >>>>>>>> ') === false ) { + return; + } + while ( endLineNo < lastLineNo ) { + endLineNo += 1; + const line = cm.getLine(endLineNo); + if ( line.startsWith('! <<<<<<<< ') ) { + return { + from: CodeMirror.Pos(startLineNo, startLine.length), + to: CodeMirror.Pos(endLineNo, line.length) + }; + } + } + }; + + return function(cm, start) { + const startLineNo = start.line; + const startLine = cm.getLine(startLineNo); + if ( startLine.startsWith('!#if') ) { + return foldIfEndif(startLineNo, startLine, cm); + } + if ( startLine.startsWith('!#include ') ) { + return foldInclude(startLineNo, startLine, cm); + } + }; +})()); + +/******************************************************************************/ + +// Linter + +{ + const astParser = new sfp.AstFilterParser({ + interactive: true, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); + + const changeset = []; + let changesetTimer; + + const includeset = new Set(); + let errorCount = 0; + + const ifendifSet = new Set(); + let ifendifSetChanged = false; + + const extractMarkerDetails = (doc, lineHandle) => { + if ( astParser.isUnsupported() ) { + return { lint: 'error', msg: 'Unsupported filter syntax' }; + } + if ( astParser.hasError() ) { + let msg = 'Invalid filter'; + switch ( astParser.astError ) { + case sfp.AST_ERROR_UNSUPPORTED: + msg = `${msg}: Unsupported filter syntax`; + break; + case sfp.AST_ERROR_REGEX: + msg = `${msg}: Bad regular expression`; + break; + case sfp.AST_ERROR_PATTERN: + msg = `${msg}: Bad pattern`; + break; + case sfp.AST_ERROR_DOMAIN_NAME: + msg = `${msg}: Bad domain name`; + break; + case sfp.AST_ERROR_OPTION_BADVALUE: + msg = `${msg}: Bad value assigned to a valid option`; + break; + case sfp.AST_ERROR_OPTION_DUPLICATE: + msg = `${msg}: Duplicate filter option`; + break; + case sfp.AST_ERROR_OPTION_UNKNOWN: + msg = `${msg}: Unsupported filter option`; + break; + case sfp.AST_ERROR_IF_TOKEN_UNKNOWN: + msg = `${msg}: Unknown preparsing token`; + break; + case sfp.AST_ERROR_UNTRUSTED_SOURCE: + msg = `${msg}: Filter requires trusted source`; + break; + default: + if ( astParser.isCosmeticFilter() && astParser.result.error ) { + msg = `${msg}: ${astParser.result.error}`; + } + break; + } + return { lint: 'error', msg }; + } + if ( astParser.astType !== sfp.AST_TYPE_COMMENT ) { return; } + if ( astParser.astTypeFlavor !== sfp.AST_TYPE_COMMENT_PREPARSER ) { + if ( astParser.raw.startsWith('! <<<<<<<< ') === false ) { return; } + for ( const include of includeset ) { + if ( astParser.raw.endsWith(include) === false ) { continue; } + includeset.delete(include); + return { lint: 'include-end' }; + } + return; + } + if ( /^\s*!#if \S+/.test(astParser.raw) ) { + return { + lint: 'if-start', + data: { + state: sfp.utils.preparser.evaluateExpr( + astParser.getTypeString(sfp.NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE), + preparseDirectiveEnv + ) ? 'y' : 'n' + } + }; + } + if ( /^\s*!#endif\b/.test(astParser.raw) ) { + return { lint: 'if-end' }; + } + const match = /^\s*!#include\s*(\S+)/.exec(astParser.raw); + if ( match === null ) { return; } + const nextLineHandle = doc.getLineHandle(lineHandle.lineNo() + 1); + if ( nextLineHandle === undefined ) { return; } + if ( nextLineHandle.text.startsWith('! >>>>>>>> ') === false ) { return; } + const includeToken = `/${match[1]}`; + if ( nextLineHandle.text.endsWith(includeToken) === false ) { return; } + includeset.add(includeToken); + return { lint: 'include-start' }; + }; + + const extractMarker = lineHandle => { + const markers = lineHandle.gutterMarkers || null; + return markers !== null + ? markers['CodeMirror-lintgutter'] || null + : null; + }; + + const markerTemplates = { + 'error': { + node: null, + html: [ + '
 ', + '', + '
', + ], + }, + 'if-start': { + node: null, + html: [ + '
 ', + '', + '', + '', + 'Mismatched if-endif directive', + '
', + ], + }, + 'if-end': { + node: null, + html: [ + '
 ', + '', + '', + '', + 'Mismatched if-endif directive', + '
', + ], + }, + 'include-start': { + node: null, + html: [ + '
 ', + '', + '', + '', + '
', + ], + }, + 'include-end': { + node: null, + html: [ + '
 ', + '', + '', + '', + '
', + ], + }, + }; + + const markerFromTemplate = details => { + const template = markerTemplates[details.lint]; + if ( template.node === null ) { + const domParser = new DOMParser(); + const doc = domParser.parseFromString(template.html.join(''), 'text/html'); + template.node = document.adoptNode(qs$(doc, '.CodeMirror-lintmarker')); + } + const node = template.node.cloneNode(true); + if ( details.data instanceof Object ) { + for ( const [ k, v ] of Object.entries(details.data) ) { + node.dataset[k] = `${v}`; + } + } + return node; + }; + + const addMarker = (doc, lineHandle, marker, details) => { + if ( marker && marker.dataset.lint !== details.lint ) { + doc.setGutterMarker(lineHandle, 'CodeMirror-lintgutter', null); + if ( marker.dataset.error === 'y' ) { + errorCount -= 1; + } + if ( marker.dataset.lint === 'if' ) { + ifendifSet.delete(lineHandle); + ifendifSetChanged = true; + } + marker = null; + } + if ( marker === null ) { + marker = markerFromTemplate(details); + doc.setGutterMarker(lineHandle, 'CodeMirror-lintgutter', marker); + if ( marker.dataset.error === 'y' ) { + errorCount += 1; + } + if ( marker.dataset.lint === 'if' ) { + ifendifSet.add(lineHandle); + ifendifSetChanged = true; + } + } + if ( typeof details.msg !== 'string' || details.msg === '' ) { return; } + const msgElem = qs$(marker, '.msg'); + if ( msgElem === null ) { return; } + msgElem.textContent = details.msg; + }; + + const removeMarker = (doc, lineHandle, marker) => { + doc.setGutterMarker(lineHandle, 'CodeMirror-lintgutter', null); + if ( marker.dataset.error === 'y' ) { + errorCount -= 1; + } + if ( marker.dataset.lint === 'if' ) { + ifendifSet.delete(lineHandle); + ifendifSetChanged = true; + } + }; + + // Analyze whether all if-endif are properly paired + const processIfendifs = ( ) => { + if ( ifendifSet.size === 0 ) { return; } + if ( ifendifSetChanged !== true ) { return; } + const sortFn = (a, b) => a.lineNo() - b.lineNo(); + const sorted = Array.from(ifendifSet).sort(sortFn); + const bad = []; + const stack = []; + for ( const line of sorted ) { + const marker = extractMarker(line); + const fold = marker.dataset.fold; + if ( fold === 'start' ) { + stack.push(line); + } else if ( fold === 'end' ) { + if ( stack.length !== 0 ) { + if ( marker.dataset.error === 'y' ) { + marker.dataset.error = ''; + errorCount -= 1; + } + const ifstart = extractMarker(stack.pop()); + if ( ifstart.dataset.error === 'y' ) { + ifstart.dataset.error = ''; + errorCount -= 1; + } + } else { + bad.push(line); + } + } + } + bad.push(...stack); + for ( const line of bad ) { + const marker = extractMarker(line); + marker.dataset.error = 'y'; + errorCount += 1; + } + ifendifSetChanged = false; + }; + + const processDeletion = (doc, change) => { + let { from, to } = change; + doc.eachLine(from.line, to.line, lineHandle => { + const marker = extractMarker(lineHandle); + if ( marker === null ) { return; } + if ( marker.dataset.error === 'y' ) { + marker.dataset.error = ''; + errorCount -= 1; + } + ifendifSet.delete(lineHandle); + ifendifSetChanged = true; + }); + }; + + const processInsertion = (doc, deadline, change) => { + let { from, to } = change; + doc.eachLine(from, to, lineHandle => { + astParser.parse(lineHandle.text); + const markerDetails = extractMarkerDetails(doc, lineHandle); + const marker = extractMarker(lineHandle); + if ( markerDetails !== undefined ) { + addMarker(doc, lineHandle, marker, markerDetails); + } else if ( marker !== null ) { + removeMarker(doc, lineHandle, marker); + } + from += 1; + if ( (from & 0x0F) !== 0 ) { return; } + if ( deadline.timeRemaining() !== 0 ) { return; } + return true; + }); + if ( from !== to ) { + return { from, to }; + } + }; + + const processChangeset = (doc, deadline) => { + const cm = doc.getEditor(); + cm.startOperation(); + while ( changeset.length !== 0 ) { + const change = processInsertion(doc, deadline, changeset.shift()); + if ( change === undefined ) { continue; } + changeset.unshift(change); + break; + } + cm.endOperation(); + if ( changeset.length !== 0 ) { + return processChangesetAsync(doc); + } + includeset.clear(); + processIfendifs(doc); + CodeMirror.signal(doc.getEditor(), 'linterDone', { errorCount }); + }; + + const processChangesetAsync = doc => { + if ( changesetTimer !== undefined ) { return; } + changesetTimer = self.requestIdleCallback(deadline => { + changesetTimer = undefined; + processChangeset(doc, deadline); + }); + }; + + const onChanges = (cm, changes) => { + if ( changes.length === 0 ) { return; } + const doc = cm.getDoc(); + for ( const change of changes ) { + const from = change.from.line; + const to = from + change.text.length; + changeset.push({ from, to }); + } + processChangesetAsync(doc); + }; + + const onBeforeChanges = (cm, change) => { + const doc = cm.getDoc(); + processDeletion(doc, change); + }; + + const foldRangeFinder = (cm, from) => { + const lineNo = from.line; + const lineHandle = cm.getDoc().getLineHandle(lineNo); + const marker = extractMarker(lineHandle); + if ( marker === null ) { return; } + if ( marker.dataset.fold === undefined ) { return; } + const foldName = marker.dataset.lint; + from.ch = lineHandle.text.length; + const to = { line: 0, ch: 0 }; + const doc = cm.getDoc(); + let depth = 0; + doc.eachLine(from.line, doc.lineCount(), lineHandle => { + const marker = extractMarker(lineHandle); + if ( marker === null ) { return; } + if ( marker.dataset.lint === foldName && marker.dataset.fold === 'start' ) { + depth += 1; + return; + } + if ( marker.dataset.lint !== foldName ) { return; } + if ( marker.dataset.fold !== 'end' ) { return; } + depth -= 1; + if ( depth !== 0 ) { return; } + to.line = lineHandle.lineNo(); + return true; + }); + return { from, to }; + }; + + const onGutterClick = (cm, lineNo, gutterId, ev) => { + if ( ev.button !== 0 ) { return; } + if ( gutterId !== 'CodeMirror-lintgutter' ) { return; } + const doc = cm.getDoc(); + const lineHandle = doc.getLineHandle(lineNo); + const marker = extractMarker(lineHandle); + if ( marker === null ) { return; } + if ( marker.dataset.fold === 'start' ) { + if ( ev.ctrlKey ) { + if ( dom.cl.has(marker, 'folded') ) { + CodeMirror.commands.unfoldAll(cm); + } else { + CodeMirror.commands.foldAll(cm); + } + doc.setCursor(lineNo); + return; + } + cm.foldCode(lineNo, { + widget: '\u00A0\u22EF\u00A0', + rangeFinder: foldRangeFinder, + }); + return; + } + if ( marker.dataset.fold === 'end' ) { + let depth = 1; + let lineNo = lineHandle.lineNo(); + while ( lineNo-- ) { + const prevLineHandle = doc.getLineHandle(lineNo); + const markerFrom = extractMarker(prevLineHandle); + if ( markerFrom === null ) { continue; } + if ( markerFrom.dataset.fold === 'end' ) { + depth += 1; + } else if ( markerFrom.dataset.fold === 'start' ) { + depth -= 1; + if ( depth === 0 ) { + doc.setCursor(lineNo); + break; + } + } + } + return; + } + }; + + self.addEventListener('trustedSource', ev => { + astParser.options.trustedSource = ev.detail; + }); + + self.addEventListener('trustedScriptletTokens', ev => { + astParser.options.trustedScriptletTokens = ev.detail; + }); + + CodeMirror.defineInitHook(cm => { + cm.on('changes', onChanges); + cm.on('beforeChange', onBeforeChanges); + cm.on('gutterClick', onGutterClick); + cm.on('fold', function(cm, from) { + const doc = cm.getDoc(); + const lineHandle = doc.getLineHandle(from.line); + const marker = extractMarker(lineHandle); + dom.cl.add(marker, 'folded'); + }); + cm.on('unfold', function(cm, from) { + const doc = cm.getDoc(); + const lineHandle = doc.getLineHandle(from.line); + const marker = extractMarker(lineHandle); + dom.cl.remove(marker, 'folded'); + }); + }); +} + +/******************************************************************************/ + +// Enhanced word selection + +{ + const selectWordAt = function(cm, pos) { + const { line, ch } = pos; + const s = cm.getLine(line); + const { type: token } = cm.getTokenAt(pos); + let beg, end; + + // Select URL in comments + if ( /\bcomment\b/.test(token) && /\blink\b/.test(token) ) { + const l = /\S+$/.exec(s.slice(0, ch)); + if ( l && /^https?:\/\//.test(s.slice(l.index)) ) { + const r = /^\S+/.exec(s.slice(ch)); + if ( r ) { + beg = l.index; + end = ch + r[0].length; + } + } + } + + // Better word selection for extended filters: prefix + else if ( + /\bline-cm-ext-(?:dom|html|js)\b/.test(token) && + /\bvalue\b/.test(token) + ) { + const l = /[^,.]*$/i.exec(s.slice(0, ch)); + const r = /^[^#,]*/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } + + // Better word selection for cosmetic and HTML filters: suffix + else if ( /\bline-cm-ext-(?:dom|html)\b/.test(token) ) { + const l = /[#.]?[a-z0-9_-]+$/i.exec(s.slice(0, ch)); + const r = /^[a-z0-9_-]+/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + if ( /\bdef\b/.test(cm.getTokenTypeAt({ line, ch: beg + 1 })) ) { + beg += 1; + } + } + } + + // Better word selection for network filters + else if ( /\bline-cm-net\b/.test(token) ) { + if ( /\bvalue\b/.test(token) ) { + const l = /[^ ,.=|]*$/i.exec(s.slice(0, ch)); + const r = /^[^ #,|]*/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } else if ( /\bdef\b/.test(token) ) { + const l = /[a-z0-9-]+$/i.exec(s.slice(0, ch)); + const r = /^[^,]*=[^,]+/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } + } + + if ( beg === undefined ) { + const { anchor, head } = cm.findWordAt(pos); + return { from: anchor, to: head }; + } + + return { + from: { line, ch: beg }, + to: { line, ch: end }, + }; + }; + + CodeMirror.defineInitHook(cm => { + cm.setOption('configureMouse', function(cm, repeat) { + return { + unit: repeat === 'double' ? selectWordAt : null, + }; + }); + }); +} + +/******************************************************************************/ diff --git a/src/js/commands.js b/src/js/commands.js new file mode 100644 index 0000000..8fd6341 --- /dev/null +++ b/src/js/commands.js @@ -0,0 +1,181 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2017-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import µb from './background.js'; +import { hostnameFromURI } from './uri-utils.js'; + +/******************************************************************************/ + +(( ) => { + +// ***************************************************************************** +// start of local namespace + +if ( vAPI.commands instanceof Object === false ) { return; } + +const relaxBlockingMode = (( ) => { + const reloadTimers = new Map(); + + return function(tab) { + if ( tab instanceof Object === false || tab.id <= 0 ) { return; } + + const normalURL = µb.normalizeTabURL(tab.id, tab.url); + + if ( µb.getNetFilteringSwitch(normalURL) === false ) { return; } + + const hn = hostnameFromURI(normalURL); + const curProfileBits = µb.blockingModeFromHostname(hn); + let newProfileBits; + for ( const profile of µb.liveBlockingProfiles ) { + if ( (curProfileBits & profile.bits & ~1) !== curProfileBits ) { + newProfileBits = profile.bits; + break; + } + } + + // TODO: Reset to original blocking profile? + if ( newProfileBits === undefined ) { return; } + + const noReload = (newProfileBits & 0b00000001) === 0; + + if ( + (curProfileBits & 0b00000010) !== 0 && + (newProfileBits & 0b00000010) === 0 + ) { + µb.toggleHostnameSwitch({ + name: 'no-scripting', + hostname: hn, + state: false, + }); + } + if ( µb.userSettings.advancedUserEnabled ) { + if ( + (curProfileBits & 0b00000100) !== 0 && + (newProfileBits & 0b00000100) === 0 + ) { + µb.toggleFirewallRule({ + tabId: noReload ? tab.id : undefined, + srcHostname: hn, + desHostname: '*', + requestType: '3p', + action: 3, + }); + } + if ( + (curProfileBits & 0b00001000) !== 0 && + (newProfileBits & 0b00001000) === 0 + ) { + µb.toggleFirewallRule({ + srcHostname: hn, + desHostname: '*', + requestType: '3p-script', + action: 3, + }); + } + if ( + (curProfileBits & 0b00010000) !== 0 && + (newProfileBits & 0b00010000) === 0 + ) { + µb.toggleFirewallRule({ + srcHostname: hn, + desHostname: '*', + requestType: '3p-frame', + action: 3, + }); + } + } + + // Reload the target tab? + if ( noReload ) { return; } + + // Reload: use a timer to coalesce bursts of reload commands. + const timer = reloadTimers.get(tab.id) || (( ) => { + const t = vAPI.defer.create(tabId => { + reloadTimers.delete(tabId); + vAPI.tabs.reload(tabId); + }); + reloadTimers.set(tab.id, t); + return t; + })(); + timer.offon(547, tab.id); + }; +})(); + +vAPI.commands.onCommand.addListener(async command => { + // Generic commands + if ( command === 'open-dashboard' ) { + µb.openNewTab({ + url: 'dashboard.html', + select: true, + index: -1, + }); + return; + } + // Tab-specific commands + const tab = await vAPI.tabs.getCurrent(); + if ( tab instanceof Object === false ) { return; } + switch ( command ) { + case 'launch-element-picker': + case 'launch-element-zapper': { + µb.epickerArgs.mouse = false; + µb.elementPickerExec( + tab.id, + 0, + undefined, + command === 'launch-element-zapper' + ); + break; + } + case 'launch-logger': { + const hash = tab.url.startsWith(vAPI.getURL('')) + ? '' + : `#_+${tab.id}`; + µb.openNewTab({ + url: `logger-ui.html${hash}`, + select: true, + index: -1, + }); + break; + } + case 'relax-blocking-mode': + relaxBlockingMode(tab); + break; + case 'toggle-cosmetic-filtering': + µb.toggleHostnameSwitch({ + name: 'no-cosmetic-filtering', + hostname: hostnameFromURI(µb.normalizeTabURL(tab.id, tab.url)), + }); + break; + default: + break; + } +}); + +// end of local namespace +// ***************************************************************************** + +})(); + +/******************************************************************************/ diff --git a/src/js/console.js b/src/js/console.js new file mode 100644 index 0000000..410abbd --- /dev/null +++ b/src/js/console.js @@ -0,0 +1,59 @@ +/******************************************************************************* + + 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 +*/ + +'use strict'; + +/******************************************************************************/ + +function ubologSet(state = false) { + if ( state ) { + if ( ubolog.process instanceof Function ) { + ubolog.process(); + } + ubolog = ubologDo; + } else { + ubolog = ubologIgnore; + } +} + +function ubologDo(...args) { + console.info('[uBO]', ...args); +} + +function ubologIgnore() { +} + +let ubolog = (( ) => { + const pending = []; + const store = function(...args) { + pending.push(args); + }; + store.process = function() { + for ( const args of pending ) { + ubologDo(...args); + } + }; + return store; +})(); + +/******************************************************************************/ + +export { ubolog, ubologSet }; diff --git a/src/js/contentscript-extra.js b/src/js/contentscript-extra.js new file mode 100644 index 0000000..45c5262 --- /dev/null +++ b/src/js/contentscript-extra.js @@ -0,0 +1,662 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +if ( + typeof vAPI === 'object' && + typeof vAPI.DOMProceduralFilterer !== 'object' +) { +// >>>>>>>> start of local scope + +/******************************************************************************/ + +const nonVisualElements = { + script: true, + style: true, +}; + +const regexFromString = (s, exact = false) => { + if ( s === '' ) { return /^/; } + const match = /^\/(.+)\/([imu]*)$/.exec(s); + if ( match !== null ) { + return new RegExp(match[1], match[2] || undefined); + } + const reStr = s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return new RegExp(exact ? `^${reStr}$` : reStr); +}; + +// 'P' stands for 'Procedural' + +class PSelectorTask { + begin() { + } + end() { + } +} + +class PSelectorVoidTask extends PSelectorTask { + constructor(task) { + super(); + console.info(`uBO: :${task[0]}() operator does not exist`); + } + transpose() { + } +} + +class PSelectorHasTextTask extends PSelectorTask { + constructor(task) { + super(); + this.needle = regexFromString(task[1]); + } + transpose(node, output) { + if ( this.needle.test(node.textContent) ) { + output.push(node); + } + } +} + +class PSelectorIfTask extends PSelectorTask { + constructor(task) { + super(); + this.pselector = new PSelector(task[1]); + } + transpose(node, output) { + if ( this.pselector.test(node) === this.target ) { + output.push(node); + } + } +} +PSelectorIfTask.prototype.target = true; + +class PSelectorIfNotTask extends PSelectorIfTask { +} +PSelectorIfNotTask.prototype.target = false; + +class PSelectorMatchesAttrTask extends PSelectorTask { + constructor(task) { + super(); + this.reAttr = regexFromString(task[1].attr, true); + this.reValue = regexFromString(task[1].value, true); + } + transpose(node, output) { + const attrs = node.getAttributeNames(); + for ( const attr of attrs ) { + if ( this.reAttr.test(attr) === false ) { continue; } + if ( this.reValue.test(node.getAttribute(attr)) === false ) { continue; } + output.push(node); + } + } +} + +class PSelectorMatchesCSSTask extends PSelectorTask { + constructor(task) { + super(); + this.name = task[1].name; + this.pseudo = task[1].pseudo ? `::${task[1].pseudo}` : null; + let arg0 = task[1].value, arg1; + if ( Array.isArray(arg0) ) { + arg1 = arg0[1]; arg0 = arg0[0]; + } + this.value = new RegExp(arg0, arg1); + } + transpose(node, output) { + const style = window.getComputedStyle(node, this.pseudo); + if ( style !== null && this.value.test(style[this.name]) ) { + output.push(node); + } + } +} +class PSelectorMatchesCSSAfterTask extends PSelectorMatchesCSSTask { + constructor(task) { + super(task); + this.pseudo = '::after'; + } +} + +class PSelectorMatchesCSSBeforeTask extends PSelectorMatchesCSSTask { + constructor(task) { + super(task); + this.pseudo = '::before'; + } +} + +class PSelectorMatchesMediaTask extends PSelectorTask { + constructor(task) { + 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 ]); + }); + } + transpose(node, output) { + if ( this.mql.matches === false ) { return; } + output.push(node); + } +} + +class PSelectorMatchesPathTask extends PSelectorTask { + constructor(task) { + super(); + this.needle = regexFromString( + task[1].replace(/\P{ASCII}/gu, s => encodeURIComponent(s)) + ); + } + transpose(node, output) { + if ( this.needle.test(self.location.pathname + self.location.search) ) { + output.push(node); + } + } +} + +class PSelectorMinTextLengthTask extends PSelectorTask { + constructor(task) { + super(); + this.min = task[1]; + } + transpose(node, output) { + if ( node.textContent.length >= this.min ) { + output.push(node); + } + } +} + +class PSelectorOthersTask extends PSelectorTask { + constructor() { + super(); + this.targets = new Set(); + } + begin() { + this.targets.clear(); + } + end(output) { + const toKeep = new Set(this.targets); + const toDiscard = new Set(); + const body = document.body; + let discard = null; + for ( let keep of this.targets ) { + while ( keep !== null && keep !== body ) { + toKeep.add(keep); + toDiscard.delete(keep); + discard = keep.previousElementSibling; + while ( discard !== null ) { + if ( + nonVisualElements[discard.localName] !== true && + toKeep.has(discard) === false + ) { + toDiscard.add(discard); + } + discard = discard.previousElementSibling; + } + discard = keep.nextElementSibling; + while ( discard !== null ) { + if ( + nonVisualElements[discard.localName] !== true && + toKeep.has(discard) === false + ) { + toDiscard.add(discard); + } + discard = discard.nextElementSibling; + } + keep = keep.parentElement; + } + } + for ( discard of toDiscard ) { + output.push(discard); + } + this.targets.clear(); + } + transpose(candidate) { + for ( const target of this.targets ) { + if ( target.contains(candidate) ) { return; } + if ( candidate.contains(target) ) { + this.targets.delete(target); + } + } + this.targets.add(candidate); + } +} + +// https://github.com/AdguardTeam/ExtendedCss/issues/31#issuecomment-302391277 +// Prepend `:scope ` if needed. +class PSelectorSpathTask extends PSelectorTask { + constructor(task) { + super(); + this.spath = task[1]; + this.nth = /^(?:\s*[+~]|:)/.test(this.spath); + if ( this.nth ) { return; } + if ( /^\s*>/.test(this.spath) ) { + this.spath = `:scope ${this.spath.trim()}`; + } + } + transpose(node, output) { + const nodes = this.nth + ? PSelectorSpathTask.qsa(node, this.spath) + : node.querySelectorAll(this.spath); + for ( const node of nodes ) { + output.push(node); + } + } + // Helper method for other operators. + static qsa(node, selector) { + const parent = node.parentElement; + if ( parent === null ) { return []; } + let pos = 1; + for (;;) { + node = node.previousElementSibling; + if ( node === null ) { break; } + pos += 1; + } + return parent.querySelectorAll( + `:scope > :nth-child(${pos})${selector}` + ); + } +} + +class PSelectorUpwardTask extends PSelectorTask { + constructor(task) { + super(); + const arg = task[1]; + if ( typeof arg === 'number' ) { + this.i = arg; + } else { + this.s = arg; + } + } + transpose(node, output) { + if ( this.s !== '' ) { + const parent = node.parentElement; + if ( parent === null ) { return; } + node = parent.closest(this.s); + if ( node === null ) { return; } + } else { + let nth = this.i; + for (;;) { + node = node.parentElement; + if ( node === null ) { return; } + nth -= 1; + if ( nth === 0 ) { break; } + } + } + output.push(node); + } +} +PSelectorUpwardTask.prototype.i = 0; +PSelectorUpwardTask.prototype.s = ''; + +class PSelectorWatchAttrs extends PSelectorTask { + constructor(task) { + super(); + this.observer = null; + this.observed = new WeakSet(); + this.observerOptions = { + attributes: true, + subtree: true, + }; + const attrs = task[1]; + if ( Array.isArray(attrs) && attrs.length !== 0 ) { + 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); + } + this.observer.observe(node, this.observerOptions); + this.observed.add(node); + } +} + +class PSelectorXpathTask extends PSelectorTask { + constructor(task) { + super(); + this.xpe = document.createExpression(task[1], null); + this.xpr = null; + } + transpose(node, output) { + this.xpr = this.xpe.evaluate( + node, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + this.xpr + ); + let j = this.xpr.snapshotLength; + while ( j-- ) { + const node = this.xpr.snapshotItem(j); + if ( node.nodeType === 1 ) { + output.push(node); + } + } + } +} + +class PSelector { + constructor(o) { + this.raw = o.raw; + this.selector = o.selector; + this.tasks = []; + const tasks = []; + if ( Array.isArray(o.tasks) === false ) { return; } + for ( const task of o.tasks ) { + const ctor = this.operatorToTaskMap.get(task[0]) || PSelectorVoidTask; + tasks.push(new ctor(task)); + } + this.tasks = tasks; + } + prime(input) { + const root = input || document; + if ( this.selector === '' ) { return [ root ]; } + if ( input !== document ) { + const c0 = this.selector.charCodeAt(0); + if ( c0 === 0x2B /* + */ || c0 === 0x7E /* ~ */ ) { + return Array.from(PSelectorSpathTask.qsa(input, this.selector)); + } else if ( c0 === 0x3E /* > */ ) { + return Array.from(input.querySelectorAll(`:scope ${this.selector}`)); + } + } + return Array.from(root.querySelectorAll(this.selector)); + } + exec(input) { + let nodes = this.prime(input); + for ( const task of this.tasks ) { + if ( nodes.length === 0 ) { break; } + const transposed = []; + task.begin(); + for ( const node of nodes ) { + task.transpose(node, transposed); + } + task.end(transposed); + nodes = transposed; + } + return nodes; + } + test(input) { + const nodes = this.prime(input); + for ( const node of nodes ) { + let output = [ node ]; + for ( const task of this.tasks ) { + const transposed = []; + task.begin(); + for ( const node of output ) { + task.transpose(node, transposed); + } + task.end(transposed); + output = transposed; + if ( output.length === 0 ) { break; } + } + if ( output.length !== 0 ) { return true; } + } + return false; + } +} +PSelector.prototype.operatorToTaskMap = new Map([ + [ 'has', PSelectorIfTask ], + [ 'has-text', PSelectorHasTextTask ], + [ 'if', PSelectorIfTask ], + [ 'if-not', PSelectorIfNotTask ], + [ 'matches-attr', PSelectorMatchesAttrTask ], + [ 'matches-css', PSelectorMatchesCSSTask ], + [ 'matches-css-after', PSelectorMatchesCSSAfterTask ], + [ 'matches-css-before', PSelectorMatchesCSSBeforeTask ], + [ 'matches-media', PSelectorMatchesMediaTask ], + [ 'matches-path', PSelectorMatchesPathTask ], + [ 'min-text-length', PSelectorMinTextLengthTask ], + [ 'not', PSelectorIfNotTask ], + [ 'others', PSelectorOthersTask ], + [ 'spath', PSelectorSpathTask ], + [ 'upward', PSelectorUpwardTask ], + [ 'watch-attr', PSelectorWatchAttrs ], + [ 'xpath', PSelectorXpathTask ], +]); + +class PSelectorRoot extends PSelector { + constructor(o) { + super(o); + this.budget = 200; // I arbitrary picked a 1/5 second + this.raw = o.raw; + this.cost = 0; + this.lastAllowanceTime = 0; + this.action = o.action; + } + prime(input) { + try { + return super.prime(input); + } catch (ex) { + } + return []; + } +} +PSelectorRoot.prototype.hit = false; + +class ProceduralFilterer { + constructor(domFilterer) { + this.domFilterer = domFilterer; + this.mustApplySelectors = false; + this.selectors = new Map(); + this.masterToken = vAPI.randomToken(); + this.styleTokenMap = new Map(); + this.styledNodes = new Set(); + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.addListener(this); + } + } + + addProceduralSelectors(selectors) { + const addedSelectors = []; + let mustCommit = false; + for ( const selector of selectors ) { + if ( this.selectors.has(selector.raw) ) { continue; } + const pselector = new PSelectorRoot(selector); + this.primeProceduralSelector(pselector); + this.selectors.set(selector.raw, pselector); + addedSelectors.push(pselector); + mustCommit = true; + } + if ( mustCommit === false ) { return; } + this.mustApplySelectors = this.selectors.size !== 0; + this.domFilterer.commit(); + if ( this.domFilterer.hasListeners() ) { + this.domFilterer.triggerListeners({ + procedural: addedSelectors + }); + } + } + + // This allows to perform potentially expensive initialization steps + // before the filters are ready to be applied. + primeProceduralSelector(pselector) { + if ( pselector.action === undefined ) { + this.styleTokenFromStyle(vAPI.hideStyle); + } else if ( pselector.action[0] === 'style' ) { + this.styleTokenFromStyle(pselector.action[1]); + } + return pselector; + } + + commitNow() { + if ( this.selectors.size === 0 ) { return; } + + this.mustApplySelectors = false; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/341 + // Be ready to unhide nodes which no longer matches any of + // the procedural selectors. + const toUnstyle = this.styledNodes; + this.styledNodes = new Set(); + + let t0 = Date.now(); + + for ( const pselector of this.selectors.values() ) { + const allowance = Math.floor((t0 - pselector.lastAllowanceTime) / 2000); + if ( allowance >= 1 ) { + pselector.budget += allowance * 50; + if ( pselector.budget > 200 ) { pselector.budget = 200; } + pselector.lastAllowanceTime = t0; + } + if ( pselector.budget <= 0 ) { continue; } + const nodes = pselector.exec(); + const t1 = Date.now(); + pselector.budget += t0 - t1; + if ( pselector.budget < -500 ) { + console.info('uBO: disabling %s', pselector.raw); + pselector.budget = -0x7FFFFFFF; + } + t0 = t1; + if ( nodes.length === 0 ) { continue; } + pselector.hit = true; + this.processNodes(nodes, pselector.action); + } + + this.unprocessNodes(toUnstyle); + } + + styleTokenFromStyle(style) { + if ( style === undefined ) { return; } + let styleToken = this.styleTokenMap.get(style); + if ( styleToken !== undefined ) { return styleToken; } + styleToken = vAPI.randomToken(); + this.styleTokenMap.set(style, styleToken); + this.domFilterer.addCSS( + `[${this.masterToken}][${styleToken}]\n{${style}}`, + { silent: true, mustInject: true } + ); + return styleToken; + } + + processNodes(nodes, action) { + const op = action && action[0] || ''; + const arg = op !== '' ? action[1] : ''; + switch ( op ) { + case '': + /* fall through */ + case 'style': { + const styleToken = this.styleTokenFromStyle( + arg === '' ? vAPI.hideStyle : arg + ); + for ( const node of nodes ) { + node.setAttribute(this.masterToken, ''); + node.setAttribute(styleToken, ''); + this.styledNodes.add(node); + } + break; + } + case 'remove': { + for ( const node of nodes ) { + node.remove(); + node.textContent = ''; + } + break; + } + case 'remove-attr': { + const reAttr = regexFromString(arg, true); + for ( const node of nodes ) { + for ( const name of node.getAttributeNames() ) { + if ( reAttr.test(name) === false ) { continue; } + node.removeAttribute(name); + } + } + break; + } + case 'remove-class': { + const reClass = regexFromString(arg, true); + for ( const node of nodes ) { + const cl = node.classList; + for ( const name of cl.values() ) { + if ( reClass.test(name) === false ) { continue; } + cl.remove(name); + } + } + break; + } + default: + break; + } + } + + // TODO: Current assumption is one style per hit element. Could be an + // issue if an element has multiple styling and one styling is + // brought back. Possibly too rare to care about this for now. + unprocessNodes(nodes) { + for ( const node of nodes ) { + if ( this.styledNodes.has(node) ) { continue; } + node.removeAttribute(this.masterToken); + } + } + + createProceduralFilter(o) { + return this.primeProceduralSelector( + new PSelectorRoot(typeof o === 'string' ? JSON.parse(o) : o) + ); + } + + onDOMCreated() { + } + + onDOMChanged(addedNodes, removedNodes) { + if ( this.selectors.size === 0 ) { return; } + this.mustApplySelectors = + this.mustApplySelectors || + addedNodes.length !== 0 || + removedNodes; + this.domFilterer.commit(); + } +} + +vAPI.DOMProceduralFilterer = ProceduralFilterer; + +/******************************************************************************/ + +// >>>>>>>> end of local scope +} + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/contentscript.js b/src/js/contentscript.js new file mode 100644 index 0000000..8f3a4cf --- /dev/null +++ b/src/js/contentscript.js @@ -0,0 +1,1364 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************* + + +--> domCollapser + | + | + domWatcher--+ + | +-- domSurveyor + | | + +--> domFilterer --+-- [domLogger] + | | + | +-- [domInspector] + | + [domProceduralFilterer] + + domWatcher: + Watches for changes in the DOM, and notify the other components about these + changes. + + domCollapser: + Enforces the collapsing of DOM elements for which a corresponding + resource was blocked through network filtering. + + domFilterer: + Enforces the filtering of DOM elements, by feeding it cosmetic filters. + + domProceduralFilterer: + Enforce the filtering of DOM elements through procedural cosmetic filters. + Loaded on demand, only when needed. + + domSurveyor: + Surveys the DOM to find new cosmetic filters to apply to the current page. + + domLogger: + Surveys the page to find and report the injected cosmetic filters blocking + actual elements on the current page. This component is dynamically loaded + IF AND ONLY IF uBO's logger is opened. + + If page is whitelisted: + - domWatcher: off + - domCollapser: off + - domFilterer: off + - domSurveyor: off + - domLogger: off + + I verified that the code in this file is completely flushed out of memory + when a page is whitelisted. + + If cosmetic filtering is disabled: + - domWatcher: on + - domCollapser: on + - domFilterer: off + - domSurveyor: off + - domLogger: off + + If generic cosmetic filtering is disabled: + - domWatcher: on + - domCollapser: on + - domFilterer: on + - domSurveyor: off + - domLogger: on if uBO logger is opened + + If generic cosmetic filtering is enabled: + - domWatcher: on + - domCollapser: on + - domFilterer: on + - domSurveyor: on + - domLogger: on if uBO logger is opened + + Additionally, the domSurveyor can turn itself off once it decides that + it has become pointless (repeatedly not finding new cosmetic filters). + + The domFilterer makes use of platform-dependent user stylesheets[1]. + + [1] "user stylesheets" refer to local CSS rules which have priority over, + and can't be overridden by a web page's own CSS rules. + +*/ + +// Abort execution if our global vAPI object does not exist. +// https://github.com/chrisaljoudi/uBlock/issues/456 +// https://github.com/gorhill/uBlock/issues/2029 + + // >>>>>>>> start of HUGE-IF-BLOCK +if ( typeof vAPI === 'object' && !vAPI.contentScript ) { + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +vAPI.contentScript = true; + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/688#issuecomment-663657508 +{ + let context = self; + try { + while ( + context !== self.top && + context.location.href.startsWith('about:blank') && + context.parent.location.href + ) { + context = context.parent; + } + } catch(ex) { + } + vAPI.effectiveSelf = context; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +vAPI.userStylesheet = { + added: new Set(), + removed: new Set(), + apply: function(callback) { + if ( this.added.size === 0 && this.removed.size === 0 ) { return; } + vAPI.messaging.send('vapi', { + what: 'userCSS', + add: Array.from(this.added), + remove: Array.from(this.removed), + }).then(( ) => { + if ( callback instanceof Function === false ) { return; } + callback(); + }); + this.added.clear(); + this.removed.clear(); + }, + add: function(cssText, now) { + if ( cssText === '' ) { return; } + this.added.add(cssText); + if ( now ) { this.apply(); } + }, + remove: function(cssText, now) { + if ( cssText === '' ) { return; } + this.removed.add(cssText); + if ( now ) { this.apply(); } + } +}; + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************* + + The purpose of SafeAnimationFrame is to take advantage of the behavior of + window.requestAnimationFrame[1]. If we use an animation frame as a timer, + then this timer is described as follow: + + - time events are throttled by the browser when the viewport is not visible -- + there is no point for uBO to play with the DOM if the document is not + visible. + - time events are micro tasks[2]. + - time events are synchronized to monitor refresh, meaning that they can fire + at most 1/60 (typically). + + If a delay value is provided, a plain timer is first used. Plain timers are + macro-tasks, so this is good when uBO wants to yield to more important tasks + on a page. Once the plain timer elapse, an animation frame is used to trigger + the next time at which to execute the job. + + [1] https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame + [2] https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ + +*/ + +// https://github.com/gorhill/uBlock/issues/2147 + +vAPI.SafeAnimationFrame = class { + constructor(callback) { + this.fid = this.tid = undefined; + this.callback = callback; + } + start(delay) { + if ( self.vAPI instanceof Object === false ) { return; } + if ( delay === undefined ) { + if ( this.fid === undefined ) { + this.fid = requestAnimationFrame(( ) => { this.onRAF(); } ); + } + if ( this.tid === undefined ) { + this.tid = vAPI.setTimeout(( ) => { this.onSTO(); }, 20000); + } + return; + } + if ( this.fid === undefined && this.tid === undefined ) { + this.tid = vAPI.setTimeout(( ) => { this.macroToMicro(); }, delay); + } + } + clear() { + if ( this.fid !== undefined ) { + cancelAnimationFrame(this.fid); + this.fid = undefined; + } + if ( this.tid !== undefined ) { + clearTimeout(this.tid); + this.tid = undefined; + } + } + macroToMicro() { + this.tid = undefined; + this.start(); + } + onRAF() { + if ( this.tid !== undefined ) { + clearTimeout(this.tid); + this.tid = undefined; + } + this.fid = undefined; + this.callback(); + } + onSTO() { + if ( this.fid !== undefined ) { + cancelAnimationFrame(this.fid); + this.fid = undefined; + } + this.tid = undefined; + this.callback(); + } +}; + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/552 +// Listen and report CSP violations so that blocked resources through CSP +// are properly reported in the logger. + +{ + const newEvents = new Set(); + const allEvents = new Set(); + let timer; + + const send = function() { + if ( self.vAPI instanceof Object === false ) { return; } + vAPI.messaging.send('scriptlets', { + what: 'securityPolicyViolation', + type: 'net', + docURL: document.location.href, + violations: Array.from(newEvents), + }).then(response => { + if ( response === true ) { return; } + stop(); + }); + for ( const event of newEvents ) { + allEvents.add(event); + } + newEvents.clear(); + }; + + const sendAsync = function() { + if ( timer !== undefined ) { return; } + timer = self.requestIdleCallback( + ( ) => { timer = undefined; send(); }, + { timeout: 2063 } + ); + }; + + const listener = function(ev) { + if ( ev.isTrusted !== true ) { return; } + if ( ev.disposition !== 'enforce' ) { return; } + const json = JSON.stringify({ + url: ev.blockedURL || ev.blockedURI, + policy: ev.originalPolicy, + directive: ev.effectiveDirective || ev.violatedDirective, + }); + if ( allEvents.has(json) ) { return; } + newEvents.add(json); + sendAsync(); + }; + + const stop = function() { + newEvents.clear(); + allEvents.clear(); + if ( timer !== undefined ) { + self.cancelIdleCallback(timer); + timer = undefined; + } + document.removeEventListener('securitypolicyviolation', listener); + if ( vAPI ) { vAPI.shutdown.remove(stop); } + }; + + document.addEventListener('securitypolicyviolation', listener); + vAPI.shutdown.add(stop); + + // We need to call at least once to find out whether we really need to + // listen to CSP violations. + sendAsync(); +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// vAPI.domWatcher + +{ + vAPI.domMutationTime = Date.now(); + + const addedNodeLists = []; + const removedNodeLists = []; + const addedNodes = []; + const ignoreTags = new Set([ 'br', 'head', 'link', 'meta', 'script', 'style' ]); + const listeners = []; + + let domLayoutObserver; + let listenerIterator = []; + let listenerIteratorDirty = false; + let removedNodes = false; + let safeObserverHandlerTimer; + + const safeObserverHandler = function() { + let i = addedNodeLists.length; + while ( i-- ) { + const nodeList = addedNodeLists[i]; + let iNode = nodeList.length; + while ( iNode-- ) { + const node = nodeList[iNode]; + if ( node.nodeType !== 1 ) { continue; } + if ( ignoreTags.has(node.localName) ) { continue; } + if ( node.parentElement === null ) { continue; } + addedNodes.push(node); + } + } + addedNodeLists.length = 0; + i = removedNodeLists.length; + while ( i-- && removedNodes === false ) { + const nodeList = removedNodeLists[i]; + let iNode = nodeList.length; + while ( iNode-- ) { + if ( nodeList[iNode].nodeType !== 1 ) { continue; } + removedNodes = true; + break; + } + } + removedNodeLists.length = 0; + if ( addedNodes.length === 0 && removedNodes === false ) { return; } + for ( const listener of getListenerIterator() ) { + try { listener.onDOMChanged(addedNodes, removedNodes); } + catch (ex) { } + } + addedNodes.length = 0; + removedNodes = false; + vAPI.domMutationTime = Date.now(); + }; + + // https://github.com/chrisaljoudi/uBlock/issues/205 + // Do not handle added node directly from within mutation observer. + const observerHandler = function(mutations) { + let i = mutations.length; + while ( i-- ) { + const mutation = mutations[i]; + let nodeList = mutation.addedNodes; + if ( nodeList.length !== 0 ) { + addedNodeLists.push(nodeList); + } + nodeList = mutation.removedNodes; + if ( nodeList.length !== 0 ) { + removedNodeLists.push(nodeList); + } + } + if ( addedNodeLists.length !== 0 || removedNodeLists.length !== 0 ) { + safeObserverHandlerTimer.start( + addedNodeLists.length < 100 ? 1 : undefined + ); + } + }; + + const startMutationObserver = function() { + if ( domLayoutObserver !== undefined ) { return; } + domLayoutObserver = new MutationObserver(observerHandler); + domLayoutObserver.observe(document, { + //attributeFilter: [ 'class', 'id' ], + //attributes: true, + childList: true, + subtree: true + }); + safeObserverHandlerTimer = new vAPI.SafeAnimationFrame(safeObserverHandler); + vAPI.shutdown.add(cleanup); + }; + + const stopMutationObserver = function() { + if ( domLayoutObserver === undefined ) { return; } + cleanup(); + vAPI.shutdown.remove(cleanup); + }; + + const getListenerIterator = function() { + if ( listenerIteratorDirty ) { + listenerIterator = listeners.slice(); + listenerIteratorDirty = false; + } + return listenerIterator; + }; + + const addListener = function(listener) { + if ( listeners.indexOf(listener) !== -1 ) { return; } + listeners.push(listener); + listenerIteratorDirty = true; + if ( domLayoutObserver === undefined ) { return; } + try { listener.onDOMCreated(); } + catch (ex) { } + startMutationObserver(); + }; + + const removeListener = function(listener) { + const pos = listeners.indexOf(listener); + if ( pos === -1 ) { return; } + listeners.splice(pos, 1); + listenerIteratorDirty = true; + if ( listeners.length === 0 ) { + stopMutationObserver(); + } + }; + + const cleanup = function() { + if ( domLayoutObserver !== undefined ) { + domLayoutObserver.disconnect(); + domLayoutObserver = undefined; + } + if ( safeObserverHandlerTimer !== undefined ) { + safeObserverHandlerTimer.clear(); + safeObserverHandlerTimer = undefined; + } + }; + + const start = function() { + for ( const listener of getListenerIterator() ) { + try { listener.onDOMCreated(); } + catch (ex) { } + } + startMutationObserver(); + }; + + vAPI.domWatcher = { start, addListener, removeListener }; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +vAPI.injectScriptlet = function(doc, text) { + if ( !doc ) { return; } + let script, url; + try { + const blob = new self.Blob([ text ], { type: 'text/javascript; charset=utf-8' }); + url = self.URL.createObjectURL(blob); + script = doc.createElement('script'); + script.async = false; + script.src = url; + (doc.head || doc.documentElement || doc).appendChild(script); + } catch (ex) { + } + if ( url ) { + if ( script ) { script.remove(); } + self.URL.revokeObjectURL(url); + } +}; + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************* + + The DOM filterer is the heart of uBO's cosmetic filtering. + + DOMFilterer: adds procedural cosmetic filtering + +*/ + +vAPI.hideStyle = 'display:none!important;'; + +vAPI.DOMFilterer = class { + constructor() { + this.commitTimer = new vAPI.SafeAnimationFrame( + ( ) => { this.commitNow(); } + ); + this.disabled = false; + this.listeners = []; + this.stylesheets = []; + this.exceptedCSSRules = []; + this.exceptions = []; + this.convertedProceduralFilters = []; + this.proceduralFilterer = null; + } + + explodeCSS(css) { + const out = []; + const cssHide = `{${vAPI.hideStyle}}`; + const blocks = css.trim().split(/\n\n+/); + for ( const block of blocks ) { + if ( block.endsWith(cssHide) === false ) { continue; } + out.push(block.slice(0, -cssHide.length).trim()); + } + return out; + } + + addCSS(css, details = {}) { + if ( typeof css !== 'string' || css.length === 0 ) { return; } + if ( this.stylesheets.includes(css) ) { return; } + this.stylesheets.push(css); + if ( details.mustInject && this.disabled === false ) { + vAPI.userStylesheet.add(css); + } + if ( this.hasListeners() === false ) { return; } + if ( details.silent ) { return; } + this.triggerListeners({ declarative: this.explodeCSS(css) }); + } + + exceptCSSRules(exceptions) { + if ( exceptions.length === 0 ) { return; } + this.exceptedCSSRules.push(...exceptions); + if ( this.hasListeners() ) { + this.triggerListeners({ exceptions }); + } + } + + addListener(listener) { + if ( this.listeners.indexOf(listener) !== -1 ) { return; } + this.listeners.push(listener); + } + + removeListener(listener) { + const pos = this.listeners.indexOf(listener); + if ( pos === -1 ) { return; } + this.listeners.splice(pos, 1); + } + + hasListeners() { + return this.listeners.length !== 0; + } + + triggerListeners(changes) { + for ( const listener of this.listeners ) { + listener.onFiltersetChanged(changes); + } + } + + toggle(state, callback) { + if ( state === undefined ) { state = this.disabled; } + if ( state !== this.disabled ) { return; } + this.disabled = !state; + const uss = vAPI.userStylesheet; + for ( const css of this.stylesheets ) { + if ( this.disabled ) { + uss.remove(css); + } else { + uss.add(css); + } + } + uss.apply(callback); + } + + // Here we will deal with: + // - Injecting low priority user styles; + // - Notifying listeners about changed filterset. + // https://www.reddit.com/r/uBlockOrigin/comments/9jj0y1/no_longer_blocking_ads/ + // Ensure vAPI is still valid -- it can go away by the time we are + // called, since the port could be force-disconnected from the main + // process. Another approach would be to have vAPI.SafeAnimationFrame + // register a shutdown job: to evaluate. For now I will keep the fix + // trivial. + commitNow() { + this.commitTimer.clear(); + if ( vAPI instanceof Object === false ) { return; } + vAPI.userStylesheet.apply(); + if ( this.proceduralFilterer instanceof Object ) { + this.proceduralFilterer.commitNow(); + } + } + + commit(commitNow) { + if ( commitNow ) { + this.commitTimer.clear(); + this.commitNow(); + } else { + this.commitTimer.start(); + } + } + + proceduralFiltererInstance() { + if ( this.proceduralFilterer instanceof Object === false ) { + if ( vAPI.DOMProceduralFilterer instanceof Object === false ) { + return null; + } + this.proceduralFilterer = new vAPI.DOMProceduralFilterer(this); + } + return this.proceduralFilterer; + } + + addProceduralSelectors(selectors) { + const procedurals = []; + for ( const raw of selectors ) { + procedurals.push(JSON.parse(raw)); + } + if ( procedurals.length === 0 ) { return; } + const pfilterer = this.proceduralFiltererInstance(); + if ( pfilterer !== null ) { + pfilterer.addProceduralSelectors(procedurals); + } + } + + createProceduralFilter(o) { + const pfilterer = this.proceduralFiltererInstance(); + if ( pfilterer === null ) { return; } + return pfilterer.createProceduralFilter(o); + } + + getAllSelectors(bits = 0) { + const out = { + declarative: [], + exceptions: this.exceptedCSSRules, + }; + const hasProcedural = this.proceduralFilterer instanceof Object; + const includePrivateSelectors = (bits & 0b01) !== 0; + const masterToken = hasProcedural + ? `[${this.proceduralFilterer.masterToken}]` + : undefined; + for ( const css of this.stylesheets ) { + for ( const block of this.explodeCSS(css) ) { + if ( + includePrivateSelectors === false && + masterToken !== undefined && + block.startsWith(masterToken) + ) { + continue; + } + out.declarative.push(block); + } + } + const excludeProcedurals = (bits & 0b10) !== 0; + if ( excludeProcedurals === false ) { + out.procedural = []; + if ( hasProcedural ) { + out.procedural.push( + ...this.proceduralFilterer.selectors.values() + ); + } + const proceduralFilterer = this.proceduralFiltererInstance(); + if ( proceduralFilterer !== null ) { + for ( const json of this.convertedProceduralFilters ) { + const pfilter = proceduralFilterer.createProceduralFilter(json); + pfilter.converted = true; + out.procedural.push(pfilter); + } + } + } + return out; + } + + getAllExceptionSelectors() { + return this.exceptions.join(',\n'); + } +}; + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// vAPI.domCollapser + +{ + const messaging = vAPI.messaging; + const toCollapse = new Map(); + const src1stProps = { + audio: 'currentSrc', + embed: 'src', + iframe: 'src', + img: 'currentSrc', + object: 'data', + video: 'currentSrc', + }; + const src2ndProps = { + audio: 'src', + img: 'src', + video: 'src', + }; + const tagToTypeMap = { + audio: 'media', + embed: 'object', + iframe: 'sub_frame', + img: 'image', + object: 'object', + video: 'media', + }; + let requestIdGenerator = 1, + processTimer, + cachedBlockedSet, + cachedBlockedSetHash, + cachedBlockedSetTimer, + toProcess = [], + toFilter = [], + netSelectorCacheCount = 0; + + const cachedBlockedSetClear = function() { + cachedBlockedSet = + cachedBlockedSetHash = + cachedBlockedSetTimer = undefined; + }; + + // https://github.com/chrisaljoudi/uBlock/issues/399 + // https://github.com/gorhill/uBlock/issues/2848 + // Use a user stylesheet to collapse placeholders. + const getCollapseToken = ( ) => { + if ( collapseToken === undefined ) { + collapseToken = vAPI.randomToken(); + vAPI.userStylesheet.add( + `[${collapseToken}]\n{display:none!important;}`, + true + ); + } + return collapseToken; + }; + let collapseToken; + + // https://github.com/chrisaljoudi/uBlock/issues/174 + // Do not remove fragment from src URL + const onProcessed = function(response) { + // This happens if uBO is disabled or restarted. + if ( response instanceof Object === false ) { + toCollapse.clear(); + return; + } + + const targets = toCollapse.get(response.id); + if ( targets === undefined ) { return; } + + toCollapse.delete(response.id); + if ( cachedBlockedSetHash !== response.hash ) { + cachedBlockedSet = new Set(response.blockedResources); + cachedBlockedSetHash = response.hash; + if ( cachedBlockedSetTimer !== undefined ) { + clearTimeout(cachedBlockedSetTimer); + } + cachedBlockedSetTimer = vAPI.setTimeout(cachedBlockedSetClear, 30000); + } + if ( cachedBlockedSet === undefined || cachedBlockedSet.size === 0 ) { + return; + } + + const selectors = []; + let netSelectorCacheCountMax = response.netSelectorCacheCountMax; + + for ( const target of targets ) { + const tag = target.localName; + let prop = src1stProps[tag]; + if ( prop === undefined ) { continue; } + let src = target[prop]; + if ( typeof src !== 'string' || src.length === 0 ) { + prop = src2ndProps[tag]; + if ( prop === undefined ) { continue; } + src = target[prop]; + if ( typeof src !== 'string' || src.length === 0 ) { continue; } + } + if ( cachedBlockedSet.has(tagToTypeMap[tag] + ' ' + src) === false ) { + continue; + } + target.setAttribute(getCollapseToken(), ''); + // https://github.com/chrisaljoudi/uBlock/issues/1048 + // Use attribute to construct CSS rule + if ( netSelectorCacheCount > netSelectorCacheCountMax ) { continue; } + const value = target.getAttribute(prop); + if ( value ) { + selectors.push(`${tag}[${prop}="${CSS.escape(value)}"]`); + netSelectorCacheCount += 1; + } + } + + if ( selectors.length === 0 ) { return; } + messaging.send('contentscript', { + what: 'cosmeticFiltersInjected', + type: 'net', + hostname: window.location.hostname, + selectors, + }); + }; + + const send = function() { + processTimer = undefined; + toCollapse.set(requestIdGenerator, toProcess); + messaging.send('contentscript', { + what: 'getCollapsibleBlockedRequests', + id: requestIdGenerator, + frameURL: window.location.href, + resources: toFilter, + hash: cachedBlockedSetHash, + }).then(response => { + onProcessed(response); + }); + toProcess = []; + toFilter = []; + requestIdGenerator += 1; + }; + + const process = function(delay) { + if ( toProcess.length === 0 ) { return; } + if ( delay === 0 ) { + if ( processTimer !== undefined ) { + clearTimeout(processTimer); + } + send(); + } else if ( processTimer === undefined ) { + processTimer = vAPI.setTimeout(send, delay || 20); + } + }; + + const add = function(target) { + toProcess[toProcess.length] = target; + }; + + const addMany = function(targets) { + for ( const target of targets ) { + add(target); + } + }; + + const iframeSourceModified = function(mutations) { + for ( const mutation of mutations ) { + addIFrame(mutation.target, true); + } + process(); + }; + const iframeSourceObserver = new MutationObserver(iframeSourceModified); + const iframeSourceObserverOptions = { + attributes: true, + attributeFilter: [ 'src' ] + }; + + // https://github.com/gorhill/uBlock/issues/162 + // Be prepared to deal with possible change of src attribute. + const addIFrame = function(iframe, dontObserve) { + if ( dontObserve !== true ) { + iframeSourceObserver.observe(iframe, iframeSourceObserverOptions); + } + const src = iframe.src; + if ( typeof src !== 'string' || src === '' ) { return; } + if ( src.startsWith('http') === false ) { return; } + toFilter.push({ type: 'sub_frame', url: iframe.src }); + add(iframe); + }; + + const addIFrames = function(iframes) { + for ( const iframe of iframes ) { + addIFrame(iframe); + } + }; + + const onResourceFailed = function(ev) { + if ( tagToTypeMap[ev.target.localName] !== undefined ) { + add(ev.target); + process(); + } + }; + + const stop = function() { + document.removeEventListener('error', onResourceFailed, true); + if ( processTimer !== undefined ) { + clearTimeout(processTimer); + } + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.removeListener(domWatcherInterface); + } + vAPI.shutdown.remove(stop); + vAPI.domCollapser = null; + }; + + const start = function() { + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.addListener(domWatcherInterface); + } + }; + + const domWatcherInterface = { + onDOMCreated: function() { + if ( self.vAPI instanceof Object === false ) { return; } + if ( vAPI.domCollapser instanceof Object === false ) { + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.removeListener(domWatcherInterface); + } + return; + } + // Listener to collapse blocked resources. + // - Future requests not blocked yet + // - Elements dynamically added to the page + // - Elements which resource URL changes + // https://github.com/chrisaljoudi/uBlock/issues/7 + // Preferring getElementsByTagName over querySelectorAll: + // http://jsperf.com/queryselectorall-vs-getelementsbytagname/145 + const elems = document.images || + document.getElementsByTagName('img'); + for ( const elem of elems ) { + if ( elem.complete ) { + add(elem); + } + } + addMany(document.embeds || document.getElementsByTagName('embed')); + addMany(document.getElementsByTagName('object')); + addIFrames(document.getElementsByTagName('iframe')); + process(0); + + document.addEventListener('error', onResourceFailed, true); + + vAPI.shutdown.add(stop); + }, + onDOMChanged: function(addedNodes) { + if ( addedNodes.length === 0 ) { return; } + for ( const node of addedNodes ) { + if ( node.localName === 'iframe' ) { + addIFrame(node); + } + if ( node.firstElementChild === null ) { continue; } + const iframes = node.getElementsByTagName('iframe'); + if ( iframes.length !== 0 ) { + addIFrames(iframes); + } + } + process(); + } + }; + + vAPI.domCollapser = { start }; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// vAPI.domSurveyor + +{ + // http://www.cse.yorku.ca/~oz/hash.html#djb2 + // Must mirror cosmetic filtering compiler's version + const hashFromStr = (type, s) => { + const len = s.length; + const step = len + 7 >>> 3; + let hash = (type << 5) + type ^ len; + for ( let i = 0; i < len; i += step ) { + hash = (hash << 5) + hash ^ s.charCodeAt(i); + } + return hash & 0xFFFFFF; + }; + + const addHashes = hashes => { + for ( const hash of hashes ) { + queriedHashes.add(hash); + } + }; + + const queriedHashes = new Set(); + const maxSurveyNodes = 65536; + const pendingLists = []; + const pendingNodes = []; + const processedSet = new Set(); + let domFilterer; + let hostname = ''; + let domChanged = false; + let scannedCount = 0; + let stopped = false; + + const addPendingList = list => { + if ( list.length === 0 ) { return; } + pendingLists.push(Array.from(list)); + }; + + const nextPendingNodes = ( ) => { + if ( pendingLists.length === 0 ) { return 0; } + const bufferSize = 256; + let j = 0; + do { + const nodeList = pendingLists[0]; + let n = bufferSize - j; + if ( n > nodeList.length ) { + n = nodeList.length; + } + for ( let i = 0; i < n; i++ ) { + pendingNodes[j+i] = nodeList[i]; + } + j += n; + if ( n !== nodeList.length ) { + pendingLists[0] = nodeList.slice(n); + break; + } + pendingLists.shift(); + } while ( j < bufferSize && pendingLists.length !== 0 ); + return j; + }; + + const hasPendingNodes = ( ) => { + return pendingLists.length !== 0; + }; + + // Extract all classes/ids: these will be passed to the cosmetic + // filtering engine, and in return we will obtain only the relevant + // CSS selectors. + + // https://github.com/gorhill/uBlock/issues/672 + // http://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#space-separated-tokens + // http://jsperf.com/enumerate-classes/6 + + const idFromNode = (node, out) => { + const raw = node.id; + if ( typeof raw !== 'string' || raw.length === 0 ) { return; } + const hash = hashFromStr(0x23 /* '#' */, raw.trim()); + if ( queriedHashes.has(hash) ) { return; } + queriedHashes.add(hash); + out.push(hash); + }; + + // https://github.com/uBlockOrigin/uBlock-issues/discussions/2076 + // Performance: avoid using Element.classList + const classesFromNode = (node, out) => { + const s = node.getAttribute('class'); + if ( typeof s !== 'string' ) { return; } + const len = s.length; + for ( let beg = 0, end = 0; beg < len; beg += 1 ) { + end = s.indexOf(' ', beg); + if ( end === beg ) { continue; } + if ( end === -1 ) { end = len; } + const hash = hashFromStr(0x2E /* '.' */, s.slice(beg, end)); + beg = end; + if ( queriedHashes.has(hash) ) { continue; } + queriedHashes.add(hash); + out.push(hash); + } + }; + + const getSurveyResults = (hashes, safeOnly) => { + if ( self.vAPI.messaging instanceof Object === false ) { + stop(); return; + } + const promise = hashes.length === 0 + ? Promise.resolve(null) + : self.vAPI.messaging.send('contentscript', { + what: 'retrieveGenericCosmeticSelectors', + hostname, + hashes, + exceptions: domFilterer.exceptions, + safeOnly, + }); + promise.then(response => { + processSurveyResults(response); + }); + }; + + const doSurvey = ( ) => { + if ( self.vAPI instanceof Object === false ) { return; } + const t0 = performance.now(); + const hashes = []; + const nodes = pendingNodes; + const deadline = t0 + 4; + let processed = 0; + let scanned = 0; + for (;;) { + const n = nextPendingNodes(); + if ( n === 0 ) { break; } + for ( let i = 0; i < n; i++ ) { + const node = nodes[i]; nodes[i] = null; + if ( domChanged ) { + if ( processedSet.has(node) ) { continue; } + processedSet.add(node); + } + idFromNode(node, hashes); + classesFromNode(node, hashes); + scanned += 1; + } + processed += n; + if ( performance.now() >= deadline ) { break; } + } + //console.info(`[domSurveyor][${hostname}] Surveyed ${scanned}/${processed} nodes in ${(performance.now()-t0).toFixed(2)} ms: ${hashes.length} hashes`); + scannedCount += scanned; + if ( scannedCount >= maxSurveyNodes ) { + stop(); + } + processedSet.clear(); + getSurveyResults(hashes); + }; + + const surveyTimer = new vAPI.SafeAnimationFrame(doSurvey); + + // This is to shutdown the surveyor if result of surveying keeps being + // fruitless. This is useful on long-lived web page. I arbitrarily + // picked 5 minutes before the surveyor is allowed to shutdown. I also + // arbitrarily picked 256 misses before the surveyor is allowed to + // shutdown. + let canShutdownAfter = Date.now() + 300000; + let surveyResultMissCount = 0; + + // Handle main process' response. + + const processSurveyResults = response => { + if ( stopped ) { return; } + const result = response && response.result; + let mustCommit = false; + if ( result ) { + const css = result.injectedCSS; + if ( typeof css === 'string' && css.length !== 0 ) { + domFilterer.addCSS(css); + mustCommit = true; + } + const selectors = result.excepted; + if ( Array.isArray(selectors) && selectors.length !== 0 ) { + domFilterer.exceptCSSRules(selectors); + } + } + if ( hasPendingNodes() ) { + surveyTimer.start(1); + } + if ( mustCommit ) { + surveyResultMissCount = 0; + canShutdownAfter = Date.now() + 300000; + return; + } + surveyResultMissCount += 1; + if ( surveyResultMissCount < 256 || Date.now() < canShutdownAfter ) { + return; + } + //console.info(`[domSurveyor][${hostname}] Shutting down, too many misses`); + stop(); + self.vAPI.messaging.send('contentscript', { + what: 'disableGenericCosmeticFilteringSurveyor', + hostname, + }); + }; + + const domWatcherInterface = { + onDOMCreated: function() { + domFilterer = vAPI.domFilterer; + // https://github.com/uBlockOrigin/uBlock-issues/issues/1692 + // Look-up safe-only selectors to mitigate probability of + // html/body elements of erroneously being targeted. + const hashes = []; + if ( document.documentElement !== null ) { + idFromNode(document.documentElement, hashes); + classesFromNode(document.documentElement, hashes); + } + if ( document.body !== null ) { + idFromNode(document.body, hashes); + classesFromNode(document.body, hashes); + } + if ( hashes.length !== 0 ) { + getSurveyResults(hashes, true); + } + addPendingList(document.querySelectorAll( + '[id]:not(html):not(body),[class]:not(html):not(body)' + )); + if ( hasPendingNodes() ) { + surveyTimer.start(); + } + }, + onDOMChanged: function(addedNodes) { + if ( addedNodes.length === 0 ) { return; } + domChanged = true; + for ( const node of addedNodes ) { + addPendingList([ node ]); + if ( node.firstElementChild === null ) { continue; } + addPendingList( + node.querySelectorAll( + '[id]:not(html):not(body),[class]:not(html):not(body)' + ) + ); + } + if ( hasPendingNodes() ) { + surveyTimer.start(1); + } + } + }; + + const start = details => { + if ( self.vAPI instanceof Object === false ) { return; } + if ( self.vAPI.domFilterer instanceof Object === false ) { return; } + if ( self.vAPI.domWatcher instanceof Object === false ) { return; } + hostname = details.hostname; + self.vAPI.domWatcher.addListener(domWatcherInterface); + }; + + const stop = ( ) => { + stopped = true; + pendingLists.length = 0; + surveyTimer.clear(); + if ( self.vAPI instanceof Object === false ) { return; } + if ( self.vAPI.domWatcher instanceof Object ) { + self.vAPI.domWatcher.removeListener(domWatcherInterface); + } + self.vAPI.domSurveyor = null; + }; + + self.vAPI.domSurveyor = { start, addHashes }; +} + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +// vAPI.bootstrap: +// Bootstrapping allows all components of the content script +// to be launched if/when needed. + +{ + const onDomReady = ( ) => { + // This can happen on Firefox. For instance: + // https://github.com/gorhill/uBlock/issues/1893 + if ( window.location === null ) { return; } + if ( self.vAPI instanceof Object === false ) { return; } + + vAPI.messaging.send('contentscript', { + what: 'shouldRenderNoscriptTags', + }); + + if ( vAPI.domFilterer instanceof Object ) { + vAPI.domFilterer.commitNow(); + } + + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.start(); + } + + // Element picker works only in top window for now. + if ( + window !== window.top || + vAPI.domFilterer instanceof Object === false + ) { + return; + } + + // To be used by element picker/zapper. + vAPI.mouseClick = { x: -1, y: -1 }; + + const onMouseClick = function(ev) { + if ( ev.isTrusted === false ) { return; } + vAPI.mouseClick.x = ev.clientX; + vAPI.mouseClick.y = ev.clientY; + + // https://github.com/chrisaljoudi/uBlock/issues/1143 + // Find a link under the mouse, to try to avoid confusing new tabs + // as nuisance popups. + // https://github.com/uBlockOrigin/uBlock-issues/issues/777 + // Mind that href may not be a string. + const elem = ev.target.closest('a[href]'); + if ( elem === null || typeof elem.href !== 'string' ) { return; } + vAPI.messaging.send('contentscript', { + what: 'maybeGoodPopup', + url: elem.href || '', + }); + }; + + document.addEventListener('mousedown', onMouseClick, true); + + // https://github.com/gorhill/uMatrix/issues/144 + vAPI.shutdown.add(function() { + document.removeEventListener('mousedown', onMouseClick, true); + }); + }; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/403 + // If there was a spurious port disconnection -- in which case the + // response is expressly set to `null`, rather than undefined or + // an object -- let's stay around, we may be given the opportunity + // to try bootstrapping again later. + + const onResponseReady = response => { + if ( response instanceof Object === false ) { return; } + vAPI.bootstrap = undefined; + + // cosmetic filtering engine aka 'cfe' + const cfeDetails = response && response.specificCosmeticFilters; + if ( !cfeDetails || !cfeDetails.ready ) { + vAPI.domWatcher = vAPI.domCollapser = vAPI.domFilterer = + vAPI.domSurveyor = vAPI.domIsLoaded = null; + return; + } + + vAPI.domCollapser.start(); + + const { + noSpecificCosmeticFiltering, + noGenericCosmeticFiltering, + scriptletDetails, + } = response; + + vAPI.noSpecificCosmeticFiltering = noSpecificCosmeticFiltering; + vAPI.noGenericCosmeticFiltering = noGenericCosmeticFiltering; + + if ( noSpecificCosmeticFiltering && noGenericCosmeticFiltering ) { + vAPI.domFilterer = null; + vAPI.domSurveyor = null; + } else { + const domFilterer = vAPI.domFilterer = new vAPI.DOMFilterer(); + if ( noGenericCosmeticFiltering || cfeDetails.disableSurveyor ) { + vAPI.domSurveyor = null; + } + domFilterer.exceptions = cfeDetails.exceptionFilters; + domFilterer.addCSS(cfeDetails.injectedCSS); + domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters); + domFilterer.exceptCSSRules(cfeDetails.exceptedFilters); + domFilterer.convertedProceduralFilters = cfeDetails.convertedProceduralFilters; + vAPI.userStylesheet.apply(); + } + + if ( scriptletDetails && typeof self.uBO_scriptletsInjected !== 'string' ) { + self.uBO_scriptletsInjected = scriptletDetails.filters; + if ( scriptletDetails.mainWorld ) { + vAPI.injectScriptlet(document, scriptletDetails.mainWorld); + vAPI.injectedScripts = scriptletDetails.mainWorld; + } + } + + if ( vAPI.domSurveyor ) { + if ( Array.isArray(cfeDetails.genericCosmeticHashes) ) { + vAPI.domSurveyor.addHashes(cfeDetails.genericCosmeticHashes); + } + vAPI.domSurveyor.start(cfeDetails); + } + + const readyState = document.readyState; + if ( readyState === 'interactive' || readyState === 'complete' ) { + return onDomReady(); + } + document.addEventListener('DOMContentLoaded', onDomReady, { once: true }); + }; + + vAPI.bootstrap = function() { + vAPI.messaging.send('contentscript', { + what: 'retrieveContentScriptParameters', + url: vAPI.effectiveSelf.location.href, + needScriptlets: typeof self.uBO_scriptletsInjected !== 'string', + }).then(response => { + onResponseReady(response); + }); + }; +} + +// This starts bootstrap process. +vAPI.bootstrap(); + +/******************************************************************************/ +/******************************************************************************/ +/******************************************************************************/ + +} +// <<<<<<<< end of HUGE-IF-BLOCK diff --git a/src/js/contextmenu.js b/src/js/contextmenu.js new file mode 100644 index 0000000..abf0582 --- /dev/null +++ b/src/js/contextmenu.js @@ -0,0 +1,270 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import µb from './background.js'; +import { i18n$ } from './i18n.js'; + +/******************************************************************************/ + +const contextMenu = (( ) => { + +/******************************************************************************/ + +if ( vAPI.contextMenu === undefined ) { + return { + update: function() {} + }; +} + +/******************************************************************************/ + +const BLOCK_ELEMENT_BIT = 0b00001; +const BLOCK_RESOURCE_BIT = 0b00010; +const TEMP_ALLOW_LARGE_MEDIA_BIT = 0b00100; +const SUBSCRIBE_TO_LIST_BIT = 0b01000; +const VIEW_SOURCE_BIT = 0b10000; + +/******************************************************************************/ + +const onBlockElement = function(details, tab) { + if ( tab === undefined ) { return; } + if ( /^https?:\/\//.test(tab.url) === false ) { return; } + let tagName = details.tagName || ''; + let src = details.frameUrl || details.srcUrl || details.linkUrl || ''; + + if ( !tagName ) { + if ( typeof details.frameUrl === 'string' ) { + tagName = 'iframe'; + } else if ( typeof details.srcUrl === 'string' ) { + if ( details.mediaType === 'image' ) { + tagName = 'img'; + } else if ( details.mediaType === 'video' ) { + tagName = 'video'; + } else if ( details.mediaType === 'audio' ) { + tagName = 'audio'; + } + } else if ( typeof details.linkUrl === 'string' ) { + tagName = 'a'; + } + } + + µb.epickerArgs.mouse = true; + µb.elementPickerExec(tab.id, 0, `${tagName}\t${src}`); +}; + +/******************************************************************************/ + +const onBlockElementInFrame = function(details, tab) { + if ( tab === undefined ) { return; } + if ( /^https?:\/\//.test(details.frameUrl) === false ) { return; } + µb.epickerArgs.mouse = false; + µb.elementPickerExec(tab.id, details.frameId); +}; + +/******************************************************************************/ + +const onSubscribeToList = function(details) { + let parsedURL; + try { + parsedURL = new URL(details.linkUrl); + } + catch(ex) { + } + if ( parsedURL instanceof URL === false ) { return; } + const url = parsedURL.searchParams.get('location'); + if ( url === null ) { return; } + const title = parsedURL.searchParams.get('title') || '?'; + const hash = µb.selectedFilterLists.indexOf(parsedURL) !== -1 + ? '#subscribed' + : ''; + vAPI.tabs.open({ + url: + `/asset-viewer.html` + + `?url=${encodeURIComponent(url)}` + + `&title=${encodeURIComponent(title)}` + + `&subscribe=1${hash}`, + select: true, + }); +}; + +/******************************************************************************/ + +const onTemporarilyAllowLargeMediaElements = function(details, tab) { + if ( tab === undefined ) { return; } + const pageStore = µb.pageStoreFromTabId(tab.id); + if ( pageStore === null ) { return; } + pageStore.temporarilyAllowLargeMediaElements(true); +}; + +/******************************************************************************/ + +const onViewSource = function(details, tab) { + if ( tab === undefined ) { return; } + const url = details.linkUrl || details.frameUrl || details.pageUrl || ''; + if ( /^https?:\/\//.test(url) === false ) { return; } + µb.openNewTab({ + url: `code-viewer.html?url=${self.encodeURIComponent(url)}`, + select: true, + }); +}; + +/******************************************************************************/ + +const onEntryClicked = function(details, tab) { + if ( details.menuItemId === 'uBlock0-blockElement' ) { + return onBlockElement(details, tab); + } + if ( details.menuItemId === 'uBlock0-blockElementInFrame' ) { + return onBlockElementInFrame(details, tab); + } + if ( details.menuItemId === 'uBlock0-blockResource' ) { + return onBlockElement(details, tab); + } + if ( details.menuItemId === 'uBlock0-subscribeToList' ) { + return onSubscribeToList(details); + } + if ( details.menuItemId === 'uBlock0-temporarilyAllowLargeMediaElements' ) { + return onTemporarilyAllowLargeMediaElements(details, tab); + } + if ( details.menuItemId === 'uBlock0-viewSource' ) { + return onViewSource(details, tab); + } +}; + +/******************************************************************************/ + +const menuEntries = { + blockElement: { + id: 'uBlock0-blockElement', + title: i18n$('pickerContextMenuEntry'), + contexts: [ 'all' ], + documentUrlPatterns: [ 'http://*/*', 'https://*/*' ], + }, + blockElementInFrame: { + id: 'uBlock0-blockElementInFrame', + title: i18n$('contextMenuBlockElementInFrame'), + contexts: [ 'frame' ], + documentUrlPatterns: [ 'http://*/*', 'https://*/*' ], + }, + blockResource: { + id: 'uBlock0-blockResource', + title: i18n$('pickerContextMenuEntry'), + contexts: [ 'audio', 'frame', 'image', 'video' ], + documentUrlPatterns: [ 'http://*/*', 'https://*/*' ], + }, + subscribeToList: { + id: 'uBlock0-subscribeToList', + title: i18n$('contextMenuSubscribeToList'), + contexts: [ 'link' ], + targetUrlPatterns: [ 'abp:*', 'https://subscribe.adblockplus.org/*' ], + }, + temporarilyAllowLargeMediaElements: { + id: 'uBlock0-temporarilyAllowLargeMediaElements', + title: i18n$('contextMenuTemporarilyAllowLargeMediaElements'), + contexts: [ 'all' ], + documentUrlPatterns: [ 'http://*/*', 'https://*/*' ], + }, + viewSource: { + id: 'uBlock0-viewSource', + title: i18n$('contextMenuViewSource'), + contexts: [ 'page', 'frame', 'link' ], + documentUrlPatterns: [ 'http://*/*', 'https://*/*' ], + }, +}; + +/******************************************************************************/ + +let currentBits = 0; + +const update = function(tabId = undefined) { + let newBits = 0; + if ( µb.userSettings.contextMenuEnabled && tabId !== undefined ) { + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore && pageStore.getNetFilteringSwitch() ) { + if ( pageStore.shouldApplySpecificCosmeticFilters(0) ) { + newBits |= BLOCK_ELEMENT_BIT; + } else { + newBits |= BLOCK_RESOURCE_BIT; + } + if ( pageStore.largeMediaCount !== 0 ) { + newBits |= TEMP_ALLOW_LARGE_MEDIA_BIT; + } + } + newBits |= SUBSCRIBE_TO_LIST_BIT; + } + if ( µb.hiddenSettings.filterAuthorMode ) { + newBits |= VIEW_SOURCE_BIT; + } + if ( newBits === currentBits ) { return; } + currentBits = newBits; + const usedEntries = []; + if ( (newBits & BLOCK_ELEMENT_BIT) !== 0 ) { + usedEntries.push(menuEntries.blockElement); + usedEntries.push(menuEntries.blockElementInFrame); + } + if ( (newBits & BLOCK_RESOURCE_BIT) !== 0 ) { + usedEntries.push(menuEntries.blockResource); + } + if ( (newBits & TEMP_ALLOW_LARGE_MEDIA_BIT) !== 0 ) { + usedEntries.push(menuEntries.temporarilyAllowLargeMediaElements); + } + if ( (newBits & SUBSCRIBE_TO_LIST_BIT) !== 0 ) { + usedEntries.push(menuEntries.subscribeToList); + } + if ( (newBits & VIEW_SOURCE_BIT) !== 0 ) { + usedEntries.push(menuEntries.viewSource); + } + vAPI.contextMenu.setEntries(usedEntries, onEntryClicked); +}; + +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/151 +// For unknown reasons, the currently active tab will not be successfully +// looked up after closing a window. + +vAPI.contextMenu.onMustUpdate = async function(tabId = undefined) { + if ( µb.userSettings.contextMenuEnabled === false ) { + return update(); + } + if ( tabId !== undefined ) { + return update(tabId); + } + const tab = await vAPI.tabs.getCurrent(); + if ( tab instanceof Object === false ) { return; } + update(tab.id); +}; + +return { update: vAPI.contextMenu.onMustUpdate }; + +/******************************************************************************/ + +})(); + +/******************************************************************************/ + +export default contextMenu; + +/******************************************************************************/ diff --git a/src/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js new file mode 100644 index 0000000..f4782bc --- /dev/null +++ b/src/js/cosmetic-filtering.js @@ -0,0 +1,983 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import logger from './logger.js'; +import µb from './background.js'; + +import { MRUCache } from './mrucache.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; + +/******************************************************************************/ +/******************************************************************************/ + +const SelectorCacheEntry = class { + constructor() { + this.reset(); + } + + reset() { + this.cosmetic = new Set(); + this.cosmeticHashes = new Set(); + this.disableSurveyor = false; + this.net = new Map(); + this.accessId = SelectorCacheEntry.accessId++; + return this; + } + + dispose() { + this.cosmetic = this.cosmeticHashes = this.net = null; + if ( SelectorCacheEntry.junkyard.length < 25 ) { + SelectorCacheEntry.junkyard.push(this); + } + } + + addCosmetic(details) { + const selectors = details.selectors.join(',\n'); + if ( selectors.length !== 0 ) { + this.cosmetic.add(selectors); + } + for ( const hash of details.hashes ) { + this.cosmeticHashes.add(hash); + } + } + + addNet(selectors) { + if ( typeof selectors === 'string' ) { + this.net.set(selectors, this.accessId); + } else { + this.net.set(selectors.join(',\n'), this.accessId); + } + // Net request-derived selectors: I limit the number of cached + // selectors, as I expect cases where the blocked network requests + // are never the exact same URL. + if ( this.net.size < SelectorCacheEntry.netHighWaterMark ) { return; } + const keys = Array.from(this.net) + .sort((a, b) => b[1] - a[1]) + .slice(SelectorCacheEntry.netLowWaterMark) + .map(a => a[0]); + for ( const key of keys ) { + this.net.delete(key); + } + } + + addNetOne(selector, token) { + this.net.set(selector, token); + } + + add(details) { + this.accessId = SelectorCacheEntry.accessId++; + if ( details.type === 'cosmetic' ) { + this.addCosmetic(details); + } else { + this.addNet(details.selectors); + } + } + + // https://github.com/chrisaljoudi/uBlock/issues/420 + remove(type) { + this.accessId = SelectorCacheEntry.accessId++; + if ( type === undefined || type === 'cosmetic' ) { + this.cosmetic.clear(); + } + if ( type === undefined || type === 'net' ) { + this.net.clear(); + } + } + + retrieveToArray(iterator, out) { + for ( const selector of iterator ) { + out.push(selector); + } + } + + retrieveToSet(iterator, out) { + for ( const selector of iterator ) { + out.add(selector); + } + } + + retrieveNet(out) { + this.accessId = SelectorCacheEntry.accessId++; + if ( this.net.size === 0 ) { return false; } + this.retrieveToArray(this.net.keys(), out); + return true; + } + + retrieveCosmetic(selectors, hashes) { + this.accessId = SelectorCacheEntry.accessId++; + if ( this.cosmetic.size === 0 ) { return false; } + this.retrieveToSet(this.cosmetic, selectors); + this.retrieveToArray(this.cosmeticHashes, hashes); + return true; + } + + static factory() { + const entry = SelectorCacheEntry.junkyard.pop(); + return entry + ? entry.reset() + : new SelectorCacheEntry(); + } +}; + +SelectorCacheEntry.accessId = 1; +SelectorCacheEntry.netLowWaterMark = 20; +SelectorCacheEntry.netHighWaterMark = 30; +SelectorCacheEntry.junkyard = []; + +/******************************************************************************/ +/******************************************************************************/ + +// http://www.cse.yorku.ca/~oz/hash.html#djb2 +// Must mirror content script surveyor's version + +const hashFromStr = (type, s) => { + const len = s.length; + const step = len + 7 >>> 3; + let hash = (type << 5) + type ^ len; + for ( let i = 0; i < len; i += step ) { + hash = (hash << 5) + hash ^ s.charCodeAt(i); + } + return hash & 0xFFFFFF; +}; + +// https://github.com/gorhill/uBlock/issues/1668 +// The key must be literal: unescape escaped CSS before extracting key. +// It's an uncommon case, so it's best to unescape only when needed. + +const keyFromSelector = selector => { + let key = ''; + let matches = rePlainSelector.exec(selector); + if ( matches !== null ) { + key = matches[0]; + } else { + matches = rePlainSelectorEx.exec(selector); + if ( matches === null ) { return; } + key = matches[1] || matches[2]; + } + if ( key.includes('\\') === false ) { return key; } + matches = rePlainSelectorEscaped.exec(selector); + if ( matches === null ) { return; } + key = ''; + const escaped = matches[0]; + let beg = 0; + reEscapeSequence.lastIndex = 0; + for (;;) { + matches = reEscapeSequence.exec(escaped); + if ( matches === null ) { + return key + escaped.slice(beg); + } + key += escaped.slice(beg, matches.index); + beg = reEscapeSequence.lastIndex; + if ( matches[1].length === 1 ) { + key += matches[1]; + } else { + key += String.fromCharCode(parseInt(matches[1], 16)); + } + } +}; + +const rePlainSelector = /^[#.][\w\\-]+/; +const rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)|([#.][\w-]+)$/; +const rePlainSelectorEscaped = /^[#.](?:\\[0-9A-Fa-f]+ |\\.|\w|-)+/; +const reEscapeSequence = /\\([0-9A-Fa-f]+ |.)/g; + +/******************************************************************************/ +/******************************************************************************/ + +// Cosmetic filter family tree: +// +// Generic +// Low generic simple: class or id only +// Low generic complex: class or id + extra stuff after +// High generic: +// High-low generic: [alt="..."],[title="..."] +// High-medium generic: [href^="..."] +// High-high generic: everything else +// Specific +// Specific hostname +// Specific entity +// Generic filters can only be enforced once the main document is loaded. +// Specific filers can be enforced before the main document is loaded. + +const FilterContainer = function() { + this.reSimpleHighGeneric = /^(?:[a-z]*\[[^\]]+\]|\S+)$/; + + this.selectorCache = new Map(); + this.selectorCachePruneDelay = 10; // 10 minutes + this.selectorCacheCountMin = 40; + this.selectorCacheCountMax = 50; + this.selectorCacheTimer = vAPI.defer.create(( ) => { + this.pruneSelectorCacheAsync(); + }); + + // specific filters + this.specificFilters = new StaticExtFilteringHostnameDB(2); + + // low generic cosmetic filters: map of hash => stringified selector list + this.lowlyGeneric = new Map(); + + // highly generic selectors sets + this.highlyGeneric = Object.create(null); + this.highlyGeneric.simple = { + canonical: 'highGenericHideSimple', + dict: new Set(), + str: '', + mru: new MRUCache(16) + }; + this.highlyGeneric.complex = { + canonical: 'highGenericHideComplex', + dict: new Set(), + str: '', + mru: new MRUCache(16) + }; + + // Short-lived: content is valid only during one function call. These + // is to prevent repeated allocation/deallocation overheads -- the + // constructors/destructors of javascript Set/Map is assumed to be costlier + // than just calling clear() on these. + this.$specificSet = new Set(); + this.$exceptionSet = new Set(); + this.$proceduralSet = new Set(); + this.$dummySet = new Set(); + + this.reset(); +}; + +/******************************************************************************/ + +// Reset all, thus reducing to a minimum memory footprint of the context. + +FilterContainer.prototype.reset = function() { + this.frozen = false; + this.acceptedCount = 0; + this.discardedCount = 0; + this.duplicateBuster = new Set(); + + this.selectorCache.clear(); + this.selectorCacheTimer.off(); + + // hostname, entity-based filters + this.specificFilters.clear(); + + // low generic cosmetic filters + this.lowlyGeneric.clear(); + + // highly generic selectors sets + this.highlyGeneric.simple.dict.clear(); + this.highlyGeneric.simple.str = ''; + this.highlyGeneric.simple.mru.reset(); + this.highlyGeneric.complex.dict.clear(); + this.highlyGeneric.complex.str = ''; + this.highlyGeneric.complex.mru.reset(); + + this.selfieVersion = 1; +}; + +/******************************************************************************/ + +FilterContainer.prototype.freeze = function() { + this.duplicateBuster.clear(); + this.specificFilters.collectGarbage(); + + this.highlyGeneric.simple.str = Array.from(this.highlyGeneric.simple.dict).join(',\n'); + this.highlyGeneric.simple.mru.reset(); + this.highlyGeneric.complex.str = Array.from(this.highlyGeneric.complex.dict).join(',\n'); + this.highlyGeneric.complex.mru.reset(); + + this.frozen = true; +}; + +/******************************************************************************/ + +FilterContainer.prototype.compile = function(parser, writer) { + if ( parser.hasOptions() === false ) { + this.compileGenericSelector(parser, writer); + return true; + } + + // 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. + 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 ( applyGlobally ) { + this.compileGenericSelector(parser, writer); + } + + return true; +}; + +/******************************************************************************/ + +FilterContainer.prototype.compileGenericSelector = function(parser, writer) { + if ( parser.isException() ) { + this.compileGenericUnhideSelector(parser, writer); + } else { + this.compileGenericHideSelector(parser, writer); + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.compileGenericHideSelector = function( + parser, + writer +) { + const { raw, compiled } = parser.result; + if ( compiled === undefined ) { + const who = writer.properties.get('name') || '?'; + logger.writeOne({ + realm: 'message', + type: 'error', + text: `Invalid generic cosmetic filter in ${who}: ${raw}` + }); + return; + } + + writer.select('COSMETIC_FILTERS:GENERIC'); + + // https://github.com/uBlockOrigin/uBlock-issues/issues/131 + // Support generic procedural filters as per advanced settings. + if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) { + if ( µb.hiddenSettings.allowGenericProceduralFilters === true ) { + return this.compileSpecificSelector(parser, '', false, writer); + } + const who = writer.properties.get('name') || '?'; + logger.writeOne({ + realm: 'message', + type: 'error', + text: `Invalid generic cosmetic filter in ${who}: ##${raw}` + }); + return; + } + + const key = keyFromSelector(compiled); + if ( key !== undefined ) { + writer.push([ + 0, + hashFromStr(key.charCodeAt(0), key.slice(1)), + compiled, + ]); + return; + } + + // Pass this point, we are dealing with highly-generic cosmetic filters. + // + // For efficiency purpose, we will distinguish between simple and complex + // selectors. + + if ( this.reSimpleHighGeneric.test(compiled) ) { + writer.push([ 4 /* simple */, compiled ]); + } else { + writer.push([ 5 /* complex */, compiled ]); + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.compileGenericUnhideSelector = function( + parser, + writer +) { + // Procedural cosmetic filters are acceptable as generic exception filters. + const { raw, compiled } = parser.result; + if ( compiled === undefined ) { + const who = writer.properties.get('name') || '?'; + logger.writeOne({ + realm: 'message', + type: 'error', + text: `Invalid cosmetic filter in ${who}: #@#${raw}` + }); + return; + } + + writer.select('COSMETIC_FILTERS:SPECIFIC'); + + // https://github.com/chrisaljoudi/uBlock/issues/497 + // All generic exception filters are stored as hostname-based filter + // whereas the hostname is the empty string (which matches all + // hostnames). No distinction is made between declarative and + // procedural selectors, since they really exist only to cancel + // out other cosmetic filters. + writer.push([ 8, '', 0b001, compiled ]); +}; + +/******************************************************************************/ + +FilterContainer.prototype.compileSpecificSelector = function( + parser, + hostname, + not, + writer +) { + const { raw, compiled, exception } = parser.result; + if ( compiled === undefined ) { + const who = writer.properties.get('name') || '?'; + logger.writeOne({ + realm: 'message', + type: 'error', + text: `Invalid cosmetic filter in ${who}: ##${raw}` + }); + return; + } + + writer.select('COSMETIC_FILTERS:SPECIFIC'); + + // https://github.com/chrisaljoudi/uBlock/issues/145 + let unhide = exception ? 1 : 0; + if ( not ) { unhide ^= 1; } + + let kind = 0; + if ( unhide === 1 ) { + kind |= 0b001; // Exception + } + if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) { + kind |= 0b010; // Procedural + } + if ( hostname === '*' ) { + kind |= 0b100; // Applies everywhere + } + + writer.push([ 8, hostname, kind, compiled ]); +}; + +/******************************************************************************/ + +FilterContainer.prototype.fromCompiledContent = function(reader, options) { + if ( options.skipCosmetic ) { + this.skipCompiledContent(reader, 'SPECIFIC'); + this.skipCompiledContent(reader, 'GENERIC'); + return; + } + + // Specific cosmetic filter section + reader.select('COSMETIC_FILTERS:SPECIFIC'); + while ( reader.next() ) { + this.acceptedCount += 1; + const fingerprint = reader.fingerprint(); + if ( this.duplicateBuster.has(fingerprint) ) { + this.discardedCount += 1; + continue; + } + this.duplicateBuster.add(fingerprint); + const args = reader.args(); + switch ( args[0] ) { + // hash, example.com, .promoted-tweet + // hash, example.*, .promoted-tweet + // + // https://github.com/uBlockOrigin/uBlock-issues/issues/803 + // Handle specific filters meant to apply everywhere, i.e. selectors + // not to be injected conditionally through the DOM surveyor. + // hash, *, .promoted-tweet + case 8: + if ( args[2] === 0b100 ) { + if ( this.reSimpleHighGeneric.test(args[3]) ) + this.highlyGeneric.simple.dict.add(args[3]); + else { + this.highlyGeneric.complex.dict.add(args[3]); + } + break; + } + this.specificFilters.store(args[1], args[2] & 0b011, args[3]); + break; + default: + this.discardedCount += 1; + break; + } + } + + if ( options.skipGenericCosmetic ) { + this.skipCompiledContent(reader, 'GENERIC'); + return; + } + + // Generic cosmetic filter section + reader.select('COSMETIC_FILTERS:GENERIC'); + while ( reader.next() ) { + this.acceptedCount += 1; + const fingerprint = reader.fingerprint(); + if ( this.duplicateBuster.has(fingerprint) ) { + this.discardedCount += 1; + continue; + } + this.duplicateBuster.add(fingerprint); + const args = reader.args(); + switch ( args[0] ) { + // low generic + case 0: { + if ( this.lowlyGeneric.has(args[1]) ) { + const selector = this.lowlyGeneric.get(args[1]); + this.lowlyGeneric.set(args[1], `${selector},\n${args[2]}`); + } else { + this.lowlyGeneric.set(args[1], args[2]); + } + break; + } + // High-high generic hide/simple selectors + // div[id^="allo"] + case 4: + this.highlyGeneric.simple.dict.add(args[1]); + break; + // High-high generic hide/complex selectors + // div[id^="allo"] > span + case 5: + this.highlyGeneric.complex.dict.add(args[1]); + break; + default: + this.discardedCount += 1; + break; + } + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.skipCompiledContent = function(reader, sectionId) { + reader.select(`COSMETIC_FILTERS:${sectionId}`); + while ( reader.next() ) { + this.acceptedCount += 1; + this.discardedCount += 1; + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.toSelfie = function() { + return { + version: this.selfieVersion, + acceptedCount: this.acceptedCount, + discardedCount: this.discardedCount, + specificFilters: this.specificFilters.toSelfie(), + lowlyGeneric: Array.from(this.lowlyGeneric), + highSimpleGenericHideArray: Array.from(this.highlyGeneric.simple.dict), + highComplexGenericHideArray: Array.from(this.highlyGeneric.complex.dict), + }; +}; + +/******************************************************************************/ + +FilterContainer.prototype.fromSelfie = function(selfie) { + if ( selfie.version !== this.selfieVersion ) { + throw new Error( + `cosmeticFilteringEngine: mismatched selfie version, ${selfie.version}, expected ${this.selfieVersion}` + ); + } + this.acceptedCount = selfie.acceptedCount; + this.discardedCount = selfie.discardedCount; + this.specificFilters.fromSelfie(selfie.specificFilters); + this.lowlyGeneric = new Map(selfie.lowlyGeneric); + this.highlyGeneric.simple.dict = new Set(selfie.highSimpleGenericHideArray); + this.highlyGeneric.simple.str = selfie.highSimpleGenericHideArray.join(',\n'); + this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray); + this.highlyGeneric.complex.str = selfie.highComplexGenericHideArray.join(',\n'); + this.frozen = true; +}; + +/******************************************************************************/ + +FilterContainer.prototype.addToSelectorCache = function(details) { + const hostname = details.hostname; + if ( typeof hostname !== 'string' || hostname === '' ) { return; } + const selectors = details.selectors; + if ( Array.isArray(selectors) === false ) { return; } + let entry = this.selectorCache.get(hostname); + if ( entry === undefined ) { + entry = SelectorCacheEntry.factory(); + this.selectorCache.set(hostname, entry); + if ( this.selectorCache.size > this.selectorCacheCountMax ) { + this.selectorCacheTimer.on({ min: this.selectorCachePruneDelay }); + } + } + entry.add(details); +}; + +/******************************************************************************/ + +FilterContainer.prototype.removeFromSelectorCache = function( + targetHostname = '*', + type = undefined +) { + const targetHostnameLength = targetHostname.length; + for ( let entry of this.selectorCache ) { + let hostname = entry[0]; + let item = entry[1]; + if ( targetHostname !== '*' ) { + if ( hostname.endsWith(targetHostname) === false ) { continue; } + if ( + hostname.length !== targetHostnameLength && + hostname.charAt(hostname.length - targetHostnameLength - 1) !== '.' + ) { + continue; + } + } + item.remove(type); + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.pruneSelectorCacheAsync = function() { + if ( this.selectorCache.size <= this.selectorCacheCountMax ) { return; } + const cache = this.selectorCache; + const hostnames = Array.from(cache.keys()) + .sort((a, b) => cache.get(b).accessId - cache.get(a).accessId) + .slice(this.selectorCacheCountMin); + for ( const hn of hostnames ) { + cache.get(hn).dispose(); + cache.delete(hn); + } +}; + +/******************************************************************************/ + +FilterContainer.prototype.disableSurveyor = function(details) { + const hostname = details.hostname; + if ( typeof hostname !== 'string' || hostname === '' ) { return; } + const cacheEntry = this.selectorCache.get(hostname); + if ( cacheEntry === undefined ) { return; } + cacheEntry.disableSurveyor = true; +}; + +/******************************************************************************/ + +FilterContainer.prototype.cssRuleFromProcedural = function(pfilter) { + if ( pfilter.cssable !== true ) { return; } + const { tasks, action } = pfilter; + let mq, selector; + if ( Array.isArray(tasks) ) { + if ( tasks[0][0] !== 'matches-media' ) { return; } + mq = tasks[0][1]; + if ( tasks.length > 2 ) { return; } + if ( tasks.length === 2 ) { + if ( tasks[1][0] !== 'spath' ) { return; } + selector = tasks[1][1]; + } + } + let style; + if ( Array.isArray(action) ) { + if ( action[0] !== 'style' ) { return; } + selector = selector || pfilter.selector; + style = action[1]; + } + if ( mq === undefined && style === undefined && selector === undefined ) { return; } + if ( mq === undefined ) { + return `${selector}\n{${style}}`; + } + if ( style === undefined ) { + return `@media ${mq} {\n${selector}\n{display:none!important;}\n}`; + } + return `@media ${mq} {\n${selector}\n{${style}}\n}`; +}; + +/******************************************************************************/ + +FilterContainer.prototype.retrieveGenericSelectors = function(request) { + if ( this.lowlyGeneric.size === 0 ) { return; } + if ( Array.isArray(request.hashes) === false ) { return; } + if ( request.hashes.length === 0 ) { return; } + + const selectorsSet = new Set(); + const hashes = []; + const safeOnly = request.safeOnly === true; + for ( const hash of request.hashes ) { + const bucket = this.lowlyGeneric.get(hash); + if ( bucket === undefined ) { continue; } + for ( const selector of bucket.split(',\n') ) { + if ( safeOnly && selector === keyFromSelector(selector) ) { continue; } + selectorsSet.add(selector); + } + hashes.push(hash); + } + + // Apply exceptions: it is the responsibility of the caller to provide + // the exceptions to be applied. + const excepted = []; + if ( selectorsSet.size !== 0 && Array.isArray(request.exceptions) ) { + for ( const exception of request.exceptions ) { + if ( selectorsSet.delete(exception) ) { + excepted.push(exception); + } + } + } + + if ( selectorsSet.size === 0 && excepted.length === 0 ) { return; } + + const out = { injectedCSS: '', excepted, }; + const selectors = Array.from(selectorsSet); + + if ( typeof request.hostname === 'string' && request.hostname !== '' ) { + this.addToSelectorCache({ + hostname: request.hostname, + selectors, + hashes, + type: 'cosmetic', + }); + } + + if ( selectors.length === 0 ) { return out; } + + out.injectedCSS = `${selectors.join(',\n')}\n{display:none!important;}`; + vAPI.tabs.insertCSS(request.tabId, { + code: out.injectedCSS, + frameId: request.frameId, + matchAboutBlank: true, + runAt: 'document_start', + }); + + return out; +}; + +/******************************************************************************/ + +FilterContainer.prototype.retrieveSpecificSelectors = function( + request, + options +) { + const hostname = request.hostname; + const cacheEntry = this.selectorCache.get(hostname); + + // https://github.com/chrisaljoudi/uBlock/issues/587 + // out.ready will tell the content script the cosmetic filtering engine is + // up and ready. + + // https://github.com/chrisaljoudi/uBlock/issues/497 + // Generic exception filters are to be applied on all pages. + + const out = { + ready: this.frozen, + hostname: hostname, + domain: request.domain, + exceptionFilters: [], + exceptedFilters: [], + proceduralFilters: [], + convertedProceduralFilters: [], + disableSurveyor: this.lowlyGeneric.size === 0, + }; + const injectedCSS = []; + + if ( + options.noSpecificCosmeticFiltering !== true || + options.noGenericCosmeticFiltering !== true + ) { + const specificSet = this.$specificSet; + const proceduralSet = this.$proceduralSet; + const exceptionSet = this.$exceptionSet; + const dummySet = this.$dummySet; + + // Cached cosmetic filters: these are always declarative. + if ( cacheEntry !== undefined ) { + cacheEntry.retrieveCosmetic(specificSet, out.genericCosmeticHashes = []); + if ( cacheEntry.disableSurveyor ) { + out.disableSurveyor = true; + } + } + + // Retrieve filters with a non-empty hostname + const retrieveSets = [ specificSet, exceptionSet, proceduralSet, exceptionSet ]; + const discardSets = [ dummySet, exceptionSet ]; + this.specificFilters.retrieve( + hostname, + options.noSpecificCosmeticFiltering ? discardSets : retrieveSets, + 1 + ); + // Retrieve filters with a regex-based hostname value + this.specificFilters.retrieve( + hostname, + options.noSpecificCosmeticFiltering ? discardSets : retrieveSets, + 3 + ); + // Retrieve filters with a entity-based hostname value + if ( request.entity !== '' ) { + this.specificFilters.retrieve( + `${hostname.slice(0, -request.domain.length)}${request.entity}`, + options.noSpecificCosmeticFiltering ? discardSets : retrieveSets, + 1 + ); + } + // Retrieve filters with an empty hostname + this.specificFilters.retrieve( + hostname, + options.noGenericCosmeticFiltering ? discardSets : retrieveSets, + 2 + ); + + // Apply exceptions to specific filterset + if ( exceptionSet.size !== 0 ) { + out.exceptionFilters = Array.from(exceptionSet); + for ( const selector of specificSet ) { + if ( exceptionSet.has(selector) === false ) { continue; } + specificSet.delete(selector); + out.exceptedFilters.push(selector); + } + } + + if ( specificSet.size !== 0 ) { + injectedCSS.push( + `${Array.from(specificSet).join(',\n')}\n{display:none!important;}` + ); + } + + // Apply exceptions to procedural filterset. + // Also, some procedural filters are really declarative cosmetic + // filters, so we extract and inject them immediately. + if ( proceduralSet.size !== 0 ) { + for ( const json of proceduralSet ) { + const pfilter = JSON.parse(json); + if ( exceptionSet.has(json) ) { + proceduralSet.delete(json); + out.exceptedFilters.push(json); + continue; + } + if ( exceptionSet.has(pfilter.raw) ) { + proceduralSet.delete(json); + out.exceptedFilters.push(pfilter.raw); + continue; + } + const cssRule = this.cssRuleFromProcedural(pfilter); + if ( cssRule === undefined ) { continue; } + injectedCSS.push(cssRule); + proceduralSet.delete(json); + out.convertedProceduralFilters.push(json); + } + out.proceduralFilters.push(...proceduralSet); + } + + // Highly generic cosmetic filters: sent once along with specific ones. + // A most-recent-used cache is used to skip computing the resulting set + // of high generics for a given set of exceptions. + // The resulting set of high generics is stored as a string, ready to + // be used as-is by the content script. The string is stored + // indirectly in the mru cache: this is to prevent duplication of the + // string in memory, which I have observed occurs when the string is + // stored directly as a value in a Map. + if ( options.noGenericCosmeticFiltering !== true ) { + const exceptionSetHash = out.exceptionFilters.join(); + for ( const key in this.highlyGeneric ) { + const entry = this.highlyGeneric[key]; + let str = entry.mru.lookup(exceptionSetHash); + if ( str === undefined ) { + str = { s: entry.str, excepted: [] }; + let genericSet = entry.dict; + let hit = false; + for ( const exception of exceptionSet ) { + if ( (hit = genericSet.has(exception)) ) { break; } + } + if ( hit ) { + genericSet = new Set(entry.dict); + for ( const exception of exceptionSet ) { + if ( genericSet.delete(exception) ) { + str.excepted.push(exception); + } + } + str.s = Array.from(genericSet).join(',\n'); + } + entry.mru.add(exceptionSetHash, str); + } + if ( str.excepted.length !== 0 ) { + out.exceptedFilters.push(...str.excepted); + } + if ( str.s.length !== 0 ) { + injectedCSS.push(`${str.s}\n{display:none!important;}`); + } + } + } + + // Important: always clear used registers before leaving. + specificSet.clear(); + proceduralSet.clear(); + exceptionSet.clear(); + dummySet.clear(); + } + + const details = { + code: '', + frameId: request.frameId, + matchAboutBlank: true, + runAt: 'document_start', + }; + + // Inject all declarative-based filters as a single stylesheet. + if ( injectedCSS.length !== 0 ) { + out.injectedCSS = injectedCSS.join('\n\n'); + details.code = out.injectedCSS; + if ( request.tabId !== undefined ) { + vAPI.tabs.insertCSS(request.tabId, details); + } + } + + // CSS selectors for collapsible blocked elements + if ( cacheEntry ) { + const networkFilters = []; + if ( cacheEntry.retrieveNet(networkFilters) ) { + details.code = `${networkFilters.join('\n')}\n{display:none!important;}`; + if ( request.tabId !== undefined ) { + vAPI.tabs.insertCSS(request.tabId, details); + } + } + } + + return out; +}; + +/******************************************************************************/ + +FilterContainer.prototype.getFilterCount = function() { + return this.acceptedCount - this.discardedCount; +}; + +/******************************************************************************/ + +FilterContainer.prototype.dump = function() { + const lowlyGenerics = []; + for ( const selectors of this.lowlyGeneric.values() ) { + lowlyGenerics.push(...selectors.split(',\n')); + } + lowlyGenerics.sort(); + const highlyGenerics = Array.from(this.highlyGeneric.simple.dict).sort(); + highlyGenerics.push(...Array.from(this.highlyGeneric.complex.dict).sort()); + return [ + 'Cosmetic Filtering Engine internals:', + `specific: ${this.specificFilters.size}`, + `generic: ${lowlyGenerics.length + highlyGenerics.length}`, + `+ lowly generic: ${lowlyGenerics.length}`, + ...lowlyGenerics.map(a => ` ${a}`), + `+ highly generic: ${highlyGenerics.length}`, + ...highlyGenerics.map(a => ` ${a}`), + ].join('\n'); +}; + +/******************************************************************************/ + +const cosmeticFilteringEngine = new FilterContainer(); + +export default cosmeticFilteringEngine; + +/******************************************************************************/ diff --git a/src/js/dashboard-common.js b/src/js/dashboard-common.js new file mode 100644 index 0000000..feceb1f --- /dev/null +++ b/src/js/dashboard-common.js @@ -0,0 +1,215 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +import { dom } from './dom.js'; + +/******************************************************************************/ + +self.uBlockDashboard = self.uBlockDashboard || {}; + +/******************************************************************************/ + +// Helper for client panes: +// Remove literal duplicate lines from a set based on another set. + +self.uBlockDashboard.mergeNewLines = function(text, newText) { + // Step 1: build dictionary for existing lines. + const fromDict = new Map(); + let lineBeg = 0; + let textEnd = text.length; + while ( lineBeg < textEnd ) { + let lineEnd = text.indexOf('\n', lineBeg); + if ( lineEnd === -1 ) { + lineEnd = text.indexOf('\r', lineBeg); + if ( lineEnd === -1 ) { + lineEnd = textEnd; + } + } + const line = text.slice(lineBeg, lineEnd).trim(); + lineBeg = lineEnd + 1; + if ( line.length === 0 ) { continue; } + const hash = line.slice(0, 8); + const bucket = fromDict.get(hash); + if ( bucket === undefined ) { + fromDict.set(hash, line); + } else if ( typeof bucket === 'string' ) { + fromDict.set(hash, [ bucket, line ]); + } else /* if ( Array.isArray(bucket) ) */ { + bucket.push(line); + } + } + + // Step 2: use above dictionary to filter out duplicate lines. + const out = [ '' ]; + lineBeg = 0; + textEnd = newText.length; + while ( lineBeg < textEnd ) { + let lineEnd = newText.indexOf('\n', lineBeg); + if ( lineEnd === -1 ) { + lineEnd = newText.indexOf('\r', lineBeg); + if ( lineEnd === -1 ) { + lineEnd = textEnd; + } + } + const line = newText.slice(lineBeg, lineEnd).trim(); + lineBeg = lineEnd + 1; + if ( line.length === 0 ) { + if ( out[out.length - 1] !== '' ) { + out.push(''); + } + continue; + } + const bucket = fromDict.get(line.slice(0, 8)); + if ( bucket === undefined ) { + out.push(line); + continue; + } + if ( typeof bucket === 'string' && line !== bucket ) { + out.push(line); + continue; + } + if ( bucket.indexOf(line) === -1 ) { + out.push(line); + /* continue; */ + } + } + + const append = out.join('\n').trim(); + if ( text !== '' && append !== '' ) { + text += '\n\n'; + } + return text + append; +}; + +/******************************************************************************/ + +self.uBlockDashboard.dateNowToSensibleString = function() { + const now = new Date(Date.now() - (new Date()).getTimezoneOffset() * 60000); + return now.toISOString().replace(/\.\d+Z$/, '') + .replace(/:/g, '.') + .replace('T', '_'); +}; + +/******************************************************************************/ + +self.uBlockDashboard.patchCodeMirrorEditor = (function() { + let grabFocusTarget; + + const grabFocus = function() { + grabFocusTarget.focus(); + grabFocusTarget = undefined; + }; + + const grabFocusTimer = vAPI.defer.create(grabFocus); + + const grabFocusAsync = function(cm) { + grabFocusTarget = cm; + grabFocusTimer.on(1); + }; + + // https://github.com/gorhill/uBlock/issues/3646 + const patchSelectAll = function(cm, details) { + var vp = cm.getViewport(); + if ( details.ranges.length !== 1 ) { return; } + var range = details.ranges[0], + lineFrom = range.anchor.line, + lineTo = range.head.line; + if ( lineTo === lineFrom ) { return; } + if ( range.head.ch !== 0 ) { lineTo += 1; } + if ( lineFrom !== vp.from || lineTo !== vp.to ) { return; } + details.update([ + { + anchor: { line: 0, ch: 0 }, + head: { line: cm.lineCount(), ch: 0 } + } + ]); + grabFocusAsync(cm); + }; + + let lastGutterClick = 0; + let lastGutterLine = 0; + + const onGutterClicked = function(cm, line, gutter) { + if ( gutter !== 'CodeMirror-linenumbers' ) { return; } + grabFocusAsync(cm); + const delta = Date.now() - lastGutterClick; + // Single click + if ( delta >= 500 || line !== lastGutterLine ) { + cm.setSelection( + { line, ch: 0 }, + { line: line + 1, ch: 0 } + ); + lastGutterClick = Date.now(); + lastGutterLine = line; + return; + } + // Double click: select fold-able block or all + let lineFrom = 0; + let lineTo = cm.lineCount(); + const foldFn = cm.getHelper({ line, ch: 0 }, 'fold'); + if ( foldFn instanceof Function ) { + const range = foldFn(cm, { line, ch: 0 }); + if ( range !== undefined ) { + lineFrom = range.from.line; + lineTo = range.to.line + 1; + } + } + cm.setSelection( + { line: lineFrom, ch: 0 }, + { line: lineTo, ch: 0 }, + { scroll: false } + ); + lastGutterClick = 0; + }; + + return function(cm) { + if ( cm.options.inputStyle === 'contenteditable' ) { + cm.on('beforeSelectionChange', patchSelectAll); + } + cm.on('gutterClick', onGutterClicked); + }; +})(); + +/******************************************************************************/ + +self.uBlockDashboard.openOrSelectPage = function(url, options = {}) { + let ev; + if ( url instanceof MouseEvent ) { + ev = url; + url = dom.attr(ev.target, 'href'); + } + const details = Object.assign({ url, select: true, index: -1 }, options); + vAPI.messaging.send('default', { + what: 'gotoURL', + details, + }); + if ( ev ) { + ev.preventDefault(); + } +}; + +/******************************************************************************/ + +// Open links in the proper window +dom.attr('a', 'target', '_blank'); +dom.attr('a[href*="dashboard.html"]', 'target', '_parent'); diff --git a/src/js/dashboard.js b/src/js/dashboard.js new file mode 100644 index 0000000..e82ec28 --- /dev/null +++ b/src/js/dashboard.js @@ -0,0 +1,166 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +import { dom, qs$ } from './dom.js'; + +/******************************************************************************/ + +const discardUnsavedData = function(synchronous = false) { + const paneFrame = qs$('#iframe'); + const paneWindow = paneFrame.contentWindow; + if ( + typeof paneWindow.hasUnsavedData !== 'function' || + paneWindow.hasUnsavedData() === false + ) { + return true; + } + + if ( synchronous ) { + return false; + } + + return new Promise(resolve => { + const modal = qs$('#unsavedWarning'); + dom.cl.add(modal, 'on'); + modal.focus(); + + const onDone = status => { + dom.cl.remove(modal, 'on'); + dom.off(document, 'click', onClick, true); + resolve(status); + }; + + const onClick = ev => { + const target = ev.target; + if ( target.matches('[data-i18n="dashboardUnsavedWarningStay"]') ) { + return onDone(false); + } + if ( target.matches('[data-i18n="dashboardUnsavedWarningIgnore"]') ) { + return onDone(true); + } + if ( qs$(modal, '[data-i18n="dashboardUnsavedWarning"]').contains(target) ) { + return; + } + onDone(false); + }; + + dom.on(document, 'click', onClick, true); + }); +}; + +const loadDashboardPanel = function(pane, first) { + const tabButton = qs$(`[data-pane="${pane}"]`); + if ( tabButton === null || dom.cl.has(tabButton, 'selected') ) { return; } + const loadPane = ( ) => { + self.location.replace(`#${pane}`); + dom.cl.remove('.tabButton.selected', 'selected'); + dom.cl.add(tabButton, 'selected'); + tabButton.scrollIntoView(); + qs$('#iframe').contentWindow.location.replace(pane); + if ( pane !== 'no-dashboard.html' ) { + vAPI.localStorage.setItem('dashboardLastVisitedPane', pane); + } + }; + if ( first ) { + return loadPane(); + } + const r = discardUnsavedData(); + if ( r === false ) { return; } + if ( r === true ) { return loadPane(); } + r.then(status => { + if ( status === false ) { return; } + loadPane(); + }); +}; + +const onTabClickHandler = function(ev) { + loadDashboardPanel(dom.attr(ev.target, 'data-pane')); +}; + +if ( self.location.hash.slice(1) === 'no-dashboard.html' ) { + dom.cl.add(dom.body, 'noDashboard'); +} + +(async ( ) => { + // Wait for uBO's main process to be ready + await new Promise(resolve => { + const check = async ( ) => { + try { + const response = await vAPI.messaging.send('dashboard', { + what: 'readyToFilter' + }); + if ( response ) { return resolve(true); } + const iframe = qs$('#iframe'); + if ( iframe.src !== '' ) { + iframe.src = ''; + } + } catch(ex) { + } + vAPI.defer.once(250).then(( ) => check()); + }; + check(); + }); + + dom.cl.remove(dom.body, 'notReady'); + + const results = await Promise.all([ + // https://github.com/uBlockOrigin/uBlock-issues/issues/106 + vAPI.messaging.send('dashboard', { what: 'dashboardConfig' }), + vAPI.localStorage.getItemAsync('dashboardLastVisitedPane'), + ]); + + { + const details = results[0] || {}; + if ( details.noDashboard ) { + self.location.hash = '#no-dashboard.html'; + dom.cl.add(dom.body, 'noDashboard'); + } else if ( self.location.hash === '#no-dashboard.html' ) { + self.location.hash = ''; + } + } + + { + let pane = results[1] || null; + if ( self.location.hash !== '' ) { + pane = self.location.hash.slice(1) || null; + } + loadDashboardPanel(pane !== null ? pane : 'settings.html', true); + + dom.on('.tabButton', 'click', onTabClickHandler); + + // https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event + dom.on(self, 'beforeunload', ( ) => { + if ( discardUnsavedData(true) ) { return; } + event.preventDefault(); + event.returnValue = ''; + }); + + // https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event + dom.on(self, 'hashchange', ( ) => { + const pane = self.location.hash.slice(1); + if ( pane === '' ) { return; } + loadDashboardPanel(pane); + }); + + } +})(); diff --git a/src/js/devtools.js b/src/js/devtools.js new file mode 100644 index 0000000..93b2697 --- /dev/null +++ b/src/js/devtools.js @@ -0,0 +1,192 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* global CodeMirror, uBlockDashboard */ + +'use strict'; + +import { dom, qs$ } from './dom.js'; + +/******************************************************************************/ + +const reFoldable = /^ *(?=\+ \S)/; + +/******************************************************************************/ + +CodeMirror.registerGlobalHelper( + 'fold', + 'ubo-dump', + ( ) => true, + (cm, start) => { + const startLineNo = start.line; + const startLine = cm.getLine(startLineNo); + let endLineNo = startLineNo; + let endLine = startLine; + const match = reFoldable.exec(startLine); + if ( match === null ) { return; } + const foldCandidate = ' ' + match[0]; + const lastLineNo = cm.lastLine(); + let nextLineNo = startLineNo + 1; + while ( nextLineNo < lastLineNo ) { + const nextLine = cm.getLine(nextLineNo); + // TODO: use regex to find folding end + if ( nextLine.startsWith(foldCandidate) === false && nextLine !== ']' ) { + if ( startLineNo >= endLineNo ) { return; } + return { + from: CodeMirror.Pos(startLineNo, startLine.length), + to: CodeMirror.Pos(endLineNo, endLine.length) + }; + } + endLine = nextLine; + endLineNo = nextLineNo; + nextLineNo += 1; + } + } +); + +const cmEditor = new CodeMirror(qs$('#console'), { + autofocus: true, + foldGutter: true, + gutters: [ 'CodeMirror-linenumbers', 'CodeMirror-foldgutter' ], + lineNumbers: true, + lineWrapping: true, + mode: 'ubo-dump', + styleActiveLine: true, + undoDepth: 5, +}); + +uBlockDashboard.patchCodeMirrorEditor(cmEditor); + +/******************************************************************************/ + +function log(text) { + cmEditor.replaceRange(text.trim() + '\n\n', { line: 0, ch: 0 }); +} + +/******************************************************************************/ + +dom.on('#console-clear', 'click', ( ) => { + cmEditor.setValue(''); +}); + +dom.on('#console-fold', 'click', ( ) => { + const unfolded = []; + let maxUnfolded = -1; + cmEditor.eachLine(handle => { + const match = reFoldable.exec(handle.text); + if ( match === null ) { return; } + const depth = match[0].length; + const line = handle.lineNo(); + const isFolded = cmEditor.isFolded({ line, ch: handle.text.length }); + if ( isFolded === true ) { return; } + unfolded.push({ line, depth }); + maxUnfolded = Math.max(maxUnfolded, depth); + }); + if ( maxUnfolded === -1 ) { return; } + cmEditor.startOperation(); + for ( const details of unfolded ) { + if ( details.depth !== maxUnfolded ) { continue; } + cmEditor.foldCode(details.line, null, 'fold'); + } + cmEditor.endOperation(); +}); + +dom.on('#console-unfold', 'click', ( ) => { + const folded = []; + let minFolded = Number.MAX_SAFE_INTEGER; + cmEditor.eachLine(handle => { + const match = reFoldable.exec(handle.text); + if ( match === null ) { return; } + const depth = match[0].length; + const line = handle.lineNo(); + const isFolded = cmEditor.isFolded({ line, ch: handle.text.length }); + if ( isFolded !== true ) { return; } + folded.push({ line, depth }); + minFolded = Math.min(minFolded, depth); + }); + if ( minFolded === Number.MAX_SAFE_INTEGER ) { return; } + cmEditor.startOperation(); + for ( const details of folded ) { + if ( details.depth !== minFolded ) { continue; } + cmEditor.foldCode(details.line, null, 'unfold'); + } + cmEditor.endOperation(); +}); + +dom.on('#snfe-dump', 'click', ev => { + const button = ev.target; + dom.attr(button, 'disabled', ''); + vAPI.messaging.send('devTools', { + what: 'snfeDump', + }).then(result => { + log(result); + dom.attr(button, 'disabled', null); + }); +}); + +dom.on('#snfe-todnr', 'click', ev => { + const button = ev.target; + dom.attr(button, 'disabled', ''); + vAPI.messaging.send('devTools', { + what: 'snfeToDNR', + }).then(result => { + log(result); + dom.attr(button, 'disabled', null); + }); +}); + +dom.on('#cfe-dump', 'click', ev => { + const button = ev.target; + dom.attr(button, 'disabled', ''); + vAPI.messaging.send('devTools', { + what: 'cfeDump', + }).then(result => { + log(result); + dom.attr(button, 'disabled', null); + }); +}); + +dom.on('#purge-all-caches', 'click', ( ) => { + vAPI.messaging.send('devTools', { + what: 'purgeAllCaches' + }).then(result => { + log(result); + }); +}); + +vAPI.messaging.send('dashboard', { + what: 'getAppData', +}).then(appData => { + if ( appData.canBenchmark !== true ) { return; } + dom.attr('#snfe-benchmark', 'disabled', null); + dom.on('#snfe-benchmark', 'click', ev => { + const button = ev.target; + dom.attr(button, 'disabled', ''); + vAPI.messaging.send('devTools', { + what: 'snfeBenchmark', + }).then(result => { + log(result); + dom.attr(button, 'disabled', null); + }); + }); +}); + +/******************************************************************************/ diff --git a/src/js/diff-updater.js b/src/js/diff-updater.js new file mode 100644 index 0000000..4e6ece1 --- /dev/null +++ b/src/js/diff-updater.js @@ -0,0 +1,288 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +// This module can be dynamically loaded or spun off as a worker. + +/******************************************************************************/ + +const patches = new Map(); +const encoder = new TextEncoder(); +const reFileName = /([^\/]+?)(?:#.+)?$/; +const EMPTYLINE = ''; + +/******************************************************************************/ + +const suffleArray = arr => { + const out = arr.slice(); + for ( let i = 0, n = out.length; i < n; i++ ) { + const j = Math.floor(Math.random() * n); + if ( j === i ) { continue; } + [ out[j], out[i] ] = [ out[i], out[j] ]; + } + return out; +}; + +const basename = url => { + const match = reFileName.exec(url); + return match && match[1] || ''; +}; + +const resolveURL = (path, url) => { + try { + return new URL(path, url); + } + catch(_) { + } +}; + +const expectedTimeFromPatch = assetDetails => { + const match = /(\d+)\.(\d+)\.(\d+)\.(\d+)/.exec(assetDetails.patchPath); + if ( match === null ) { return 0; } + const date = new Date(); + date.setUTCFullYear( + parseInt(match[1], 10), + parseInt(match[2], 10) - 1, + parseInt(match[3], 10) + ); + date.setUTCHours(0, parseInt(match[4], 10), 0, 0); + return date.getTime() + assetDetails.diffExpires; +}; + +function parsePatch(patch) { + const patchDetails = new Map(); + const diffLines = patch.split('\n'); + let i = 0, n = diffLines.length; + while ( i < n ) { + const line = diffLines[i++]; + if ( line.startsWith('diff ') === false ) { continue; } + const fields = line.split(/\s+/); + const diffBlock = {}; + for ( let j = 0; j < fields.length; j++ ) { + const field = fields[j]; + const pos = field.indexOf(':'); + if ( pos === -1 ) { continue; } + const name = field.slice(0, pos); + if ( name === '' ) { continue; } + const value = field.slice(pos+1); + switch ( name ) { + case 'name': + case 'checksum': + diffBlock[name] = value; + break; + case 'lines': + diffBlock.lines = parseInt(value, 10); + break; + default: + break; + } + } + if ( diffBlock.name === undefined ) { return; } + if ( isNaN(diffBlock.lines) || diffBlock.lines <= 0 ) { return; } + if ( diffBlock.checksum === undefined ) { return; } + patchDetails.set(diffBlock.name, diffBlock); + diffBlock.diff = diffLines.slice(i, i + diffBlock.lines).join('\n'); + i += diffBlock.lines; + } + if ( patchDetails.size === 0 ) { return; } + return patchDetails; +} + +function applyPatch(text, diff) { + // Inspired from (Perl) "sub _patch" at: + // https://twiki.org/p/pub/Codev/RcsLite/RcsLite.pm + // Apparently authored by John Talintyre in Jan. 2002 + // https://twiki.org/cgi-bin/view/Codev/RcsLite + const lines = text.split('\n'); + const diffLines = diff.split('\n'); + let iAdjust = 0; + let iDiff = 0, nDiff = diffLines.length; + while ( iDiff < nDiff ) { + const diffLine = diffLines[iDiff++]; + if ( diffLine === '' ) { break; } + const diffParsed = /^([ad])(\d+) (\d+)$/.exec(diffLine); + if ( diffParsed === null ) { return; } + const op = diffParsed[1]; + const iOp = parseInt(diffParsed[2], 10); + const nOp = parseInt(diffParsed[3], 10); + const iOpAdj = iOp + iAdjust; + if ( iOpAdj > lines.length ) { return; } + // Delete lines + if ( op === 'd' ) { + lines.splice(iOpAdj-1, nOp); + iAdjust -= nOp; + continue; + } + // Add lines: Don't use splice() to avoid stack limit issues + for ( let i = 0; i < nOp; i++ ) { + lines.push(EMPTYLINE); + } + lines.copyWithin(iOpAdj+nOp, iOpAdj); + for ( let i = 0; i < nOp; i++ ) { + lines[iOpAdj+i] = diffLines[iDiff+i]; + } + iAdjust += nOp; + iDiff += nOp; + } + return lines.join('\n'); +} + +function hasPatchDetails(assetDetails) { + const { patchPath } = assetDetails; + const patchFile = basename(patchPath); + return patchFile !== '' && patches.has(patchFile); +} + +/******************************************************************************/ + +// Async + +async function applyPatchAndValidate(assetDetails, diffDetails) { + const { text } = assetDetails; + const { diff, checksum } = diffDetails; + const textAfter = applyPatch(text, diff); + if ( typeof textAfter !== 'string' ) { + assetDetails.error = 'baddiff'; + return false; + } + const crypto = globalThis.crypto; + if ( typeof crypto !== 'object' ) { + assetDetails.error = 'nocrypto'; + return false; + } + const arrayin = encoder.encode(textAfter); + const arraybuffer = await crypto.subtle.digest('SHA-1', arrayin); + const arrayout = new Uint8Array(arraybuffer); + const sha1Full = Array.from(arrayout).map(i => + i.toString(16).padStart(2, '0') + ).join(''); + if ( sha1Full.startsWith(checksum) === false ) { + assetDetails.error = `badchecksum: expected ${checksum}, computed ${sha1Full.slice(0, checksum.length)}`; + return false; + } + assetDetails.text = textAfter; + return true; +} + +async function fetchPatchDetailsFromCDNs(assetDetails) { + const { patchPath, cdnURLs } = assetDetails; + if ( Array.isArray(cdnURLs) === false ) { return null; } + if ( cdnURLs.length === 0 ) { return null; } + for ( const cdnURL of suffleArray(cdnURLs) ) { + const patchURL = resolveURL(patchPath, cdnURL); + if ( patchURL === undefined ) { continue; } + const response = await fetch(patchURL).catch(reason => { + console.error(reason, patchURL); + }); + if ( response === undefined ) { continue; } + if ( response.status === 404 ) { break; } + if ( response.ok !== true ) { continue; } + const patchText = await response.text(); + const patchDetails = parsePatch(patchText); + if ( patchURL.hash.length > 1 ) { + assetDetails.diffName = patchURL.hash.slice(1); + patchURL.hash = ''; + } + return { + patchURL: patchURL.href, + patchSize: `${(patchText.length / 1000).toFixed(1)} KB`, + patchDetails, + }; + } + return null; +} + +async function fetchPatchDetails(assetDetails) { + const { patchPath } = assetDetails; + const patchFile = basename(patchPath); + if ( patchFile === '' ) { return null; } + if ( patches.has(patchFile) ) { + return patches.get(patchFile); + } + const patchDetailsPromise = fetchPatchDetailsFromCDNs(assetDetails); + patches.set(patchFile, patchDetailsPromise); + return patchDetailsPromise; +} + +async function fetchAndApplyAllPatches(assetDetails) { + if ( assetDetails.fetch === false ) { + if ( hasPatchDetails(assetDetails) === false ) { + assetDetails.status = 'nodiff'; + return assetDetails; + } + } + // uBO-specific, to avoid pointless fetches which are likely to fail + // because the patch has not yet been created + const patchTime = expectedTimeFromPatch(assetDetails); + if ( patchTime > Date.now() ) { + assetDetails.status = 'nopatch-yet'; + return assetDetails; + } + const patchData = await fetchPatchDetails(assetDetails); + if ( patchData === null ) { + assetDetails.status = (Date.now() - patchTime) < (4 * assetDetails.diffExpires) + ? 'nopatch-yet' + : 'nopatch'; + return assetDetails; + } + const { patchDetails } = patchData; + if ( patchDetails instanceof Map === false ) { + assetDetails.status = 'nodiff'; + return assetDetails; + } + const diffDetails = patchDetails.get(assetDetails.diffName); + if ( diffDetails === undefined ) { + assetDetails.status = 'nodiff'; + return assetDetails; + } + if ( assetDetails.text === undefined ) { + assetDetails.status = 'needtext'; + return assetDetails; + } + const outcome = await applyPatchAndValidate(assetDetails, diffDetails); + if ( outcome !== true ) { return assetDetails; } + assetDetails.status = 'updated'; + assetDetails.patchURL = patchData.patchURL; + assetDetails.patchSize = patchData.patchSize; + return assetDetails; +} + +/******************************************************************************/ + +const bc = new globalThis.BroadcastChannel('diffUpdater'); + +bc.onmessage = ev => { + const message = ev.data || {}; + switch ( message.what ) { + case 'update': + fetchAndApplyAllPatches(message).then(response => { + bc.postMessage(response); + }).catch(error => { + bc.postMessage({ what: 'broken', error }); + }); + break; + } +}; + +bc.postMessage({ what: 'ready' }); + +/******************************************************************************/ diff --git a/src/js/document-blocked.js b/src/js/document-blocked.js new file mode 100644 index 0000000..59a6bc8 --- /dev/null +++ b/src/js/document-blocked.js @@ -0,0 +1,230 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +import { i18n, i18n$ } from './i18n.js'; +import { dom, qs$ } from './dom.js'; + +/******************************************************************************/ + +const messaging = vAPI.messaging; +let details = {}; + +{ + const matches = /details=([^&]+)/.exec(window.location.search); + if ( matches !== null ) { + details = JSON.parse(decodeURIComponent(matches[1])); + } +} + +/******************************************************************************/ + +(async ( ) => { + const response = await messaging.send('documentBlocked', { + what: 'listsFromNetFilter', + rawFilter: details.fs, + }); + if ( response instanceof Object === false ) { return; } + + let lists; + for ( const rawFilter in response ) { + if ( response.hasOwnProperty(rawFilter) ) { + lists = response[rawFilter]; + break; + } + } + + if ( Array.isArray(lists) === false || lists.length === 0 ) { + qs$('#whyex').style.setProperty('visibility', 'collapse'); + return; + } + + const parent = qs$('#whyex > ul'); + parent.firstElementChild.remove(); // remove placeholder element + for ( const list of lists ) { + const listElem = dom.clone('#templates .filterList'); + const sourceElem = qs$(listElem, '.filterListSource'); + sourceElem.href += encodeURIComponent(list.assetKey); + sourceElem.append(i18n.patchUnicodeFlags(list.title)); + if ( typeof list.supportURL === 'string' && list.supportURL !== '' ) { + const supportElem = qs$(listElem, '.filterListSupport'); + dom.attr(supportElem, 'href', list.supportURL); + dom.cl.remove(supportElem, 'hidden'); + } + parent.appendChild(listElem); + } + qs$('#whyex').style.removeProperty('visibility'); +})(); + +/******************************************************************************/ + +dom.text('#theURL > p > span:first-of-type', details.url); +dom.text('#why', details.fs); + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/691 +// Parse URL to extract as much useful information as possible. This is +// useful to assist the user in deciding whether to navigate to the web page. +(( ) => { + if ( typeof URL !== 'function' ) { return; } + + const reURL = /^https?:\/\//; + + const liFromParam = function(name, value) { + if ( value === '' ) { + value = name; + name = ''; + } + const li = dom.create('li'); + let span = dom.create('span'); + dom.text(span, name); + li.appendChild(span); + if ( name !== '' && value !== '' ) { + li.appendChild(document.createTextNode(' = ')); + } + span = dom.create('span'); + if ( reURL.test(value) ) { + const a = dom.create('a'); + dom.attr(a, 'href', value); + dom.text(a, value); + span.appendChild(a); + } else { + dom.text(span, value); + } + li.appendChild(span); + return li; + }; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1649 + // Limit recursion. + const renderParams = function(parentNode, rawURL, depth = 0) { + let url; + try { + url = new URL(rawURL); + } catch(ex) { + return false; + } + + const search = url.search.slice(1); + if ( search === '' ) { return false; } + + url.search = ''; + const li = liFromParam(i18n$('docblockedNoParamsPrompt'), url.href); + parentNode.appendChild(li); + + const params = new self.URLSearchParams(search); + for ( const [ name, value ] of params ) { + const li = liFromParam(name, value); + if ( depth < 2 && reURL.test(value) ) { + const ul = dom.create('ul'); + renderParams(ul, value, depth + 1); + li.appendChild(ul); + } + parentNode.appendChild(li); + } + + return true; + }; + + if ( renderParams(qs$('#parsed'), details.url) === false ) { + return; + } + + dom.cl.remove('#toggleParse', 'hidden'); + + dom.on('#toggleParse', 'click', ( ) => { + dom.cl.toggle('#theURL', 'collapsed'); + vAPI.localStorage.setItem( + 'document-blocked-expand-url', + (dom.cl.has('#theURL', 'collapsed') === false).toString() + ); + }); + + vAPI.localStorage.getItemAsync('document-blocked-expand-url').then(value => { + dom.cl.toggle('#theURL', 'collapsed', value !== 'true' && value !== true); + }); +})(); + +/******************************************************************************/ + +// https://www.reddit.com/r/uBlockOrigin/comments/breeux/close_this_window_doesnt_work_on_firefox/ + +if ( window.history.length > 1 ) { + dom.on('#back', 'click', ( ) => { + window.history.back(); + }); + qs$('#bye').style.display = 'none'; +} else { + dom.on('#bye', 'click', ( ) => { + messaging.send('documentBlocked', { + what: 'closeThisTab', + }); + }); + qs$('#back').style.display = 'none'; +} + +/******************************************************************************/ + +const getTargetHostname = function() { + return details.hn; +}; + +const proceedToURL = function() { + window.location.replace(details.url); +}; + +const proceedTemporary = async function() { + await messaging.send('documentBlocked', { + what: 'temporarilyWhitelistDocument', + hostname: getTargetHostname(), + }); + proceedToURL(); +}; + +const proceedPermanent = async function() { + await messaging.send('documentBlocked', { + what: 'toggleHostnameSwitch', + name: 'no-strict-blocking', + hostname: getTargetHostname(), + deep: true, + state: true, + persist: true, + }); + proceedToURL(); +}; + +dom.on('#disableWarning', 'change', ev => { + const checked = ev.target.checked; + dom.cl.toggle('[data-i18n="docblockedBack"]', 'disabled', checked); + dom.cl.toggle('[data-i18n="docblockedClose"]', 'disabled', checked); +}); + +dom.on('#proceed', 'click', ( ) => { + if ( qs$('#disableWarning').checked ) { + proceedPermanent(); + } else { + proceedTemporary(); + } +}); + +/******************************************************************************/ diff --git a/src/js/dom-inspector.js b/src/js/dom-inspector.js new file mode 100644 index 0000000..a0d334b --- /dev/null +++ b/src/js/dom-inspector.js @@ -0,0 +1,68 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ +/******************************************************************************/ + +const svgRoot = document.querySelector('svg'); +let inspectorContentPort; + +const shutdown = ( ) => { + inspectorContentPort.close(); + inspectorContentPort.onmessage = inspectorContentPort.onmessageerror = null; + inspectorContentPort = undefined; +}; + +const contentInspectorChannel = ev => { + const msg = ev.data || {}; + switch ( msg.what ) { + case 'quitInspector': { + shutdown(); + break; + } + case 'svgPaths': { + const paths = svgRoot.children; + paths[0].setAttribute('d', msg.paths[0]); + paths[1].setAttribute('d', msg.paths[1]); + paths[2].setAttribute('d', msg.paths[2]); + paths[3].setAttribute('d', msg.paths[3]); + break; + } + default: + break; + } +}; + +// Wait for the content script to establish communication +globalThis.addEventListener('message', ev => { + const msg = ev.data || {}; + if ( msg.what !== 'startInspector' ) { return; } + if ( Array.isArray(ev.ports) === false ) { return; } + if ( ev.ports.length === 0 ) { return; } + inspectorContentPort = ev.ports[0]; + inspectorContentPort.onmessage = contentInspectorChannel; + inspectorContentPort.onmessageerror = shutdown; + inspectorContentPort.postMessage({ what: 'startInspector' }); +}, { once: true }); + +/******************************************************************************/ diff --git a/src/js/dom.js b/src/js/dom.js new file mode 100644 index 0000000..3d2f517 --- /dev/null +++ b/src/js/dom.js @@ -0,0 +1,213 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* jshint esversion:11 */ + +'use strict'; + +/******************************************************************************/ + +const normalizeTarget = target => { + if ( typeof target === 'string' ) { return Array.from(qsa$(target)); } + if ( target instanceof Element ) { return [ target ]; } + if ( target === null ) { return []; } + if ( Array.isArray(target) ) { return target; } + return Array.from(target); +}; + +const makeEventHandler = (selector, callback) => { + return function(event) { + const dispatcher = event.currentTarget; + if ( + dispatcher instanceof HTMLElement === false || + typeof dispatcher.querySelectorAll !== 'function' + ) { + return; + } + const receiver = event.target; + const ancestor = receiver.closest(selector); + if ( + ancestor === receiver && + ancestor !== dispatcher && + dispatcher.contains(ancestor) + ) { + callback.call(receiver, event); + } + }; +}; + +/******************************************************************************/ + +class dom { + static attr(target, attr, value = undefined) { + for ( const elem of normalizeTarget(target) ) { + if ( value === undefined ) { + return elem.getAttribute(attr); + } + if ( value === null ) { + elem.removeAttribute(attr); + } else { + elem.setAttribute(attr, value); + } + } + } + + static clear(target) { + for ( const elem of normalizeTarget(target) ) { + while ( elem.firstChild !== null ) { + elem.removeChild(elem.firstChild); + } + } + } + + static clone(target) { + const elements = normalizeTarget(target); + if ( elements.length === 0 ) { return null; } + return elements[0].cloneNode(true); + } + + static create(a) { + if ( typeof a === 'string' ) { + return document.createElement(a); + } + } + + static prop(target, prop, value = undefined) { + for ( const elem of normalizeTarget(target) ) { + if ( value === undefined ) { return elem[prop]; } + elem[prop] = value; + } + } + + static text(target, text) { + const targets = normalizeTarget(target); + if ( text === undefined ) { + return targets.length !== 0 ? targets[0].textContent : undefined; + } + for ( const elem of targets ) { + elem.textContent = text; + } + } + + static remove(target) { + for ( const elem of normalizeTarget(target) ) { + elem.remove(); + } + } + + // target, type, callback, [options] + // target, type, subtarget, callback, [options] + + static on(target, type, subtarget, callback, options) { + if ( typeof subtarget === 'function' ) { + options = callback; + callback = subtarget; + subtarget = undefined; + if ( typeof options === 'boolean' ) { + options = { capture: true }; + } + } else { + callback = makeEventHandler(subtarget, callback); + if ( options === undefined || typeof options === 'boolean' ) { + options = { capture: true }; + } else { + options.capture = true; + } + } + const targets = target instanceof Window || target instanceof Document + ? [ target ] + : normalizeTarget(target); + for ( const elem of targets ) { + elem.addEventListener(type, callback, options); + } + } + + static off(target, type, callback, options) { + if ( typeof callback !== 'function' ) { return; } + if ( typeof options === 'boolean' ) { + options = { capture: true }; + } + const targets = target instanceof Window || target instanceof Document + ? [ target ] + : normalizeTarget(target); + for ( const elem of targets ) { + elem.removeEventListener(type, callback, options); + } + } +} + +dom.cl = class { + static add(target, name) { + for ( const elem of normalizeTarget(target) ) { + elem.classList.add(name); + } + } + + static remove(target, name) { + for ( const elem of normalizeTarget(target) ) { + elem.classList.remove(name); + } + } + + static toggle(target, name, state) { + let r; + for ( const elem of normalizeTarget(target) ) { + r = elem.classList.toggle(name, state); + } + return r; + } + + static has(target, name) { + for ( const elem of normalizeTarget(target) ) { + if ( elem.classList.contains(name) ) { + return true; + } + } + return false; + } +}; + +/******************************************************************************/ + +function qs$(a, b) { + if ( typeof a === 'string') { + return document.querySelector(a); + } + if ( a === null ) { return null; } + return a.querySelector(b); +} + +function qsa$(a, b) { + if ( typeof a === 'string') { + return document.querySelectorAll(a); + } + if ( a === null ) { return []; } + return a.querySelectorAll(b); +} + +dom.root = qs$(':root'); +dom.html = document.documentElement; +dom.head = document.head; +dom.body = document.body; + +/******************************************************************************/ + +export { dom, qs$, qsa$ }; diff --git a/src/js/dyna-rules.js b/src/js/dyna-rules.js new file mode 100644 index 0000000..ea79742 --- /dev/null +++ b/src/js/dyna-rules.js @@ -0,0 +1,678 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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/uMatrix +*/ + +/* global CodeMirror, diff_match_patch, uBlockDashboard */ + +'use strict'; + +import publicSuffixList from '../lib/publicsuffixlist/publicsuffixlist.js'; + +import { hostnameFromURI } from './uri-utils.js'; +import { i18n$ } from './i18n.js'; +import { dom, qs$, qsa$ } from './dom.js'; + +import './codemirror/ubo-dynamic-filtering.js'; + +/******************************************************************************/ + +const hostnameToDomainMap = new Map(); + +const mergeView = new CodeMirror.MergeView( + qs$('.codeMirrorMergeContainer'), + { + allowEditingOriginals: true, + connect: 'align', + inputStyle: 'contenteditable', + lineNumbers: true, + lineWrapping: false, + origLeft: '', + revertButtons: true, + value: '', + } +); +mergeView.editor().setOption('styleActiveLine', true); +mergeView.editor().setOption('lineNumbers', false); +mergeView.leftOriginal().setOption('readOnly', 'nocursor'); + +uBlockDashboard.patchCodeMirrorEditor(mergeView.editor()); + +const thePanes = { + orig: { + doc: mergeView.leftOriginal(), + original: [], + modified: [], + }, + edit: { + doc: mergeView.editor(), + original: [], + modified: [], + }, +}; + +let cleanEditToken = 0; +let cleanEditText = ''; +let isCollapsed = false; + +/******************************************************************************/ + +// The following code is to take care of properly internationalizing +// the tooltips of the arrows used by the CodeMirror merge view. These +// are hard-coded by CodeMirror ("Push to left", "Push to right"). An +// observer is necessary because there is no hook for uBO to overwrite +// reliably the default title attribute assigned by CodeMirror. + +{ + const i18nCommitStr = i18n$('rulesCommit'); + const i18nRevertStr = i18n$('rulesRevert'); + const commitArrowSelector = '.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy-reverse:not([title="' + i18nCommitStr + '"])'; + const revertArrowSelector = '.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy:not([title="' + i18nRevertStr + '"])'; + + dom.attr('.CodeMirror-merge-scrolllock', 'title', i18n$('genericMergeViewScrollLock')); + + const translate = function() { + let elems = qsa$(commitArrowSelector); + for ( const elem of elems ) { + dom.attr(elem, 'title', i18nCommitStr); + } + elems = qsa$(revertArrowSelector); + for ( const elem of elems ) { + dom.attr(elem, 'title', i18nRevertStr); + } + }; + + const mergeGapObserver = new MutationObserver(translate); + + mergeGapObserver.observe( + qs$('.CodeMirror-merge-copybuttons-left'), + { attributes: true, attributeFilter: [ 'title' ], subtree: true } + ); + +} + +/******************************************************************************/ + +const getDiffer = (( ) => { + let differ; + return ( ) => { + if ( differ === undefined ) { differ = new diff_match_patch(); } + return differ; + }; +})(); + +/******************************************************************************/ + +// Borrowed from... +// https://github.com/codemirror/CodeMirror/blob/3e1bb5fff682f8f6cbfaef0e56c61d62403d4798/addon/search/search.js#L22 +// ... and modified as needed. + +const updateOverlay = (( ) => { + let reFilter; + const mode = { + token: function(stream) { + if ( reFilter !== undefined ) { + reFilter.lastIndex = stream.pos; + let match = reFilter.exec(stream.string); + if ( match !== null ) { + if ( match.index === stream.pos ) { + stream.pos += match[0].length || 1; + return 'searching'; + } + stream.pos = match.index; + return; + } + } + stream.skipToEnd(); + } + }; + return function(filter) { + reFilter = typeof filter === 'string' && filter !== '' ? + new RegExp(filter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi') : + undefined; + return mode; + }; +})(); + +/******************************************************************************/ + +// Incrementally update text in a CodeMirror editor for best user experience: +// - Scroll position preserved +// - Minimum amount of text updated + +const rulesToDoc = function(clearHistory) { + const orig = thePanes.orig.doc; + const edit = thePanes.edit.doc; + orig.startOperation(); + edit.startOperation(); + + for ( const key in thePanes ) { + if ( thePanes.hasOwnProperty(key) === false ) { continue; } + const doc = thePanes[key].doc; + const rules = filterRules(key); + if ( + clearHistory || + doc.lineCount() === 1 && doc.getValue() === '' || + rules.length === 0 + ) { + doc.setValue(rules.length !== 0 ? rules.join('\n') + '\n' : ''); + continue; + } + // https://github.com/uBlockOrigin/uBlock-issues/issues/593 + // Ensure the text content always ends with an empty line to avoid + // spurious diff entries. + // https://github.com/uBlockOrigin/uBlock-issues/issues/657 + // Diff against unmodified beforeText so that the last newline can + // be reported in the diff and thus appended if needed. + let beforeText = doc.getValue(); + let afterText = rules.join('\n').trim(); + if ( afterText !== '' ) { afterText += '\n'; } + const diffs = getDiffer().diff_main(beforeText, afterText); + let i = diffs.length; + let iedit = beforeText.length; + while ( i-- ) { + const diff = diffs[i]; + if ( diff[0] === 0 ) { + iedit -= diff[1].length; + continue; + } + const end = doc.posFromIndex(iedit); + if ( diff[0] === 1 ) { + doc.replaceRange(diff[1], end, end); + continue; + } + /* diff[0] === -1 */ + iedit -= diff[1].length; + const beg = doc.posFromIndex(iedit); + doc.replaceRange('', beg, end); + } + } + + // Mark ellipses as read-only + const marks = edit.getAllMarks(); + for ( const mark of marks ) { + if ( mark.uboEllipsis !== true ) { continue; } + mark.clear(); + } + if ( isCollapsed ) { + for ( let iline = 0, n = edit.lineCount(); iline < n; iline++ ) { + if ( edit.getLine(iline) !== '...' ) { continue; } + const mark = edit.markText( + { line: iline, ch: 0 }, + { line: iline + 1, ch: 0 }, + { atomic: true, readOnly: true } + ); + mark.uboEllipsis = true; + } + } + + orig.endOperation(); + edit.endOperation(); + cleanEditText = mergeView.editor().getValue().trim(); + cleanEditToken = mergeView.editor().changeGeneration(); + + if ( clearHistory !== true ) { return; } + + mergeView.editor().clearHistory(); + const chunks = mergeView.leftChunks(); + if ( chunks.length === 0 ) { return; } + const ldoc = thePanes.orig.doc; + const { clientHeight } = ldoc.getScrollInfo(); + const line = Math.min(chunks[0].editFrom, chunks[0].origFrom); + ldoc.setCursor(line, 0); + ldoc.scrollIntoView( + { line, ch: 0 }, + (clientHeight - ldoc.defaultTextHeight()) / 2 + ); +}; + +/******************************************************************************/ + +const filterRules = function(key) { + const filter = qs$('#ruleFilter input').value; + const rules = thePanes[key].modified; + if ( filter === '' ) { return rules; } + const out = []; + for ( const rule of rules ) { + if ( rule.indexOf(filter) === -1 ) { continue; } + out.push(rule); + } + return out; +}; + +/******************************************************************************/ + +const applyDiff = async function(permanent, toAdd, toRemove) { + const details = await vAPI.messaging.send('dashboard', { + what: 'modifyRuleset', + permanent: permanent, + toAdd: toAdd, + toRemove: toRemove, + }); + thePanes.orig.original = details.permanentRules; + thePanes.edit.original = details.sessionRules; + onPresentationChanged(); +}; + +/******************************************************************************/ + +// CodeMirror quirk: sometimes fromStart.ch and/or toStart.ch is undefined. +// When this happens, use 0. + +mergeView.options.revertChunk = function( + mv, + from, fromStart, fromEnd, + to, toStart, toEnd +) { + // https://github.com/gorhill/uBlock/issues/3611 + if ( dom.attr(dom.body, 'dir') === 'rtl' ) { + let tmp = from; from = to; to = tmp; + tmp = fromStart; fromStart = toStart; toStart = tmp; + tmp = fromEnd; fromEnd = toEnd; toEnd = tmp; + } + if ( typeof fromStart.ch !== 'number' ) { fromStart.ch = 0; } + if ( fromEnd.ch !== 0 ) { fromEnd.line += 1; } + const toAdd = from.getRange( + { line: fromStart.line, ch: 0 }, + { line: fromEnd.line, ch: 0 } + ); + if ( typeof toStart.ch !== 'number' ) { toStart.ch = 0; } + if ( toEnd.ch !== 0 ) { toEnd.line += 1; } + const toRemove = to.getRange( + { line: toStart.line, ch: 0 }, + { line: toEnd.line, ch: 0 } + ); + applyDiff(from === mv.editor(), toAdd, toRemove); +}; + +/******************************************************************************/ + +function handleImportFilePicker() { + const fileReaderOnLoadHandler = function() { + if ( typeof this.result !== 'string' || this.result === '' ) { return; } + // https://github.com/chrisaljoudi/uBlock/issues/757 + // Support RequestPolicy rule syntax + let result = this.result; + let matches = /\[origins-to-destinations\]([^\[]+)/.exec(result); + if ( matches && matches.length === 2 ) { + result = matches[1].trim() + .replace(/\|/g, ' ') + .replace(/\n/g, ' * noop\n'); + } + applyDiff(false, result, ''); + }; + const file = this.files[0]; + if ( file === undefined || file.name === '' ) { return; } + if ( file.type.indexOf('text') !== 0 ) { return; } + const fr = new FileReader(); + fr.onload = fileReaderOnLoadHandler; + fr.readAsText(file); +} + +/******************************************************************************/ + +const startImportFilePicker = function() { + const input = qs$('#importFilePicker'); + // Reset to empty string, this will ensure an change event is properly + // triggered if the user pick a file, even if it is the same as the last + // one picked. + input.value = ''; + input.click(); +}; + +/******************************************************************************/ + +function exportUserRulesToFile() { + const filename = i18n$('rulesDefaultFileName') + .replace('{{datetime}}', uBlockDashboard.dateNowToSensibleString()) + .replace(/ +/g, '_'); + vAPI.download({ + url: 'data:text/plain,' + encodeURIComponent( + mergeView.leftOriginal().getValue().trim() + '\n' + ), + filename: filename, + saveAs: true + }); +} + +/******************************************************************************/ + +const onFilterChanged = (( ) => { + let timer; + let overlay = null; + let last = ''; + + const process = function() { + timer = undefined; + if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; } + const filter = qs$('#ruleFilter input').value; + if ( filter === last ) { return; } + last = filter; + if ( overlay !== null ) { + mergeView.leftOriginal().removeOverlay(overlay); + mergeView.editor().removeOverlay(overlay); + overlay = null; + } + if ( filter !== '' ) { + overlay = updateOverlay(filter); + mergeView.leftOriginal().addOverlay(overlay); + mergeView.editor().addOverlay(overlay); + } + rulesToDoc(true); + }; + + return function() { + if ( timer !== undefined ) { self.cancelIdleCallback(timer); } + timer = self.requestIdleCallback(process, { timeout: 773 }); + }; +})(); + +/******************************************************************************/ + +const onPresentationChanged = (( ) => { + let sortType = 1; + + const reSwRule = /^([^/]+): ([^/ ]+) ([^ ]+)/; + const reRule = /^([^ ]+) ([^/ ]+) ([^ ]+ [^ ]+)/; + const reUrlRule = /^([^ ]+) ([^ ]+) ([^ ]+ [^ ]+)/; + + const sortNormalizeHn = function(hn) { + let domain = hostnameToDomainMap.get(hn); + if ( domain === undefined ) { + domain = /(\d|\])$/.test(hn) + ? hn + : publicSuffixList.getDomain(hn); + hostnameToDomainMap.set(hn, domain); + } + let normalized = domain || hn; + if ( hn.length !== domain.length ) { + const subdomains = hn.slice(0, hn.length - domain.length - 1); + normalized += '.' + ( + subdomains.includes('.') + ? subdomains.split('.').reverse().join('.') + : subdomains + ); + } + return normalized; + }; + + const slotFromRule = rule => { + let type, srcHn, desHn, extra; + let match = reSwRule.exec(rule); + if ( match !== null ) { + type = ' ' + match[1]; + srcHn = sortNormalizeHn(match[2]); + desHn = srcHn; + extra = match[3]; + } else if ( (match = reRule.exec(rule)) !== null ) { + type = '\x10FFFE'; + srcHn = sortNormalizeHn(match[1]); + desHn = sortNormalizeHn(match[2]); + extra = match[3]; + } else if ( (match = reUrlRule.exec(rule)) !== null ) { + type = '\x10FFFF'; + srcHn = sortNormalizeHn(match[1]); + desHn = sortNormalizeHn(hostnameFromURI(match[2])); + extra = match[3]; + } + if ( sortType === 0 ) { + return { rule, token: `${type} ${srcHn} ${desHn} ${extra}` }; + } + if ( sortType === 1 ) { + return { rule, token: `${srcHn} ${type} ${desHn} ${extra}` }; + } + return { rule, token: `${desHn} ${type} ${srcHn} ${extra}` }; + }; + + const sort = rules => { + const slots = []; + for ( let i = 0; i < rules.length; i++ ) { + slots.push(slotFromRule(rules[i], 1)); + } + slots.sort((a, b) => a.token.localeCompare(b.token)); + for ( let i = 0; i < rules.length; i++ ) { + rules[i] = slots[i].rule; + } + }; + + const collapse = ( ) => { + if ( isCollapsed !== true ) { return; } + const diffs = getDiffer().diff_main( + thePanes.orig.modified.join('\n'), + thePanes.edit.modified.join('\n') + ); + const ll = []; let il = 0, lellipsis = false; + const rr = []; let ir = 0, rellipsis = false; + for ( let i = 0; i < diffs.length; i++ ) { + const diff = diffs[i]; + if ( diff[0] === 0 ) { + lellipsis = rellipsis = true; + il += 1; ir += 1; + continue; + } + if ( diff[0] < 0 ) { + if ( lellipsis ) { + ll.push('...'); + if ( rellipsis ) { rr.push('...'); } + lellipsis = rellipsis = false; + } + ll.push(diff[1].trim()); + il += 1; + continue; + } + /* diff[0] > 0 */ + if ( rellipsis ) { + rr.push('...'); + if ( lellipsis ) { ll.push('...'); } + lellipsis = rellipsis = false; + } + rr.push(diff[1].trim()); + ir += 1; + } + if ( lellipsis ) { ll.push('...'); } + if ( rellipsis ) { rr.push('...'); } + thePanes.orig.modified = ll; + thePanes.edit.modified = rr; + }; + + return function(clearHistory) { + const origPane = thePanes.orig; + const editPane = thePanes.edit; + origPane.modified = origPane.original.slice(); + editPane.modified = editPane.original.slice(); + const select = qs$('#ruleFilter select'); + sortType = parseInt(select.value, 10); + if ( isNaN(sortType) ) { sortType = 1; } + { + const mode = origPane.doc.getMode(); + mode.sortType = sortType; + mode.setHostnameToDomainMap(hostnameToDomainMap); + mode.setPSL(publicSuffixList); + } + { + const mode = editPane.doc.getMode(); + mode.sortType = sortType; + mode.setHostnameToDomainMap(hostnameToDomainMap); + mode.setPSL(publicSuffixList); + } + sort(origPane.modified); + sort(editPane.modified); + collapse(); + rulesToDoc(clearHistory); + onTextChanged(clearHistory); + }; +})(); + +/******************************************************************************/ + +const onTextChanged = (( ) => { + let timer; + + const process = details => { + timer = undefined; + const diff = qs$('#diff'); + let isClean = mergeView.editor().isClean(cleanEditToken); + if ( + details === undefined && + isClean === false && + mergeView.editor().getValue().trim() === cleanEditText + ) { + cleanEditToken = mergeView.editor().changeGeneration(); + isClean = true; + } + const isDirty = mergeView.leftChunks().length !== 0; + dom.cl.toggle(dom.body, 'editing', isClean === false); + dom.cl.toggle(diff, 'dirty', isDirty); + dom.cl.toggle('#editSaveButton', 'disabled', isClean); + dom.cl.toggle('#exportButton,#importButton', 'disabled', isClean === false); + dom.cl.toggle('#revertButton,#commitButton', 'disabled', isClean === false || isDirty === false); + const input = qs$('#ruleFilter input'); + if ( isClean ) { + dom.attr(input, 'disabled', null); + CodeMirror.commands.save = undefined; + } else { + dom.attr(input, 'disabled', ''); + CodeMirror.commands.save = editSaveHandler; + } + }; + + return function(now) { + if ( timer !== undefined ) { self.cancelIdleCallback(timer); } + timer = now ? process() : self.requestIdleCallback(process, { timeout: 57 }); + }; +})(); + +/******************************************************************************/ + +const revertAllHandler = function() { + const toAdd = [], toRemove = []; + const left = mergeView.leftOriginal(); + const edit = mergeView.editor(); + for ( const chunk of mergeView.leftChunks() ) { + const addedLines = left.getRange( + { line: chunk.origFrom, ch: 0 }, + { line: chunk.origTo, ch: 0 } + ); + const removedLines = edit.getRange( + { line: chunk.editFrom, ch: 0 }, + { line: chunk.editTo, ch: 0 } + ); + toAdd.push(addedLines.trim()); + toRemove.push(removedLines.trim()); + } + applyDiff(false, toAdd.join('\n'), toRemove.join('\n')); +}; + +/******************************************************************************/ + +const commitAllHandler = function() { + const toAdd = [], toRemove = []; + const left = mergeView.leftOriginal(); + const edit = mergeView.editor(); + for ( const chunk of mergeView.leftChunks() ) { + const addedLines = edit.getRange( + { line: chunk.editFrom, ch: 0 }, + { line: chunk.editTo, ch: 0 } + ); + const removedLines = left.getRange( + { line: chunk.origFrom, ch: 0 }, + { line: chunk.origTo, ch: 0 } + ); + toAdd.push(addedLines.trim()); + toRemove.push(removedLines.trim()); + } + applyDiff(true, toAdd.join('\n'), toRemove.join('\n')); +}; + +/******************************************************************************/ + +const editSaveHandler = function() { + const editor = mergeView.editor(); + const editText = editor.getValue().trim(); + if ( editText === cleanEditText ) { + onTextChanged(true); + return; + } + const toAdd = [], toRemove = []; + const diffs = getDiffer().diff_main(cleanEditText, editText); + for ( const diff of diffs ) { + if ( diff[0] === 1 ) { + toAdd.push(diff[1]); + } else if ( diff[0] === -1 ) { + toRemove.push(diff[1]); + } + } + applyDiff(false, toAdd.join(''), toRemove.join('')); +}; + +/******************************************************************************/ + +self.cloud.onPush = function() { + return thePanes.orig.original.join('\n'); +}; + +self.cloud.onPull = function(data, append) { + if ( typeof data !== 'string' ) { return; } + applyDiff( + false, + data, + append ? '' : mergeView.editor().getValue().trim() + ); +}; + +/******************************************************************************/ + +self.hasUnsavedData = function() { + return mergeView.editor().isClean(cleanEditToken) === false; +}; + +/******************************************************************************/ + +vAPI.messaging.send('dashboard', { + what: 'getRules', +}).then(details => { + thePanes.orig.original = details.permanentRules; + thePanes.edit.original = details.sessionRules; + publicSuffixList.fromSelfie(details.pslSelfie); + onPresentationChanged(true); +}); + +// Handle user interaction +dom.on('#importButton', 'click', startImportFilePicker); +dom.on('#importFilePicker', 'change', handleImportFilePicker); +dom.on('#exportButton', 'click', exportUserRulesToFile); +dom.on('#revertButton', 'click', revertAllHandler); +dom.on('#commitButton', 'click', commitAllHandler); +dom.on('#editSaveButton', 'click', editSaveHandler); +dom.on('#ruleFilter input', 'input', onFilterChanged); +dom.on('#ruleFilter select', 'input', ( ) => { + onPresentationChanged(true); +}); +dom.on('#ruleFilter #diffCollapse', 'click', ev => { + isCollapsed = dom.cl.toggle(ev.target, 'active'); + onPresentationChanged(true); +}); + +// https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs +mergeView.editor().on('updateDiff', ( ) => { + onTextChanged(); +}); + +/******************************************************************************/ + diff --git a/src/js/dynamic-net-filtering.js b/src/js/dynamic-net-filtering.js new file mode 100644 index 0000000..ec7a7c9 --- /dev/null +++ b/src/js/dynamic-net-filtering.js @@ -0,0 +1,488 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2014-2018 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import punycode from '../lib/punycode.js'; + +import { LineIterator } from './text-utils.js'; + +import { + decomposeHostname, + domainFromHostname, +} from './uri-utils.js'; + +/******************************************************************************/ + +// Object.create(null) is used below to eliminate worries about unexpected +// property names in prototype chain -- and this way we don't have to use +// hasOwnProperty() to avoid this. + +const supportedDynamicTypes = Object.create(null); +Object.assign(supportedDynamicTypes, { + '3p': true, + 'image': true, +'inline-script': true, + '1p-script': true, + '3p-script': true, + '3p-frame': true +}); + +const typeBitOffsets = Object.create(null); +Object.assign(typeBitOffsets, { + '*': 0, +'inline-script': 2, + '1p-script': 4, + '3p-script': 6, + '3p-frame': 8, + 'image': 10, + '3p': 12 +}); + +const nameToActionMap = Object.create(null); +Object.assign(nameToActionMap, { + 'block': 1, + 'allow': 2, + 'noop': 3 +}); + +const intToActionMap = new Map([ + [ 1, 'block' ], + [ 2, 'allow' ], + [ 3, 'noop' ] +]); + +// For performance purpose, as simple tests as possible +const reBadHostname = /[^0-9a-z_.\[\]:%-]/; +const reNotASCII = /[^\x20-\x7F]/; +const decomposedSource = []; +const decomposedDestination = []; + +/******************************************************************************/ + +function is3rdParty(srcHostname, desHostname) { + // If at least one is party-less, the relation can't be labelled + // "3rd-party" + if ( desHostname === '*' || srcHostname === '*' || srcHostname === '' ) { + return false; + } + + // No domain can very well occurs, for examples: + // - localhost + // - file-scheme + // etc. + const srcDomain = domainFromHostname(srcHostname) || srcHostname; + + if ( desHostname.endsWith(srcDomain) === false ) { + return true; + } + // Do not confuse 'example.com' with 'anotherexample.com' + return desHostname.length !== srcDomain.length && + desHostname.charAt(desHostname.length - srcDomain.length - 1) !== '.'; +} + +/******************************************************************************/ + +class DynamicHostRuleFiltering { + + constructor() { + this.reset(); + } + + reset() { + this.r = 0; + this.type = ''; + this.y = ''; + this.z = ''; + this.rules = new Map(); + this.changed = false; + } + + assign(other) { + // Remove rules not in other + for ( const k of this.rules.keys() ) { + if ( other.rules.has(k) === false ) { + this.rules.delete(k); + this.changed = true; + } + } + // Add/change rules in other + for ( const entry of other.rules ) { + if ( this.rules.get(entry[0]) !== entry[1] ) { + this.rules.set(entry[0], entry[1]); + this.changed = true; + } + } + } + + copyRules(from, srcHostname, desHostnames) { + // Specific types + let thisBits = this.rules.get('* *'); + let fromBits = from.rules.get('* *'); + if ( fromBits !== thisBits ) { + if ( fromBits !== undefined ) { + this.rules.set('* *', fromBits); + } else { + this.rules.delete('* *'); + } + this.changed = true; + } + + let key = `${srcHostname} *`; + thisBits = this.rules.get(key); + fromBits = from.rules.get(key); + if ( fromBits !== thisBits ) { + if ( fromBits !== undefined ) { + this.rules.set(key, fromBits); + } else { + this.rules.delete(key); + } + this.changed = true; + } + + // Specific destinations + for ( const desHostname in desHostnames ) { + key = `* ${desHostname}`; + thisBits = this.rules.get(key); + fromBits = from.rules.get(key); + if ( fromBits !== thisBits ) { + if ( fromBits !== undefined ) { + this.rules.set(key, fromBits); + } else { + this.rules.delete(key); + } + this.changed = true; + } + key = `${srcHostname} ${desHostname}` ; + thisBits = this.rules.get(key); + fromBits = from.rules.get(key); + if ( fromBits !== thisBits ) { + if ( fromBits !== undefined ) { + this.rules.set(key, fromBits); + } else { + this.rules.delete(key); + } + this.changed = true; + } + } + + return this.changed; + } + + // - * * type + // - from * type + // - * to * + // - from to * + + hasSameRules(other, srcHostname, desHostnames) { + // Specific types + let key = '* *'; + if ( this.rules.get(key) !== other.rules.get(key) ) { return false; } + key = `${srcHostname} *`; + if ( this.rules.get(key) !== other.rules.get(key) ) { return false; } + // Specific destinations + for ( const desHostname in desHostnames ) { + key = `* ${desHostname}`; + if ( this.rules.get(key) !== other.rules.get(key) ) { + return false; + } + key = `${srcHostname} ${desHostname}`; + if ( this.rules.get(key) !== other.rules.get(key) ) { + return false; + } + } + return true; + } + + setCell(srcHostname, desHostname, type, state) { + const bitOffset = typeBitOffsets[type]; + const k = `${srcHostname} ${desHostname}`; + const oldBitmap = this.rules.get(k) || 0; + const newBitmap = oldBitmap & ~(3 << bitOffset) | (state << bitOffset); + if ( newBitmap === oldBitmap ) { return false; } + if ( newBitmap === 0 ) { + this.rules.delete(k); + } else { + this.rules.set(k, newBitmap); + } + this.changed = true; + return true; + } + + unsetCell(srcHostname, desHostname, type) { + this.evaluateCellZY(srcHostname, desHostname, type); + if ( this.r === 0 ) { return false; } + this.setCell(srcHostname, desHostname, type, 0); + this.changed = true; + return true; + } + + evaluateCell(srcHostname, desHostname, type) { + const key = `${srcHostname} ${desHostname}`; + const bitmap = this.rules.get(key); + if ( bitmap === undefined ) { return 0; } + return bitmap >> typeBitOffsets[type] & 3; + } + + clearRegisters() { + this.r = 0; + this.type = this.y = this.z = ''; + return this; + } + + evaluateCellZ(srcHostname, desHostname, type) { + decomposeHostname(srcHostname, decomposedSource); + this.type = type; + const bitOffset = typeBitOffsets[type]; + for ( const srchn of decomposedSource ) { + this.z = srchn; + let v = this.rules.get(`${srchn} ${desHostname}`); + if ( v === undefined ) { continue; } + v = v >>> bitOffset & 3; + if ( v === 0 ) { continue; } + return (this.r = v); + } + // srcHostname is '*' at this point + this.r = 0; + return 0; + } + + evaluateCellZY(srcHostname, desHostname, type) { + // Pathological cases. + if ( desHostname === '' ) { + this.r = 0; + return 0; + } + + // Precedence: from most specific to least specific + + // Specific-destination, any party, any type + decomposeHostname(desHostname, decomposedDestination); + for ( const deshn of decomposedDestination ) { + if ( deshn === '*' ) { break; } + this.y = deshn; + if ( this.evaluateCellZ(srcHostname, deshn, '*') !== 0 ) { + return this.r; + } + } + + const thirdParty = is3rdParty(srcHostname, desHostname); + + // Any destination + this.y = '*'; + + // Specific party + if ( thirdParty ) { + // 3rd-party, specific type + if ( type === 'script' ) { + if ( this.evaluateCellZ(srcHostname, '*', '3p-script') !== 0 ) { + return this.r; + } + } else if ( type === 'sub_frame' || type === 'object' ) { + if ( this.evaluateCellZ(srcHostname, '*', '3p-frame') !== 0 ) { + return this.r; + } + } + // 3rd-party, any type + if ( this.evaluateCellZ(srcHostname, '*', '3p') !== 0 ) { + return this.r; + } + } else if ( type === 'script' ) { + // 1st party, specific type + if ( this.evaluateCellZ(srcHostname, '*', '1p-script') !== 0 ) { + return this.r; + } + } + + // Any destination, any party, specific type + if ( supportedDynamicTypes[type] !== undefined ) { + if ( this.evaluateCellZ(srcHostname, '*', type) !== 0 ) { + return this.r; + } + if ( type.startsWith('3p-') ) { + if ( this.evaluateCellZ(srcHostname, '*', '3p') !== 0 ) { + return this.r; + } + } + } + + // Any destination, any party, any type + if ( this.evaluateCellZ(srcHostname, '*', '*') !== 0 ) { + return this.r; + } + + this.type = ''; + return 0; + } + + mustAllowCellZY(srcHostname, desHostname, type) { + return this.evaluateCellZY(srcHostname, desHostname, type) === 2; + } + + mustBlockOrAllow() { + return this.r === 1 || this.r === 2; + } + + mustBlock() { + return this.r === 1; + } + + mustAbort() { + return this.r === 3; + } + + lookupRuleData(src, des, type) { + const r = this.evaluateCellZY(src, des, type); + if ( r === 0 ) { return; } + return `${this.z} ${this.y} ${this.type} ${r}`; + } + + toLogData() { + if ( this.r === 0 || this.type === '' ) { return; } + return { + source: 'dynamicHost', + result: this.r, + raw: `${this.z} ${this.y} ${this.type} ${intToActionMap.get(this.r)}` + }; + } + + srcHostnameFromRule(rule) { + return rule.slice(0, rule.indexOf(' ')); + } + + desHostnameFromRule(rule) { + return rule.slice(rule.indexOf(' ') + 1); + } + + toArray() { + const out = []; + for ( const key of this.rules.keys() ) { + const srchn = this.srcHostnameFromRule(key); + const deshn = this.desHostnameFromRule(key); + const srchnPretty = srchn.includes('xn--') && punycode + ? punycode.toUnicode(srchn) + : srchn; + const deshnPretty = deshn.includes('xn--') && punycode + ? punycode.toUnicode(deshn) + : deshn; + for ( const type in typeBitOffsets ) { + if ( typeBitOffsets[type] === undefined ) { continue; } + const val = this.evaluateCell(srchn, deshn, type); + if ( val === 0 ) { continue; } + const action = intToActionMap.get(val); + if ( action === undefined ) { continue; } + out.push(`${srchnPretty} ${deshnPretty} ${type} ${action}`); + } + } + return out; + } + + toString() { + return this.toArray().join('\n'); + } + + fromString(text, append) { + const lineIter = new LineIterator(text); + if ( append !== true ) { this.reset(); } + while ( lineIter.eot() === false ) { + this.addFromRuleParts(lineIter.next().trim().split(/\s+/)); + } + } + + validateRuleParts(parts) { + if ( parts.length < 4 ) { return; } + + // Ignore hostname-based switch rules + if ( parts[0].endsWith(':') ) { return; } + + // Ignore URL-based rules + if ( parts[1].includes('/') ) { return; } + + if ( typeBitOffsets[parts[2]] === undefined ) { return; } + + if ( nameToActionMap[parts[3]] === undefined ) { return; } + + // https://github.com/chrisaljoudi/uBlock/issues/840 + // Discard invalid rules + if ( parts[1] !== '*' && parts[2] !== '*' ) { return; } + + // Performance: avoid punycoding when only ASCII chars + if ( punycode !== undefined ) { + if ( reNotASCII.test(parts[0]) ) { + parts[0] = punycode.toASCII(parts[0]); + } + if ( reNotASCII.test(parts[1]) ) { + parts[1] = punycode.toASCII(parts[1]); + } + } + + // https://github.com/chrisaljoudi/uBlock/issues/1082 + // Discard rules with invalid hostnames + if ( + (parts[0] !== '*' && reBadHostname.test(parts[0])) || + (parts[1] !== '*' && reBadHostname.test(parts[1])) + ) { + return; + } + + return parts; + } + + addFromRuleParts(parts) { + if ( this.validateRuleParts(parts) !== undefined ) { + this.setCell(parts[0], parts[1], parts[2], nameToActionMap[parts[3]]); + return true; + } + return false; + } + + removeFromRuleParts(parts) { + if ( this.validateRuleParts(parts) !== undefined ) { + this.setCell(parts[0], parts[1], parts[2], 0); + return true; + } + return false; + } + + toSelfie() { + return { + magicId: this.magicId, + rules: Array.from(this.rules) + }; + } + + fromSelfie(selfie) { + if ( selfie.magicId !== this.magicId ) { return false; } + this.rules = new Map(selfie.rules); + this.changed = true; + return true; + } +} + +DynamicHostRuleFiltering.prototype.magicId = 1; + +/******************************************************************************/ + +export default DynamicHostRuleFiltering; + +/******************************************************************************/ diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js new file mode 100644 index 0000000..49fc116 --- /dev/null +++ b/src/js/epicker-ui.js @@ -0,0 +1,900 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* global CodeMirror */ + +'use strict'; + +import './codemirror/ubo-static-filtering.js'; + +import { hostnameFromURI } from './uri-utils.js'; +import punycode from '../lib/punycode.js'; +import * as sfp from './static-filtering-parser.js'; + +/******************************************************************************/ +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } + +const $id = id => document.getElementById(id); +const $stor = selector => document.querySelector(selector); +const $storAll = selector => document.querySelectorAll(selector); + +const pickerRoot = document.documentElement; +const dialog = $stor('aside'); +let staticFilteringParser; + +const svgRoot = $stor('svg'); +const svgOcean = svgRoot.children[0]; +const svgIslands = svgRoot.children[1]; +const NoPaths = 'M0 0'; + +const reCosmeticAnchor = /^#(\$|\?|\$\?)?#/; + +{ + const url = new URL(self.location.href); + if ( url.searchParams.has('zap') ) { + pickerRoot.classList.add('zap'); + } +} + +const docURL = new URL(vAPI.getURL('')); + +let resultsetOpt; + +let netFilterCandidates = []; +let cosmeticFilterCandidates = []; +let computedCandidateSlot = 0; +let computedCandidate = ''; +const computedSpecificityCandidates = new Map(); +let needBody = false; + +/******************************************************************************/ + +const cmEditor = new CodeMirror(document.querySelector('.codeMirrorContainer'), { + autoCloseBrackets: true, + autofocus: true, + extraKeys: { + 'Ctrl-Space': 'autocomplete', + }, + lineWrapping: true, + matchBrackets: true, + maxScanLines: 1, +}); + +vAPI.messaging.send('dashboard', { + what: 'getAutoCompleteDetails' +}).then(hints => { + // For unknown reasons, `instanceof Object` does not work here in Firefox. + if ( hints instanceof Object === false ) { return; } + cmEditor.setOption('uboHints', hints); +}); + +/******************************************************************************/ + +const rawFilterFromTextarea = function() { + const text = cmEditor.getValue(); + const pos = text.indexOf('\n'); + return pos === -1 ? text : text.slice(0, pos); +}; + +/******************************************************************************/ + +const filterFromTextarea = function() { + const filter = rawFilterFromTextarea(); + if ( filter === '' ) { return ''; } + const parser = staticFilteringParser; + parser.parse(filter); + if ( parser.isFilter() === false ) { return '!'; } + if ( parser.isExtendedFilter() ) { + if ( parser.isCosmeticFilter() === false ) { return '!'; } + } else if ( parser.isNetworkFilter() === false ) { + return '!'; + } + return filter; +}; + +/******************************************************************************/ + +const renderRange = function(id, value, invert = false) { + const input = $stor(`#${id} input`); + const max = parseInt(input.max, 10); + if ( typeof value !== 'number' ) { + value = parseInt(input.value, 10); + } + if ( invert ) { + value = max - value; + } + input.value = value; + const slider = $stor(`#${id} > span`); + const lside = slider.children[0]; + const thumb = slider.children[1]; + const sliderWidth = slider.offsetWidth; + const maxPercent = (sliderWidth - thumb.offsetWidth) / sliderWidth * 100; + const widthPercent = value / max * maxPercent; + lside.style.width = `${widthPercent}%`; +}; + +/******************************************************************************/ + +const userFilterFromCandidate = function(filter) { + if ( filter === '' || filter === '!' ) { return; } + + let hn = hostnameFromURI(docURL.href); + if ( hn.startsWith('xn--') ) { + hn = punycode.toUnicode(hn); + } + + // Cosmetic filter? + if ( reCosmeticAnchor.test(filter) ) { + return hn + filter; + } + + // Assume net filter + const opts = []; + + // If no domain included in filter, we need domain option + if ( filter.startsWith('||') === false ) { + opts.push(`domain=${hn}`); + } + + if ( resultsetOpt !== undefined ) { + opts.push(resultsetOpt); + } + + if ( opts.length ) { + filter += '$' + opts.join(','); + } + + return filter; +}; + +/******************************************************************************/ + +const candidateFromFilterChoice = function(filterChoice) { + let { slot, filters } = filterChoice; + let filter = filters[slot]; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/47 + for ( const elem of $storAll('#candidateFilters li') ) { + elem.classList.remove('active'); + } + + computedCandidateSlot = slot; + computedCandidate = ''; + + if ( filter === undefined ) { return ''; } + + // For net filters there no such thing as a path + if ( filter.startsWith('##') === false ) { + $stor(`#netFilters li:nth-of-type(${slot+1})`) + .classList.add('active'); + return filter; + } + + // At this point, we have a cosmetic filter + + $stor(`#cosmeticFilters li:nth-of-type(${slot+1})`) + .classList.add('active'); + + return cosmeticCandidatesFromFilterChoice(filterChoice); +}; + +/******************************************************************************/ + +const cosmeticCandidatesFromFilterChoice = function(filterChoice) { + let { slot, filters } = filterChoice; + + renderRange('resultsetDepth', slot, true); + renderRange('resultsetSpecificity'); + + if ( computedSpecificityCandidates.has(slot) ) { + onCandidatesOptimized({ slot }); + return; + } + + const specificities = [ + 0b0000, // remove hierarchy; remove id, nth-of-type, attribute values + 0b0010, // remove hierarchy; remove id, nth-of-type + 0b0011, // remove hierarchy + 0b1000, // trim hierarchy; remove id, nth-of-type, attribute values + 0b1010, // trim hierarchy; remove id, nth-of-type + 0b1100, // remove id, nth-of-type, attribute values + 0b1110, // remove id, nth-of-type + 0b1111, // keep all = most specific + ]; + + const candidates = []; + + let filter = filters[slot]; + + for ( const specificity of specificities ) { + // Return path: the target element, then all siblings prepended + const paths = []; + for ( let i = slot; i < filters.length; i++ ) { + filter = filters[i].slice(2); + // Remove id, nth-of-type + // https://github.com/uBlockOrigin/uBlock-issues/issues/162 + // Mind escaped periods: they do not denote a class identifier. + if ( (specificity & 0b0001) === 0 ) { + filter = filter.replace(/:nth-of-type\(\d+\)/, ''); + if ( + filter.charAt(0) === '#' && ( + (specificity & 0b1000) === 0 || i === slot + ) + ) { + const pos = filter.search(/[^\\]\./); + if ( pos !== -1 ) { + filter = filter.slice(pos + 1); + } + } + } + // Remove attribute values. + if ( (specificity & 0b0010) === 0 ) { + const match = /^\[([^^*$=]+)[\^*$]?=.+\]$/.exec(filter); + if ( match !== null ) { + filter = `[${match[1]}]`; + } + } + // Remove all classes when an id exists. + // https://github.com/uBlockOrigin/uBlock-issues/issues/162 + // Mind escaped periods: they do not denote a class identifier. + if ( filter.charAt(0) === '#' ) { + filter = filter.replace(/([^\\])\..+$/, '$1'); + } + if ( paths.length !== 0 ) { + filter += ' > '; + } + paths.unshift(filter); + // Stop at any element with an id: these are unique in a web page + if ( (specificity & 0b1000) === 0 || filter.startsWith('#') ) { + break; + } + } + + // Trim hierarchy: remove generic elements from path + if ( (specificity & 0b1100) === 0b1000 ) { + let i = 0; + while ( i < paths.length - 1 ) { + if ( /^[a-z0-9]+ > $/.test(paths[i+1]) ) { + if ( paths[i].endsWith(' > ') ) { + paths[i] = paths[i].slice(0, -2); + } + paths.splice(i + 1, 1); + } else { + i += 1; + } + } + } + + if ( + needBody && + paths.length !== 0 && + paths[0].startsWith('#') === false && + paths[0].startsWith('body ') === false && + (specificity & 0b1100) !== 0 + ) { + paths.unshift('body > '); + } + + candidates.push(paths); + } + + pickerContentPort.postMessage({ + what: 'optimizeCandidates', + candidates, + slot, + }); +}; + +/******************************************************************************/ + +const onCandidatesOptimized = function(details) { + $id('resultsetModifiers').classList.remove('hide'); + const i = parseInt($stor('#resultsetSpecificity input').value, 10); + if ( Array.isArray(details.candidates) ) { + computedSpecificityCandidates.set(details.slot, details.candidates); + } + const candidates = computedSpecificityCandidates.get(details.slot); + computedCandidate = candidates[i]; + cmEditor.setValue(computedCandidate); + cmEditor.clearHistory(); + onCandidateChanged(); +}; + +/******************************************************************************/ + +const onSvgClicked = function(ev) { + // If zap mode, highlight element under mouse, this makes the zapper usable + // on touch screens. + if ( pickerRoot.classList.contains('zap') ) { + pickerContentPort.postMessage({ + what: 'zapElementAtPoint', + mx: ev.clientX, + my: ev.clientY, + options: { + stay: ev.shiftKey || ev.type === 'touch', + highlight: ev.target !== svgIslands, + }, + }); + return; + } + // https://github.com/chrisaljoudi/uBlock/issues/810#issuecomment-74600694 + // Unpause picker if: + // - click outside dialog AND + // - not in preview mode + if ( pickerRoot.classList.contains('paused') ) { + if ( pickerRoot.classList.contains('preview') === false ) { + unpausePicker(); + } + return; + } + // Force dialog to always be visible when using a touch-driven device. + if ( ev.type === 'touch' ) { + pickerRoot.classList.add('show'); + } + pickerContentPort.postMessage({ + what: 'filterElementAtPoint', + mx: ev.clientX, + my: ev.clientY, + broad: ev.ctrlKey, + }); +}; + +/******************************************************************************* + + Swipe right: + If picker not paused: quit picker + If picker paused and dialog visible: hide dialog + If picker paused and dialog not visible: quit picker + + Swipe left: + If picker paused and dialog not visible: show dialog + +*/ + +const onSvgTouch = (( ) => { + let startX = 0, startY = 0; + let t0 = 0; + return ev => { + if ( ev.type === 'touchstart' ) { + startX = ev.touches[0].screenX; + startY = ev.touches[0].screenY; + t0 = ev.timeStamp; + return; + } + if ( startX === undefined ) { return; } + const stopX = ev.changedTouches[0].screenX; + const stopY = ev.changedTouches[0].screenY; + const angle = Math.abs(Math.atan2(stopY - startY, stopX - startX)); + const distance = Math.sqrt( + Math.pow(stopX - startX, 2), + Math.pow(stopY - startY, 2) + ); + // Interpret touch events as a tap if: + // - Swipe is not valid; and + // - The time between start and stop was less than 200ms. + const duration = ev.timeStamp - t0; + if ( distance < 32 && duration < 200 ) { + onSvgClicked({ + type: 'touch', + target: ev.target, + clientX: ev.changedTouches[0].pageX, + clientY: ev.changedTouches[0].pageY, + }); + ev.preventDefault(); + return; + } + if ( distance < 64 ) { return; } + const angleUpperBound = Math.PI * 0.25 * 0.5; + const swipeRight = angle < angleUpperBound; + if ( swipeRight === false && angle < Math.PI - angleUpperBound ) { + return; + } + if ( ev.cancelable ) { + ev.preventDefault(); + } + // Swipe left. + if ( swipeRight === false ) { + if ( pickerRoot.classList.contains('paused') ) { + pickerRoot.classList.remove('hide'); + pickerRoot.classList.add('show'); + } + return; + } + // Swipe right. + if ( + pickerRoot.classList.contains('zap') && + svgIslands.getAttribute('d') !== NoPaths + ) { + pickerContentPort.postMessage({ + what: 'unhighlight' + }); + return; + } + else if ( + pickerRoot.classList.contains('paused') && + pickerRoot.classList.contains('show') + ) { + pickerRoot.classList.remove('show'); + pickerRoot.classList.add('hide'); + return; + } + quitPicker(); + }; +})(); + +/******************************************************************************/ + +const onCandidateChanged = function() { + const filter = filterFromTextarea(); + const bad = filter === '!'; + $stor('section').classList.toggle('invalidFilter', bad); + if ( bad ) { + $id('resultsetCount').textContent = 'E'; + $id('create').setAttribute('disabled', ''); + } + const text = rawFilterFromTextarea(); + $id('resultsetModifiers').classList.toggle( + 'hide', text === '' || text !== computedCandidate + ); + pickerContentPort.postMessage({ + what: 'dialogSetFilter', + filter, + compiled: reCosmeticAnchor.test(filter) + ? staticFilteringParser.result.compiled + : undefined, + }); +}; + +/******************************************************************************/ + +const onPreviewClicked = function() { + const state = pickerRoot.classList.toggle('preview'); + pickerContentPort.postMessage({ + what: 'togglePreview', + state, + }); +}; + +/******************************************************************************/ + +const onCreateClicked = function() { + const candidate = filterFromTextarea(); + const filter = userFilterFromCandidate(candidate); + if ( filter !== undefined ) { + vAPI.messaging.send('elementPicker', { + what: 'createUserFilter', + autoComment: true, + filters: filter, + docURL: docURL.href, + killCache: reCosmeticAnchor.test(candidate) === false, + }); + } + pickerContentPort.postMessage({ + what: 'dialogCreate', + filter: candidate, + compiled: reCosmeticAnchor.test(candidate) + ? staticFilteringParser.result.compiled + : undefined, + }); +}; + +/******************************************************************************/ + +const onPickClicked = function() { + unpausePicker(); +}; + +/******************************************************************************/ + +const onQuitClicked = function() { + quitPicker(); +}; + +/******************************************************************************/ + +const onDepthChanged = function() { + const input = $stor('#resultsetDepth input'); + const max = parseInt(input.max, 10); + const value = parseInt(input.value, 10); + const text = candidateFromFilterChoice({ + filters: cosmeticFilterCandidates, + slot: max - value, + }); + if ( text === undefined ) { return; } + cmEditor.setValue(text); + cmEditor.clearHistory(); + onCandidateChanged(); +}; + +/******************************************************************************/ + +const onSpecificityChanged = function() { + renderRange('resultsetSpecificity'); + if ( rawFilterFromTextarea() !== computedCandidate ) { return; } + const depthInput = $stor('#resultsetDepth input'); + const slot = parseInt(depthInput.max, 10) - parseInt(depthInput.value, 10); + const i = parseInt($stor('#resultsetSpecificity input').value, 10); + const candidates = computedSpecificityCandidates.get(slot); + computedCandidate = candidates[i]; + cmEditor.setValue(computedCandidate); + cmEditor.clearHistory(); + onCandidateChanged(); +}; + +/******************************************************************************/ + +const onCandidateClicked = function(ev) { + let li = ev.target.closest('li'); + if ( li === null ) { return; } + const ul = li.closest('.changeFilter'); + if ( ul === null ) { return; } + const choice = { + filters: Array.from(ul.querySelectorAll('li')).map(a => a.textContent), + slot: 0, + }; + while ( li.previousElementSibling !== null ) { + li = li.previousElementSibling; + choice.slot += 1; + } + const text = candidateFromFilterChoice(choice); + if ( text === undefined ) { return; } + cmEditor.setValue(text); + cmEditor.clearHistory(); + onCandidateChanged(); +}; + +/******************************************************************************/ + +const onKeyPressed = function(ev) { + // Delete + if ( + (ev.key === 'Delete' || ev.key === 'Backspace') && + pickerRoot.classList.contains('zap') + ) { + pickerContentPort.postMessage({ + what: 'zapElementAtPoint', + options: { stay: true }, + }); + return; + } + // Esc + if ( ev.key === 'Escape' || ev.which === 27 ) { + onQuitClicked(); + return; + } +}; + +/******************************************************************************/ + +const onStartMoving = (( ) => { + let isTouch = false; + let mx0 = 0, my0 = 0; + let mx1 = 0, my1 = 0; + let r0 = 0, b0 = 0; + let rMax = 0, bMax = 0; + let timer; + + const eatEvent = function(ev) { + ev.stopPropagation(); + ev.preventDefault(); + }; + + const move = ( ) => { + timer = undefined; + const r1 = Math.min(Math.max(r0 - mx1 + mx0, 2), rMax); + const b1 = Math.min(Math.max(b0 - my1 + my0, 2), bMax); + dialog.style.setProperty('right', `${r1}px`); + dialog.style.setProperty('bottom', `${b1}px`); + }; + + const moveAsync = ev => { + if ( timer !== undefined ) { return; } + if ( isTouch ) { + const touch = ev.touches[0]; + mx1 = touch.pageX; + my1 = touch.pageY; + } else { + mx1 = ev.pageX; + my1 = ev.pageY; + } + timer = self.requestAnimationFrame(move); + }; + + const stop = ev => { + if ( dialog.classList.contains('moving') === false ) { return; } + dialog.classList.remove('moving'); + if ( isTouch ) { + self.removeEventListener('touchmove', moveAsync, { capture: true }); + } else { + self.removeEventListener('mousemove', moveAsync, { capture: true }); + } + eatEvent(ev); + }; + + return function(ev) { + const target = dialog.querySelector('#move'); + if ( ev.target !== target ) { return; } + if ( dialog.classList.contains('moving') ) { return; } + isTouch = ev.type.startsWith('touch'); + if ( isTouch ) { + const touch = ev.touches[0]; + mx0 = touch.pageX; + my0 = touch.pageY; + } else { + mx0 = ev.pageX; + my0 = ev.pageY; + } + const style = self.getComputedStyle(dialog); + r0 = parseInt(style.right, 10); + b0 = parseInt(style.bottom, 10); + const rect = dialog.getBoundingClientRect(); + rMax = pickerRoot.clientWidth - 2 - rect.width ; + bMax = pickerRoot.clientHeight - 2 - rect.height; + dialog.classList.add('moving'); + if ( isTouch ) { + self.addEventListener('touchmove', moveAsync, { capture: true }); + self.addEventListener('touchend', stop, { capture: true, once: true }); + } else { + self.addEventListener('mousemove', moveAsync, { capture: true }); + self.addEventListener('mouseup', stop, { capture: true, once: true }); + } + eatEvent(ev); + }; +})(); + +/******************************************************************************/ + +const svgListening = (( ) => { + let on = false; + let timer; + let mx = 0, my = 0; + + const onTimer = ( ) => { + timer = undefined; + pickerContentPort.postMessage({ + what: 'highlightElementAtPoint', + mx, + my, + }); + }; + + const onHover = ev => { + mx = ev.clientX; + my = ev.clientY; + if ( timer === undefined ) { + timer = self.requestAnimationFrame(onTimer); + } + }; + + return state => { + if ( state === on ) { return; } + on = state; + if ( on ) { + document.addEventListener('mousemove', onHover, { passive: true }); + return; + } + document.removeEventListener('mousemove', onHover, { passive: true }); + if ( timer !== undefined ) { + self.cancelAnimationFrame(timer); + timer = undefined; + } + }; +})(); + +/******************************************************************************/ + +// Create lists of candidate filters. This takes into account whether the +// current mode is narrow or broad. + +const populateCandidates = function(candidates, selector) { + + const root = dialog.querySelector(selector); + const ul = root.querySelector('ul'); + while ( ul.firstChild !== null ) { + ul.firstChild.remove(); + } + for ( let i = 0; i < candidates.length; i++ ) { + const li = document.createElement('li'); + li.textContent = candidates[i]; + ul.appendChild(li); + } + if ( candidates.length !== 0 ) { + root.style.removeProperty('display'); + } else { + root.style.setProperty('display', 'none'); + } +}; + +/******************************************************************************/ + +const showDialog = function(details) { + pausePicker(); + + const { netFilters, cosmeticFilters, filter } = details; + + netFilterCandidates = netFilters; + + needBody = + cosmeticFilters.length !== 0 && + cosmeticFilters[cosmeticFilters.length - 1] === '##body'; + if ( needBody ) { + cosmeticFilters.pop(); + } + cosmeticFilterCandidates = cosmeticFilters; + + docURL.href = details.url; + + populateCandidates(netFilters, '#netFilters'); + populateCandidates(cosmeticFilters, '#cosmeticFilters'); + computedSpecificityCandidates.clear(); + + const depthInput = $stor('#resultsetDepth input'); + depthInput.max = cosmeticFilters.length - 1; + depthInput.value = depthInput.max; + + dialog.querySelector('ul').style.display = + netFilters.length || cosmeticFilters.length ? '' : 'none'; + $id('create').setAttribute('disabled', ''); + + // Auto-select a candidate filter + + // 2020-09-01: + // In Firefox, `details instanceof Object` resolves to `false` despite + // `details` being a valid object. Consequently, falling back to use + // `typeof details`. + // This is an issue which surfaced when the element picker code was + // revisited to isolate the picker dialog DOM from the page DOM. + if ( typeof filter !== 'object' || filter === null ) { + cmEditor.setValue(''); + return; + } + + const filterChoice = { + filters: filter.filters, + slot: filter.slot, + }; + + const text = candidateFromFilterChoice(filterChoice); + if ( text === undefined ) { return; } + cmEditor.setValue(text); + onCandidateChanged(); +}; + +/******************************************************************************/ + +const pausePicker = function() { + pickerRoot.classList.add('paused'); + svgListening(false); +}; + +/******************************************************************************/ + +const unpausePicker = function() { + pickerRoot.classList.remove('paused', 'preview'); + pickerContentPort.postMessage({ + what: 'togglePreview', + state: false, + }); + svgListening(true); +}; + +/******************************************************************************/ + +const startPicker = function() { + self.addEventListener('keydown', onKeyPressed, true); + const svg = $stor('svg'); + svg.addEventListener('click', onSvgClicked); + svg.addEventListener('touchstart', onSvgTouch); + svg.addEventListener('touchend', onSvgTouch); + + unpausePicker(); + + if ( pickerRoot.classList.contains('zap') ) { return; } + + cmEditor.on('changes', onCandidateChanged); + + $id('preview').addEventListener('click', onPreviewClicked); + $id('create').addEventListener('click', onCreateClicked); + $id('pick').addEventListener('click', onPickClicked); + $id('quit').addEventListener('click', onQuitClicked); + $id('move').addEventListener('mousedown', onStartMoving); + $id('move').addEventListener('touchstart', onStartMoving); + $id('candidateFilters').addEventListener('click', onCandidateClicked); + $stor('#resultsetDepth input').addEventListener('input', onDepthChanged); + $stor('#resultsetSpecificity input').addEventListener('input', onSpecificityChanged); + staticFilteringParser = new sfp.AstFilterParser({ + interactive: true, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); +}; + +/******************************************************************************/ + +const quitPicker = function() { + pickerContentPort.postMessage({ what: 'quitPicker' }); + pickerContentPort.close(); + pickerContentPort = undefined; +}; + +/******************************************************************************/ + +const onPickerMessage = function(msg) { + switch ( msg.what ) { + case 'candidatesOptimized': + onCandidatesOptimized(msg); + break; + case 'showDialog': + showDialog(msg); + break; + case 'resultsetDetails': { + resultsetOpt = msg.opt; + $id('resultsetCount').textContent = msg.count; + if ( msg.count !== 0 ) { + $id('create').removeAttribute('disabled'); + } else { + $id('create').setAttribute('disabled', ''); + } + break; + } + case 'svgPaths': { + let { ocean, islands } = msg; + ocean += islands; + svgOcean.setAttribute('d', ocean); + svgIslands.setAttribute('d', islands || NoPaths); + break; + } + default: + break; + } +}; + +/******************************************************************************/ + +// Wait for the content script to establish communication + +let pickerContentPort; + +globalThis.addEventListener('message', ev => { + const msg = ev.data || {}; + if ( msg.what !== 'epickerStart' ) { return; } + if ( Array.isArray(ev.ports) === false ) { return; } + if ( ev.ports.length === 0 ) { return; } + pickerContentPort = ev.ports[0]; + pickerContentPort.onmessage = ev => { + const msg = ev.data || {}; + onPickerMessage(msg); + }; + pickerContentPort.onmessageerror = ( ) => { + quitPicker(); + }; + startPicker(); + pickerContentPort.postMessage({ what: 'start' }); +}, { once: true }); + +/******************************************************************************/ + +})(); diff --git a/src/js/fa-icons.js b/src/js/fa-icons.js new file mode 100644 index 0000000..79968d0 --- /dev/null +++ b/src/js/fa-icons.js @@ -0,0 +1,129 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2018-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/uMatrix +*/ + +'use strict'; + +/******************************************************************************/ + +export const faIconsInit = (( ) => { + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1196 + const svgIcons = new Map([ + // See /img/fontawesome/fontawesome-defs.svg + [ 'angle-up', { viewBox: '0 0 998 582', path: 'm 998,499 q 0,13 -10,23 l -50,50 q -10,10 -23,10 -13,0 -23,-10 L 499,179 106,572 Q 96,582 83,582 70,582 60,572 L 10,522 Q 0,512 0,499 0,486 10,476 L 476,10 q 10,-10 23,-10 13,0 23,10 l 466,466 q 10,10 10,23 z' } ], + [ 'arrow-right', { viewBox: '0 0 1472 1558', path: 'm 1472,779 q 0,54 -37,91 l -651,651 q -39,37 -91,37 -51,0 -90,-37 l -75,-75 q -38,-38 -38,-91 0,-53 38,-91 L 821,971 H 117 Q 65,971 32.5,933.5 0,896 0,843 V 715 Q 0,662 32.5,624.5 65,587 117,587 H 821 L 528,293 q -38,-36 -38,-90 0,-54 38,-90 l 75,-75 q 38,-38 90,-38 53,0 91,38 l 651,651 q 37,35 37,90 z' } ], + [ 'bar-chart', { viewBox: '0 0 2048 1536', path: 'm 640,768 0,512 -256,0 0,-512 256,0 z m 384,-512 0,1024 -256,0 0,-1024 256,0 z m 1024,1152 0,128 L 0,1536 0,0 l 128,0 0,1408 1920,0 z m -640,-896 0,768 -256,0 0,-768 256,0 z m 384,-384 0,1152 -256,0 0,-1152 256,0 z' } ], + [ 'bolt', { viewBox: '0 0 896 1664', path: 'm 885.08696,438 q 18,20 7,44 l -540,1157 q -13,25 -42,25 -4,0 -14,-2 -17,-5 -25.5,-19 -8.5,-14 -4.5,-30 l 197,-808 -406,101 q -4,1 -12,1 -18,0 -31,-11 Q -3.9130435,881 1.0869565,857 L 202.08696,32 q 4,-14 16,-23 12,-9 28,-9 l 328,0 q 19,0 32,12.5 13,12.5 13,29.5 0,8 -5,18 l -171,463 396,-98 q 8,-2 12,-2 19,0 34,15 z' } ], + [ 'clipboard', { viewBox: '0 0 1792 1792', path: 'm 768,1664 896,0 0,-640 -416,0 q -40,0 -68,-28 -28,-28 -28,-68 l 0,-416 -384,0 0,1152 z m 256,-1440 0,-64 q 0,-13 -9.5,-22.5 Q 1005,128 992,128 l -704,0 q -13,0 -22.5,9.5 Q 256,147 256,160 l 0,64 q 0,13 9.5,22.5 9.5,9.5 22.5,9.5 l 704,0 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-22.5 z m 256,672 299,0 -299,-299 0,299 z m 512,128 0,672 q 0,40 -28,68 -28,28 -68,28 l -960,0 q -40,0 -68,-28 -28,-28 -28,-68 l 0,-160 -544,0 Q 56,1536 28,1508 0,1480 0,1440 L 0,96 Q 0,56 28,28 56,0 96,0 l 1088,0 q 40,0 68,28 28,28 28,68 l 0,328 q 21,13 36,28 l 408,408 q 28,28 48,76 20,48 20,88 z' } ], + [ 'clock-o', { viewBox: '0 0 1536 1536', path: 'm 896,416 v 448 q 0,14 -9,23 -9,9 -23,9 H 544 q -14,0 -23,-9 -9,-9 -9,-23 v -64 q 0,-14 9,-23 9,-9 23,-9 H 768 V 416 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 416,352 q 0,-148 -73,-273 -73,-125 -198,-198 -125,-73 -273,-73 -148,0 -273,73 -125,73 -198,198 -73,125 -73,273 0,148 73,273 73,125 198,198 125,73 273,73 148,0 273,-73 125,-73 198,-198 73,-125 73,-273 z m 224,0 q 0,209 -103,385.5 Q 1330,1330 1153.5,1433 977,1536 768,1536 559,1536 382.5,1433 206,1330 103,1153.5 0,977 0,768 0,559 103,382.5 206,206 382.5,103 559,0 768,0 977,0 1153.5,103 1330,206 1433,382.5 1536,559 1536,768 Z' } ], + [ 'cloud-download', { viewBox: '0 0 1920 1408', path: 'm 1280,800 q 0,-14 -9,-23 -9,-9 -23,-9 l -224,0 0,-352 q 0,-13 -9.5,-22.5 Q 1005,384 992,384 l -192,0 q -13,0 -22.5,9.5 Q 768,403 768,416 l 0,352 -224,0 q -13,0 -22.5,9.5 -9.5,9.5 -9.5,22.5 0,14 9,23 l 352,352 q 9,9 23,9 14,0 23,-9 l 351,-351 q 10,-12 10,-24 z m 640,224 q 0,159 -112.5,271.5 Q 1695,1408 1536,1408 l -1088,0 Q 263,1408 131.5,1276.5 0,1145 0,960 0,830 70,720 140,610 258,555 256,525 256,512 256,300 406,150 556,0 768,0 q 156,0 285.5,87 129.5,87 188.5,231 71,-62 166,-62 106,0 181,75 75,75 75,181 0,76 -41,138 130,31 213.5,135.5 Q 1920,890 1920,1024 Z' } ], + [ 'cloud-upload', { viewBox: '0 0 1920 1408', path: 'm 1280,736 q 0,-14 -9,-23 L 919,361 q -9,-9 -23,-9 -14,0 -23,9 L 522,712 q -10,12 -10,24 0,14 9,23 9,9 23,9 l 224,0 0,352 q 0,13 9.5,22.5 9.5,9.5 22.5,9.5 l 192,0 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-22.5 l 0,-352 224,0 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-22.5 z m 640,288 q 0,159 -112.5,271.5 Q 1695,1408 1536,1408 l -1088,0 Q 263,1408 131.5,1276.5 0,1145 0,960 0,830 70,720 140,610 258,555 256,525 256,512 256,300 406,150 556,0 768,0 q 156,0 285.5,87 129.5,87 188.5,231 71,-62 166,-62 106,0 181,75 75,75 75,181 0,76 -41,138 130,31 213.5,135.5 Q 1920,890 1920,1024 Z' } ], + [ 'check', { viewBox: '0 0 1550 1188', path: 'm 1550,232 q 0,40 -28,68 l -724,724 -136,136 q -28,28 -68,28 -40,0 -68,-28 L 390,1024 28,662 Q 0,634 0,594 0,554 28,526 L 164,390 q 28,-28 68,-28 40,0 68,28 L 594,685 1250,28 q 28,-28 68,-28 40,0 68,28 l 136,136 q 28,28 28,68 z' } ], + [ 'code', { viewBox: '0 0 1830 1373', path: 'm 572,1125.5 -50,50 q -10,10 -23,10 -13,0 -23,-10 l -466,-466 q -10,-10 -10,-23 0,-13 10,-23 l 466,-466 q 10,-10 23,-10 13,0 23,10 l 50,50 q 10,10 10,23 0,13 -10,23 l -393,393 393,393 q 10,10 10,23 0,13 -10,23 z M 1163,58.476203 790,1349.4762 q -4,13 -15.5,19.5 -11.5,6.5 -23.5,2.5 l -62,-17 q -13,-4 -19.5,-15.5 -6.5,-11.5 -2.5,-24.5 L 1040,23.5 q 4,-13 15.5,-19.5 11.5,-6.5 23.5,-2.5 l 62,17 q 13,4 19.5,15.5 6.5,11.5 2.5,24.5 z m 657,651 -466,466 q -10,10 -23,10 -13,0 -23,-10 l -50,-50 q -10,-10 -10,-23 0,-13 10,-23 l 393,-393 -393,-393 q -10,-10 -10,-23 0,-13 10,-23 l 50,-50 q 10,-10 23,-10 13,0 23,10 l 466,466 q 10,10 10,23 0,13 -10,23 z' } ], + [ 'cog', { viewBox: '0 0 1536 1536', path: 'm 1024,768 q 0,-106 -75,-181 -75,-75 -181,-75 -106,0 -181,75 -75,75 -75,181 0,106 75,181 75,75 181,75 106,0 181,-75 75,-75 75,-181 z m 512,-109 0,222 q 0,12 -8,23 -8,11 -20,13 l -185,28 q -19,54 -39,91 35,50 107,138 10,12 10,25 0,13 -9,23 -27,37 -99,108 -72,71 -94,71 -12,0 -26,-9 l -138,-108 q -44,23 -91,38 -16,136 -29,186 -7,28 -36,28 l -222,0 q -14,0 -24.5,-8.5 Q 622,1519 621,1506 l -28,-184 q -49,-16 -90,-37 l -141,107 q -10,9 -25,9 -14,0 -25,-11 -126,-114 -165,-168 -7,-10 -7,-23 0,-12 8,-23 15,-21 51,-66.5 36,-45.5 54,-70.5 -27,-50 -41,-99 L 29,913 Q 16,911 8,900.5 0,890 0,877 L 0,655 q 0,-12 8,-23 8,-11 19,-13 l 186,-28 q 14,-46 39,-92 -40,-57 -107,-138 -10,-12 -10,-24 0,-10 9,-23 26,-36 98.5,-107.5 Q 315,135 337,135 q 13,0 26,10 L 501,252 Q 545,229 592,214 608,78 621,28 628,0 657,0 L 879,0 Q 893,0 903.5,8.5 914,17 915,30 l 28,184 q 49,16 90,37 l 142,-107 q 9,-9 24,-9 13,0 25,10 129,119 165,170 7,8 7,22 0,12 -8,23 -15,21 -51,66.5 -36,45.5 -54,70.5 26,50 41,98 l 183,28 q 13,2 21,12.5 8,10.5 8,23.5 z' } ], + [ 'cogs', { viewBox: '0 0 1920 1761', path: 'm 896,880 q 0,-106 -75,-181 -75,-75 -181,-75 -106,0 -181,75 -75,75 -75,181 0,106 75,181 75,75 181,75 106,0 181,-75 75,-75 75,-181 z m 768,512 q 0,-52 -38,-90 -38,-38 -90,-38 -52,0 -90,38 -38,38 -38,90 0,53 37.5,90.5 37.5,37.5 90.5,37.5 53,0 90.5,-37.5 37.5,-37.5 37.5,-90.5 z m 0,-1024 q 0,-52 -38,-90 -38,-38 -90,-38 -52,0 -90,38 -38,38 -38,90 0,53 37.5,90.5 37.5,37.5 90.5,37.5 53,0 90.5,-37.5 Q 1664,421 1664,368 Z m -384,421 v 185 q 0,10 -7,19.5 -7,9.5 -16,10.5 l -155,24 q -11,35 -32,76 34,48 90,115 7,11 7,20 0,12 -7,19 -23,30 -82.5,89.5 -59.5,59.5 -78.5,59.5 -11,0 -21,-7 l -115,-90 q -37,19 -77,31 -11,108 -23,155 -7,24 -30,24 H 547 q -11,0 -20,-7.5 -9,-7.5 -10,-17.5 l -23,-153 q -34,-10 -75,-31 l -118,89 q -7,7 -20,7 -11,0 -21,-8 -144,-133 -144,-160 0,-9 7,-19 10,-14 41,-53 31,-39 47,-61 -23,-44 -35,-82 L 24,1000 Q 14,999 7,990.5 0,982 0,971 V 786 Q 0,776 7,766.5 14,757 23,756 l 155,-24 q 11,-35 32,-76 -34,-48 -90,-115 -7,-11 -7,-20 0,-12 7,-20 22,-30 82,-89 60,-59 79,-59 11,0 21,7 l 115,90 q 34,-18 77,-32 11,-108 23,-154 7,-24 30,-24 h 186 q 11,0 20,7.5 9,7.5 10,17.5 l 23,153 q 34,10 75,31 l 118,-89 q 8,-7 20,-7 11,0 21,8 144,133 144,160 0,8 -7,19 -12,16 -42,54 -30,38 -45,60 23,48 34,82 l 152,23 q 10,2 17,10.5 7,8.5 7,19.5 z m 640,533 v 140 q 0,16 -149,31 -12,27 -30,52 51,113 51,138 0,4 -4,7 -122,71 -124,71 -8,0 -46,-47 -38,-47 -52,-68 -20,2 -30,2 -10,0 -30,-2 -14,21 -52,68 -38,47 -46,47 -2,0 -124,-71 -4,-3 -4,-7 0,-25 51,-138 -18,-25 -30,-52 -149,-15 -149,-31 v -140 q 0,-16 149,-31 13,-29 30,-52 -51,-113 -51,-138 0,-4 4,-7 4,-2 35,-20 31,-18 59,-34 28,-16 30,-16 8,0 46,46.5 38,46.5 52,67.5 20,-2 30,-2 10,0 30,2 51,-71 92,-112 l 6,-2 q 4,0 124,70 4,3 4,7 0,25 -51,138 17,23 30,52 149,15 149,31 z m 0,-1024 v 140 q 0,16 -149,31 -12,27 -30,52 51,113 51,138 0,4 -4,7 -122,71 -124,71 -8,0 -46,-47 -38,-47 -52,-68 -20,2 -30,2 -10,0 -30,-2 -14,21 -52,68 -38,47 -46,47 -2,0 -124,-71 -4,-3 -4,-7 0,-25 51,-138 -18,-25 -30,-52 -149,-15 -149,-31 V 298 q 0,-16 149,-31 13,-29 30,-52 -51,-113 -51,-138 0,-4 4,-7 4,-2 35,-20 31,-18 59,-34 28,-16 30,-16 8,0 46,46.5 38,46.5 52,67.5 20,-2 30,-2 10,0 30,2 51,-71 92,-112 l 6,-2 q 4,0 124,70 4,3 4,7 0,25 -51,138 17,23 30,52 149,15 149,31 z' } ], + [ 'comment-alt', { viewBox: '0 0 1792 1536', path: 'M 896,128 Q 692,128 514.5,197.5 337,267 232.5,385 128,503 128,640 128,752 199.5,853.5 271,955 401,1029 l 87,50 -27,96 q -24,91 -70,172 152,-63 275,-171 l 43,-38 57,6 q 69,8 130,8 204,0 381.5,-69.5 Q 1455,1013 1559.5,895 1664,777 1664,640 1664,503 1559.5,385 1455,267 1277.5,197.5 1100,128 896,128 Z m 896,512 q 0,174 -120,321.5 -120,147.5 -326,233 -206,85.5 -450,85.5 -70,0 -145,-8 -198,175 -460,242 -49,14 -114,22 h -5 q -15,0 -27,-10.5 -12,-10.5 -16,-27.5 v -1 q -3,-4 -0.5,-12 2.5,-8 2,-10 -0.5,-2 4.5,-9.5 l 6,-9 q 0,0 7,-8.5 7,-8.5 8,-9 7,-8 31,-34.5 24,-26.5 34.5,-38 10.5,-11.5 31,-39.5 20.5,-28 32.5,-51 12,-23 27,-59 15,-36 26,-76 Q 181,1052 90.5,921 0,790 0,640 0,466 120,318.5 240,171 446,85.5 652,0 896,0 q 244,0 450,85.5 206,85.5 326,233 120,147.5 120,321.5 z' } ], + [ 'double-angle-left', { viewBox: '0 0 966 998', path: 'm 582,915 q 0,13 -10,23 l -50,50 q -10,10 -23,10 -13,0 -23,-10 L 10,522 Q 0,512 0,499 0,486 10,476 L 476,10 q 10,-10 23,-10 13,0 23,10 l 50,50 q 10,10 10,23 0,13 -10,23 L 179,499 572,892 q 10,10 10,23 z m 384,0 q 0,13 -10,23 l -50,50 q -10,10 -23,10 -13,0 -23,-10 L 394,522 q -10,-10 -10,-23 0,-13 10,-23 L 860,10 q 10,-10 23,-10 13,0 23,10 l 50,50 q 10,10 10,23 0,13 -10,23 L 563,499 956,892 q 10,10 10,23 z' } ], + [ 'double-angle-up', { viewBox: '0 0 998 966', path: 'm 998,883 q 0,13 -10,23 l -50,50 q -10,10 -23,10 -13,0 -23,-10 L 499,563 106,956 Q 96,966 83,966 70,966 60,956 L 10,906 Q 0,896 0,883 0,870 10,860 L 476,394 q 10,-10 23,-10 13,0 23,10 l 466,466 q 10,10 10,23 z m 0,-384 q 0,13 -10,23 l -50,50 q -10,10 -23,10 -13,0 -23,-10 L 499,179 106,572 Q 96,582 83,582 70,582 60,572 L 10,522 Q 0,512 0,499 0,486 10,476 L 476,10 q 10,-10 23,-10 13,0 23,10 l 466,466 q 10,10 10,23 z' } ], + [ 'download-alt', { viewBox: '0 0 1664 1536', path: 'm 1280,1344 q 0,-26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 -19,19 -19,45 0,26 19,45 19,19 45,19 26,0 45,-19 19,-19 19,-45 z m 256,0 q 0,-26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 -19,19 -19,45 0,26 19,45 19,19 45,19 26,0 45,-19 19,-19 19,-45 z m 128,-224 v 320 q 0,40 -28,68 -28,28 -68,28 H 96 q -40,0 -68,-28 -28,-28 -28,-68 v -320 q 0,-40 28,-68 28,-28 68,-28 h 465 l 135,136 q 58,56 136,56 78,0 136,-56 l 136,-136 h 464 q 40,0 68,28 28,28 28,68 z M 1339,551 q 17,41 -14,70 l -448,448 q -18,19 -45,19 -27,0 -45,-19 L 339,621 q -31,-29 -14,-70 17,-39 59,-39 H 640 V 64 Q 640,38 659,19 678,0 704,0 h 256 q 26,0 45,19 19,19 19,45 v 448 h 256 q 42,0 59,39 z' } ], + [ 'eraser', { viewBox: '0 0 1920 1280', path: 'M 896,1152 1232,768 l -768,0 -336,384 768,0 z M 1909,75 q 15,34 9.5,71.5 Q 1913,184 1888,212 L 992,1236 q -38,44 -96,44 l -768,0 q -38,0 -69.5,-20.5 -31.5,-20.5 -47.5,-54.5 -15,-34 -9.5,-71.5 5.5,-37.5 30.5,-65.5 L 928,44 Q 966,0 1024,0 l 768,0 q 38,0 69.5,20.5 Q 1893,41 1909,75 Z' } ], + [ 'exclamation-triangle', { viewBox: '0 0 1794 1664', path: 'm 1025.0139,1375 0,-190 q 0,-14 -9.5,-23.5 -9.5,-9.5 -22.5,-9.5 l -192,0 q -13,0 -22.5,9.5 -9.5,9.5 -9.5,23.5 l 0,190 q 0,14 9.5,23.5 9.5,9.5 22.5,9.5 l 192,0 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-23.5 z m -2,-374 18,-459 q 0,-12 -10,-19 -13,-11 -24,-11 l -220,0 q -11,0 -24,11 -10,7 -10,21 l 17,457 q 0,10 10,16.5 10,6.5 24,6.5 l 185,0 q 14,0 23.5,-6.5 9.5,-6.5 10.5,-16.5 z m -14,-934 768,1408 q 35,63 -2,126 -17,29 -46.5,46 -29.5,17 -63.5,17 l -1536,0 q -34,0 -63.5,-17 -29.5,-17 -46.5,-46 -37,-63 -2,-126 L 785.01389,67 q 17,-31 47,-49 30,-18 65,-18 35,0 65,18 30,18 47,49 z' } ], + [ 'external-link', { viewBox: '0 0 1792 1536', path: 'm 1408,928 0,320 q 0,119 -84.5,203.5 Q 1239,1536 1120,1536 l -832,0 Q 169,1536 84.5,1451.5 0,1367 0,1248 L 0,416 Q 0,297 84.5,212.5 169,128 288,128 l 704,0 q 14,0 23,9 9,9 9,23 l 0,64 q 0,14 -9,23 -9,9 -23,9 l -704,0 q -66,0 -113,47 -47,47 -47,113 l 0,832 q 0,66 47,113 47,47 113,47 l 832,0 q 66,0 113,-47 47,-47 47,-113 l 0,-320 q 0,-14 9,-23 9,-9 23,-9 l 64,0 q 14,0 23,9 9,9 9,23 z m 384,-864 0,512 q 0,26 -19,45 -19,19 -45,19 -26,0 -45,-19 L 1507,445 855,1097 q -10,10 -23,10 -13,0 -23,-10 L 695,983 q -10,-10 -10,-23 0,-13 10,-23 L 1347,285 1171,109 q -19,-19 -19,-45 0,-26 19,-45 19,-19 45,-19 l 512,0 q 26,0 45,19 19,19 19,45 z' } ], + [ 'eye-dropper', { viewBox: '0 0 1792 1792', path: 'm 1698,94 q 94,94 94,226.5 0,132.5 -94,225.5 l -225,223 104,104 q 10,10 10,23 0,13 -10,23 l -210,210 q -10,10 -23,10 -13,0 -23,-10 l -105,-105 -603,603 q -37,37 -90,37 l -203,0 -256,128 -64,-64 128,-256 0,-203 q 0,-53 37,-90 L 768,576 663,471 q -10,-10 -10,-23 0,-13 10,-23 L 873,215 q 10,-10 23,-10 13,0 23,10 L 1023,319 1246,94 Q 1339,0 1471.5,0 1604,0 1698,94 Z M 512,1472 1088,896 896,704 l -576,576 0,192 192,0 z' } ], + [ 'eye-open', { viewBox: '0 0 1792 1152', path: 'm 1664,576 q -152,-236 -381,-353 61,104 61,225 0,185 -131.5,316.5 Q 1081,896 896,896 711,896 579.5,764.5 448,633 448,448 448,327 509,223 280,340 128,576 261,781 461.5,902.5 662,1024 896,1024 1130,1024 1330.5,902.5 1531,781 1664,576 Z M 944,192 q 0,-20 -14,-34 -14,-14 -34,-14 -125,0 -214.5,89.5 Q 592,323 592,448 q 0,20 14,34 14,14 34,14 20,0 34,-14 14,-14 14,-34 0,-86 61,-147 61,-61 147,-61 20,0 34,-14 14,-14 14,-34 z m 848,384 q 0,34 -20,69 -140,230 -376.5,368.5 Q 1159,1152 896,1152 633,1152 396.5,1013 160,874 20,645 0,610 0,576 0,542 20,507 160,278 396.5,139 633,0 896,0 q 263,0 499.5,139 236.5,139 376.5,368 20,35 20,69 z' } ], + [ 'eye-slash', { viewBox: '0 0 1792 1344', path: 'M 555,1047 633,906 Q 546,843 497,747 448,651 448,544 448,423 509,319 280,436 128,672 295,930 555,1047 Z M 944,288 q 0,-20 -14,-34 -14,-14 -34,-14 -125,0 -214.5,89.5 Q 592,419 592,544 q 0,20 14,34 14,14 34,14 20,0 34,-14 14,-14 14,-34 0,-86 61,-147 61,-61 147,-61 20,0 34,-14 14,-14 14,-34 z M 1307,97 q 0,7 -1,9 -106,189 -316,567 -210,378 -315,566 l -49,89 q -10,16 -28,16 -12,0 -134,-70 -16,-10 -16,-28 0,-12 44,-87 Q 349,1094 228.5,986 108,878 20,741 0,710 0,672 0,634 20,603 173,368 400,232 627,96 896,96 q 89,0 180,17 l 54,-97 q 10,-16 28,-16 5,0 18,6 13,6 31,15.5 18,9.5 33,18.5 15,9 31.5,18.5 16.5,9.5 19.5,11.5 16,10 16,27 z m 37,447 q 0,139 -79,253.5 Q 1186,912 1056,962 l 280,-502 q 8,45 8,84 z m 448,128 q 0,35 -20,69 -39,64 -109,145 -150,172 -347.5,267 -197.5,95 -419.5,95 l 74,-132 Q 1182,1098 1362.5,979 1543,860 1664,672 1549,493 1382,378 l 63,-112 q 95,64 182.5,153 87.5,89 144.5,184 20,34 20,69 z' } ], + [ 'files-o', { viewBox: '0 0 1792 1792', path: 'm 1696,384 q 40,0 68,28 28,28 28,68 l 0,1216 q 0,40 -28,68 -28,28 -68,28 l -960,0 q -40,0 -68,-28 -28,-28 -28,-68 l 0,-288 -544,0 Q 56,1408 28,1380 0,1352 0,1312 L 0,640 Q 0,600 20,552 40,504 68,476 L 476,68 Q 504,40 552,20 600,0 640,0 l 416,0 q 40,0 68,28 28,28 28,68 l 0,328 q 68,-40 128,-40 l 416,0 z m -544,213 -299,299 299,0 0,-299 z M 512,213 213,512 l 299,0 0,-299 z m 196,647 316,-316 0,-416 -384,0 0,416 q 0,40 -28,68 -28,28 -68,28 l -416,0 0,640 512,0 0,-256 q 0,-40 20,-88 20,-48 48,-76 z m 956,804 0,-1152 -384,0 0,416 q 0,40 -28,68 -28,28 -68,28 l -416,0 0,640 896,0 z' } ], + [ 'film', { viewBox: '0 0 1920 1664', path: 'm 384,1472 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 0,-384 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 0,-384 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 1024,768 0,-512 q 0,-26 -19,-45 -19,-19 -45,-19 l -768,0 q -26,0 -45,19 -19,19 -19,45 l 0,512 q 0,26 19,45 19,19 45,19 l 768,0 q 26,0 45,-19 19,-19 19,-45 z M 384,320 384,192 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 1408,1152 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m -384,-768 0,-512 q 0,-26 -19,-45 -19,-19 -45,-19 l -768,0 q -26,0 -45,19 -19,19 -19,45 l 0,512 q 0,26 19,45 19,19 45,19 l 768,0 q 26,0 45,-19 19,-19 19,-45 z m 384,384 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 0,-384 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 0,-384 0,-128 q 0,-26 -19,-45 -19,-19 -45,-19 l -128,0 q -26,0 -45,19 -19,19 -19,45 l 0,128 q 0,26 19,45 19,19 45,19 l 128,0 q 26,0 45,-19 19,-19 19,-45 z m 128,-160 0,1344 q 0,66 -47,113 -47,47 -113,47 l -1600,0 Q 94,1664 47,1617 0,1570 0,1504 L 0,160 Q 0,94 47,47 94,0 160,0 l 1600,0 q 66,0 113,47 47,47 47,113 z' } ], + [ 'filter', { viewBox: '0 0 1410 1408', path: 'm 1404.0208,39 q 17,41 -14,70 l -493,493 0,742 q 0,42 -39,59 -13,5 -25,5 -27,0 -45,-19 l -256,-256 q -19,-19 -19,-45 l 0,-486 L 20.020833,109 q -31,-29 -14,-70 Q 23.020833,0 65.020833,0 L 1345.0208,0 q 42,0 59,39 z' } ], + [ 'floppy-o', { viewBox: '0 0 1536 1536', path: 'm 384,1408 768,0 0,-384 -768,0 0,384 z m 896,0 128,0 0,-896 q 0,-14 -10,-38.5 Q 1388,449 1378,439 L 1097,158 q -10,-10 -34,-20 -24,-10 -39,-10 l 0,416 q 0,40 -28,68 -28,28 -68,28 l -576,0 q -40,0 -68,-28 -28,-28 -28,-68 l 0,-416 -128,0 0,1280 128,0 0,-416 q 0,-40 28,-68 28,-28 68,-28 l 832,0 q 40,0 68,28 28,28 28,68 l 0,416 z M 896,480 896,160 q 0,-13 -9.5,-22.5 Q 877,128 864,128 l -192,0 q -13,0 -22.5,9.5 Q 640,147 640,160 l 0,320 q 0,13 9.5,22.5 9.5,9.5 22.5,9.5 l 192,0 q 13,0 22.5,-9.5 Q 896,493 896,480 Z m 640,32 0,928 q 0,40 -28,68 -28,28 -68,28 L 96,1536 Q 56,1536 28,1508 0,1480 0,1440 L 0,96 Q 0,56 28,28 56,0 96,0 l 928,0 q 40,0 88,20 48,20 76,48 l 280,280 q 28,28 48,76 20,48 20,88 z' } ], + [ 'font', { viewBox: '0 0 1664 1536', path: 'M 725,431 555,881 q 33,0 136.5,2 103.5,2 160.5,2 19,0 57,-2 Q 822,630 725,431 Z M 0,1536 2,1457 q 23,-7 56,-12.5 33,-5.5 57,-10.5 24,-5 49.5,-14.5 25.5,-9.5 44.5,-29 19,-19.5 31,-50.5 L 477,724 757,0 l 75,0 53,0 q 8,14 11,21 l 205,480 q 33,78 106,257.5 73,179.5 114,274.5 15,34 58,144.5 43,110.5 72,168.5 20,45 35,57 19,15 88,29.5 69,14.5 84,20.5 6,38 6,57 0,5 -0.5,13.5 -0.5,8.5 -0.5,12.5 -63,0 -190,-8 -127,-8 -191,-8 -76,0 -215,7 -139,7 -178,8 0,-43 4,-78 l 131,-28 q 1,0 12.5,-2.5 11.5,-2.5 15.5,-3.5 4,-1 14.5,-4.5 10.5,-3.5 15,-6.5 4.5,-3 11,-8 6.5,-5 9,-11 2.5,-6 2.5,-14 0,-16 -31,-96.5 -31,-80.5 -72,-177.5 -41,-97 -42,-100 l -450,-2 q -26,58 -76.5,195.5 Q 382,1336 382,1361 q 0,22 14,37.5 14,15.5 43.5,24.5 29.5,9 48.5,13.5 19,4.5 57,8.5 38,4 41,4 1,19 1,58 0,9 -2,27 -58,0 -174.5,-10 -116.5,-10 -174.5,-10 -8,0 -26.5,4 -18.5,4 -21.5,4 -80,14 -188,14 z' } ], + [ 'home', { viewBox: '0 0 1612 1283', path: 'm 1382.1111,739 v 480 q 0,26 -19,45 -19,19 -45,19 H 934.11111 V 899 h -256 v 384 h -384 q -26,0 -45,-19 -19,-19 -19,-45 V 739 q 0,-1 0.5,-3 0.5,-2 0.5,-3 l 575,-474 574.99999,474 q 1,2 1,6 z m 223,-69 -62,74 q -8,9 -21,11 h -3 q -13,0 -21,-7 l -691.99999,-577 -692,577 q -12,8 -23.999999,7 -13,-2 -21,-11 L 7.1111111,670 Q -0.88888889,660 0.11111111,646.5 1.1111111,633 11.111111,625 L 730.11111,26 q 32,-26 76,-26 44,0 76,26 L 1126.1111,230 V 35 q 0,-14 9,-23 9,-9 23,-9 h 192 q 14,0 23,9 9,9 9,23 v 408 l 219,182 q 10,8 11,21.5 1,13.5 -7,23.5 z' } ], + [ 'info-circle', { viewBox: '0 0 1536 1536', path: 'm 1024,1248 0,-160 q 0,-14 -9,-23 -9,-9 -23,-9 l -96,0 0,-512 q 0,-14 -9,-23 -9,-9 -23,-9 l -320,0 q -14,0 -23,9 -9,9 -9,23 l 0,160 q 0,14 9,23 9,9 23,9 l 96,0 0,320 -96,0 q -14,0 -23,9 -9,9 -9,23 l 0,160 q 0,14 9,23 9,9 23,9 l 448,0 q 14,0 23,-9 9,-9 9,-23 z M 896,352 896,192 q 0,-14 -9,-23 -9,-9 -23,-9 l -192,0 q -14,0 -23,9 -9,9 -9,23 l 0,160 q 0,14 9,23 9,9 23,9 l 192,0 q 14,0 23,-9 9,-9 9,-23 z m 640,416 q 0,209 -103,385.5 Q 1330,1330 1153.5,1433 977,1536 768,1536 559,1536 382.5,1433 206,1330 103,1153.5 0,977 0,768 0,559 103,382.5 206,206 382.5,103 559,0 768,0 977,0 1153.5,103 1330,206 1433,382.5 1536,559 1536,768 Z' } ], + [ 'list-alt', { viewBox: '0 0 1792 1408', path: 'm 384,1056 0,64 q 0,13 -9.5,22.5 -9.5,9.5 -22.5,9.5 l -64,0 q -13,0 -22.5,-9.5 Q 256,1133 256,1120 l 0,-64 q 0,-13 9.5,-22.5 9.5,-9.5 22.5,-9.5 l 64,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 0,-256 0,64 q 0,13 -9.5,22.5 Q 365,896 352,896 l -64,0 q -13,0 -22.5,-9.5 Q 256,877 256,864 l 0,-64 q 0,-13 9.5,-22.5 Q 275,768 288,768 l 64,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 0,-256 0,64 q 0,13 -9.5,22.5 Q 365,640 352,640 l -64,0 q -13,0 -22.5,-9.5 Q 256,621 256,608 l 0,-64 q 0,-13 9.5,-22.5 Q 275,512 288,512 l 64,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 1152,512 0,64 q 0,13 -9.5,22.5 -9.5,9.5 -22.5,9.5 l -960,0 q -13,0 -22.5,-9.5 Q 512,1133 512,1120 l 0,-64 q 0,-13 9.5,-22.5 9.5,-9.5 22.5,-9.5 l 960,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 0,-256 0,64 q 0,13 -9.5,22.5 -9.5,9.5 -22.5,9.5 l -960,0 q -13,0 -22.5,-9.5 Q 512,877 512,864 l 0,-64 q 0,-13 9.5,-22.5 Q 531,768 544,768 l 960,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 0,-256 0,64 q 0,13 -9.5,22.5 -9.5,9.5 -22.5,9.5 l -960,0 q -13,0 -22.5,-9.5 Q 512,621 512,608 l 0,-64 q 0,-13 9.5,-22.5 Q 531,512 544,512 l 960,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 128,704 0,-832 q 0,-13 -9.5,-22.5 Q 1645,384 1632,384 l -1472,0 q -13,0 -22.5,9.5 Q 128,403 128,416 l 0,832 q 0,13 9.5,22.5 9.5,9.5 22.5,9.5 l 1472,0 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-22.5 z m 128,-1088 0,1088 q 0,66 -47,113 -47,47 -113,47 l -1472,0 Q 94,1408 47,1361 0,1314 0,1248 L 0,160 Q 0,94 47,47 94,0 160,0 l 1472,0 q 66,0 113,47 47,47 47,113 z' } ], + [ 'lock', { viewBox: '0 0 1152 1408', path: 'm 320,640 512,0 0,-192 q 0,-106 -75,-181 -75,-75 -181,-75 -106,0 -181,75 -75,75 -75,181 l 0,192 z m 832,96 0,576 q 0,40 -28,68 -28,28 -68,28 l -960,0 Q 56,1408 28,1380 0,1352 0,1312 L 0,736 q 0,-40 28,-68 28,-28 68,-28 l 32,0 0,-192 Q 128,264 260,132 392,0 576,0 q 184,0 316,132 132,132 132,316 l 0,192 32,0 q 40,0 68,28 28,28 28,68 z' } ], + [ 'magic', { viewBox: '0 0 1637 1637', path: 'M 1163,581 1456,288 1349,181 1056,474 Z m 447,-293 q 0,27 -18,45 L 306,1619 q -18,18 -45,18 -27,0 -45,-18 L 18,1421 Q 0,1403 0,1376 0,1349 18,1331 L 1304,45 q 18,-18 45,-18 27,0 45,18 l 198,198 q 18,18 18,45 z M 259,98 l 98,30 -98,30 -30,98 -30,-98 -98,-30 98,-30 30,-98 z M 609,260 805,320 609,380 549,576 489,380 293,320 489,260 549,64 Z m 930,478 98,30 -98,30 -30,98 -30,-98 -98,-30 98,-30 30,-98 z M 899,98 l 98,30 -98,30 -30,98 -30,-98 -98,-30 98,-30 30,-98 z' } ], + [ 'pause-circle-o', { viewBox: '0 0 1536 1536', path: 'M 768,0 Q 977,0 1153.5,103 1330,206 1433,382.5 1536,559 1536,768 1536,977 1433,1153.5 1330,1330 1153.5,1433 977,1536 768,1536 559,1536 382.5,1433 206,1330 103,1153.5 0,977 0,768 0,559 103,382.5 206,206 382.5,103 559,0 768,0 Z m 0,1312 q 148,0 273,-73 125,-73 198,-198 73,-125 73,-273 0,-148 -73,-273 -73,-125 -198,-198 -125,-73 -273,-73 -148,0 -273,73 -125,73 -198,198 -73,125 -73,273 0,148 73,273 73,125 198,198 125,73 273,73 z m 96,-224 q -14,0 -23,-9 -9,-9 -9,-23 l 0,-576 q 0,-14 9,-23 9,-9 23,-9 l 192,0 q 14,0 23,9 9,9 9,23 l 0,576 q 0,14 -9,23 -9,9 -23,9 l -192,0 z m -384,0 q -14,0 -23,-9 -9,-9 -9,-23 l 0,-576 q 0,-14 9,-23 9,-9 23,-9 l 192,0 q 14,0 23,9 9,9 9,23 l 0,576 q 0,14 -9,23 -9,9 -23,9 l -192,0 z' } ], + [ 'play-circle-o', { viewBox: '0 0 1536 1536', path: 'm 1184,768 q 0,37 -32,55 l -544,320 q -15,9 -32,9 -16,0 -32,-8 -32,-19 -32,-56 l 0,-640 q 0,-37 32,-56 33,-18 64,1 l 544,320 q 32,18 32,55 z m 128,0 q 0,-148 -73,-273 -73,-125 -198,-198 -125,-73 -273,-73 -148,0 -273,73 -125,73 -198,198 -73,125 -73,273 0,148 73,273 73,125 198,198 125,73 273,73 148,0 273,-73 125,-73 198,-198 73,-125 73,-273 z m 224,0 q 0,209 -103,385.5 Q 1330,1330 1153.5,1433 977,1536 768,1536 559,1536 382.5,1433 206,1330 103,1153.5 0,977 0,768 0,559 103,382.5 206,206 382.5,103 559,0 768,0 977,0 1153.5,103 1330,206 1433,382.5 1536,559 1536,768 Z' } ], + [ 'plus', { viewBox: '0 0 1408 1408', path: 'm 1408,608 0,192 q 0,40 -28,68 -28,28 -68,28 l -416,0 0,416 q 0,40 -28,68 -28,28 -68,28 l -192,0 q -40,0 -68,-28 -28,-28 -28,-68 l 0,-416 -416,0 Q 56,896 28,868 0,840 0,800 L 0,608 q 0,-40 28,-68 28,-28 68,-28 l 416,0 0,-416 Q 512,56 540,28 568,0 608,0 l 192,0 q 40,0 68,28 28,28 28,68 l 0,416 416,0 q 40,0 68,28 28,28 28,68 z' } ], + [ 'power-off', { viewBox: '0 0 1536 1664', path: 'm 1536,896 q 0,156 -61,298 -61,142 -164,245 -103,103 -245,164 -142,61 -298,61 -156,0 -298,-61 Q 328,1542 225,1439 122,1336 61,1194 0,1052 0,896 0,714 80.5,553 161,392 307,283 q 43,-32 95.5,-25 52.5,7 83.5,50 32,42 24.5,94.5 Q 503,455 461,487 363,561 309.5,668 256,775 256,896 q 0,104 40.5,198.5 40.5,94.5 109.5,163.5 69,69 163.5,109.5 94.5,40.5 198.5,40.5 104,0 198.5,-40.5 Q 1061,1327 1130,1258 1199,1189 1239.5,1094.5 1280,1000 1280,896 1280,775 1226.5,668 1173,561 1075,487 1033,455 1025.5,402.5 1018,350 1050,308 q 31,-43 84,-50 53,-7 95,25 146,109 226.5,270 80.5,161 80.5,343 z m -640,-768 0,640 q 0,52 -38,90 -38,38 -90,38 -52,0 -90,-38 -38,-38 -38,-90 l 0,-640 q 0,-52 38,-90 38,-38 90,-38 52,0 90,38 38,38 38,90 z' } ], + [ 'question-circle', { viewBox: '0 0 1536 1536', path: 'm 896,1248 v -192 q 0,-14 -9,-23 -9,-9 -23,-9 H 672 q -14,0 -23,9 -9,9 -9,23 v 192 q 0,14 9,23 9,9 23,9 h 192 q 14,0 23,-9 9,-9 9,-23 z m 256,-672 q 0,-88 -55.5,-163 Q 1041,338 958,297 875,256 788,256 q -243,0 -371,213 -15,24 8,42 l 132,100 q 7,6 19,6 16,0 25,-12 53,-68 86,-92 34,-24 86,-24 48,0 85.5,26 37.5,26 37.5,59 0,38 -20,61 -20,23 -68,45 -63,28 -115.5,86.5 Q 640,825 640,892 v 36 q 0,14 9,23 9,9 23,9 h 192 q 14,0 23,-9 9,-9 9,-23 0,-19 21.5,-49.5 Q 939,848 972,829 q 32,-18 49,-28.5 17,-10.5 46,-35 29,-24.5 44.5,-48 15.5,-23.5 28,-60.5 12.5,-37 12.5,-81 z m 384,192 q 0,209 -103,385.5 Q 1330,1330 1153.5,1433 977,1536 768,1536 559,1536 382.5,1433 206,1330 103,1153.5 0,977 0,768 0,559 103,382.5 206,206 382.5,103 559,0 768,0 977,0 1153.5,103 1330,206 1433,382.5 1536,559 1536,768 Z' } ], + [ 'refresh', { viewBox: '0 0 1536 1536', path: 'm 1511,928 q 0,5 -1,7 -64,268 -268,434.5 Q 1038,1536 764,1536 618,1536 481.5,1481 345,1426 238,1324 l -129,129 q -19,19 -45,19 -26,0 -45,-19 Q 0,1434 0,1408 L 0,960 q 0,-26 19,-45 19,-19 45,-19 l 448,0 q 26,0 45,19 19,19 19,45 0,26 -19,45 l -137,137 q 71,66 161,102 90,36 187,36 134,0 250,-65 116,-65 186,-179 11,-17 53,-117 8,-23 30,-23 l 192,0 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 25,-800 0,448 q 0,26 -19,45 -19,19 -45,19 l -448,0 q -26,0 -45,-19 -19,-19 -19,-45 0,-26 19,-45 L 1117,393 Q 969,256 768,256 q -134,0 -250,65 -116,65 -186,179 -11,17 -53,117 -8,23 -30,23 L 50,640 Q 37,640 27.5,630.5 18,621 18,608 l 0,-7 Q 83,333 288,166.5 493,0 768,0 914,0 1052,55.5 1190,111 1297,212 L 1427,83 q 19,-19 45,-19 26,0 45,19 19,19 19,45 z' } ], + [ 'save', { viewBox: '0 0 1536 1536', path: 'm 384,1408 h 768 V 1024 H 384 Z m 896,0 h 128 V 512 q 0,-14 -10,-38.5 Q 1388,449 1378,439 L 1097,158 q -10,-10 -34,-20 -24,-10 -39,-10 v 416 q 0,40 -28,68 -28,28 -68,28 H 352 q -40,0 -68,-28 -28,-28 -28,-68 V 128 H 128 V 1408 H 256 V 992 q 0,-40 28,-68 28,-28 68,-28 h 832 q 40,0 68,28 28,28 28,68 z M 896,480 V 160 q 0,-13 -9.5,-22.5 Q 877,128 864,128 H 672 q -13,0 -22.5,9.5 Q 640,147 640,160 v 320 q 0,13 9.5,22.5 9.5,9.5 22.5,9.5 h 192 q 13,0 22.5,-9.5 Q 896,493 896,480 Z m 640,32 v 928 q 0,40 -28,68 -28,28 -68,28 H 96 Q 56,1536 28,1508 0,1480 0,1440 V 96 Q 0,56 28,28 56,0 96,0 h 928 q 40,0 88,20 48,20 76,48 l 280,280 q 28,28 48,76 20,48 20,88 z' } ], + [ 'search', { viewBox: '0 0 1664 1664', path: 'M 1152,704 Q 1152,519 1020.5,387.5 889,256 704,256 519,256 387.5,387.5 256,519 256,704 256,889 387.5,1020.5 519,1152 704,1152 889,1152 1020.5,1020.5 1152,889 1152,704 Z m 512,832 q 0,52 -38,90 -38,38 -90,38 -54,0 -90,-38 L 1103,1284 Q 924,1408 704,1408 561,1408 430.5,1352.5 300,1297 205.5,1202.5 111,1108 55.5,977.5 0,847 0,704 0,561 55.5,430.5 111,300 205.5,205.5 300,111 430.5,55.5 561,0 704,0 q 143,0 273.5,55.5 130.5,55.5 225,150 94.5,94.5 150,225 55.5,130.5 55.5,273.5 0,220 -124,399 l 343,343 q 37,37 37,90 z' } ], + [ 'sliders', { viewBox: '0 0 1536 1408', path: 'm 352,1152 0,128 -352,0 0,-128 352,0 z m 352,-128 q 26,0 45,19 19,19 19,45 l 0,256 q 0,26 -19,45 -19,19 -45,19 l -256,0 q -26,0 -45,-19 -19,-19 -19,-45 l 0,-256 q 0,-26 19,-45 19,-19 45,-19 l 256,0 z m 160,-384 0,128 -864,0 0,-128 864,0 z m -640,-512 0,128 -224,0 0,-128 224,0 z m 1312,1024 0,128 -736,0 0,-128 736,0 z M 576,0 q 26,0 45,19 19,19 19,45 l 0,256 q 0,26 -19,45 -19,19 -45,19 l -256,0 q -26,0 -45,-19 -19,-19 -19,-45 L 256,64 Q 256,38 275,19 294,0 320,0 l 256,0 z m 640,512 q 26,0 45,19 19,19 19,45 l 0,256 q 0,26 -19,45 -19,19 -45,19 l -256,0 q -26,0 -45,-19 -19,-19 -19,-45 l 0,-256 q 0,-26 19,-45 19,-19 45,-19 l 256,0 z m 320,128 0,128 -224,0 0,-128 224,0 z m 0,-512 0,128 -864,0 0,-128 864,0 z' } ], + [ 'spinner', { viewBox: '0 0 1664 1728', path: 'm 462,1394 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -52,0 -90,-38 -38,-38 -38,-90 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 37.5,37.5 37.5,90.5 z m 498,206 q 0,53 -37.5,90.5 Q 885,1728 832,1728 779,1728 741.5,1690.5 704,1653 704,1600 q 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 Q 960,1547 960,1600 Z M 256,896 q 0,53 -37.5,90.5 Q 181,1024 128,1024 75,1024 37.5,986.5 0,949 0,896 0,843 37.5,805.5 75,768 128,768 q 53,0 90.5,37.5 Q 256,843 256,896 Z m 1202,498 q 0,52 -38,90 -38,38 -90,38 -53,0 -90.5,-37.5 -37.5,-37.5 -37.5,-90.5 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 37.5,37.5 37.5,90.5 z M 494,398 q 0,66 -47,113 -47,47 -113,47 -66,0 -113,-47 -47,-47 -47,-113 0,-66 47,-113 47,-47 113,-47 66,0 113,47 47,47 47,113 z m 1170,498 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -53,0 -90.5,-37.5 Q 1408,949 1408,896 q 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 Q 1664,843 1664,896 Z M 1024,192 q 0,80 -56,136 -56,56 -136,56 -80,0 -136,-56 -56,-56 -56,-136 0,-80 56,-136 56,-56 136,-56 80,0 136,56 56,56 56,136 z m 530,206 q 0,93 -66,158.5 -66,65.5 -158,65.5 -93,0 -158.5,-65.5 Q 1106,491 1106,398 q 0,-92 65.5,-158 65.5,-66 158.5,-66 92,0 158,66 66,66 66,158 z' } ], + [ 'sun', { viewBox: '0 0 1708 1792', path: 'm 1706,1172.5 c -3,10 -11,17 -20,20 l -292,96 v 306 c 0,10 -5,20 -13,26 -9,6 -19,8 -29,4 l -292,-94 -180,248 c -6,8 -16,13 -26,13 -10,0 -20,-5 -26,-13 l -180,-248 -292,94 c -10,4 -20,2 -29,-4 -8,-6 -13,-16 -13,-26 v -306 l -292,-96 c -9,-3 -17,-10 -20,-20 -3,-10 -2,-21 4,-29 l 180,-248 -180,-248 c -6,-9 -7,-19 -4,-29 3,-10 11,-17 20,-20 l 292,-96 v -306 c 0,-10 5,-20 13,-26 9,-6 19,-8 29,-4 l 292,94 180,-248 c 12,-16 40,-16 52,0 L 1060,260.5 l 292,-94 c 10,-4 20,-2 29,4 8,6 13,16 13,26 v 306 l 292,96 c 9,3 17,10 20,20 3,10 2,20 -4,29 l -180,248 180,248 c 6,8 7,19 4,29 z' } ], + [ 'sun-o', { viewBox: '0 0 1708 1792', path: 'm 1430,895.5 c 0,-318 -258,-576 -576,-576 -318,0 -576,258 -576,576 0,318 258,576 576,576 C 1172,1471.5 1430,1213.5 1430,895.5 Z m 276,277 c -3,10 -11,17 -20,20 l -292,96 v 306 c 0,10 -5,20 -13,26 -9,6 -19,8 -29,4 l -292,-94 -180,248 c -6,8 -16,13 -26,13 -10,0 -20,-5 -26,-13 l -180,-248 -292,94 c -10,4 -20,2 -29,-4 -8,-6 -13,-16 -13,-26 v -306 l -292,-96 c -9,-3 -17,-10 -20,-20 -3,-10 -2,-21 4,-29 l 180,-248 -180,-248 c -6,-9 -7,-19 -4,-29 3,-10 11,-17 20,-20 l 292,-96 v -306 c 0,-10 5,-20 13,-26 9,-6 19,-8 29,-4 l 292,94 180,-248 c 12,-16 40,-16 52,0 L 1060,260.5 l 292,-94 c 10,-4 20,-2 29,4 8,6 13,16 13,26 v 306 l 292,96 c 9,3 17,10 20,20 3,10 2,20 -4,29 l -180,248 180,248 c 6,8 7,19 4,29 z' } ], + [ 'times', { viewBox: '0 0 1188 1188', path: 'm 1188,956 q 0,40 -28,68 l -136,136 q -28,28 -68,28 -40,0 -68,-28 L 594,866 300,1160 q -28,28 -68,28 -40,0 -68,-28 L 28,1024 Q 0,996 0,956 0,916 28,888 L 322,594 28,300 Q 0,272 0,232 0,192 28,164 L 164,28 Q 192,0 232,0 272,0 300,28 L 594,322 888,28 q 28,-28 68,-28 40,0 68,28 l 136,136 q 28,28 28,68 0,40 -28,68 l -294,294 294,294 q 28,28 28,68 z' } ], + [ 'trash-o', { viewBox: '0 0 1408 1536', path: 'm 512,608 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 256,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 256,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 128,724 V 384 H 256 v 948 q 0,22 7,40.5 7,18.5 14.5,27 7.5,8.5 10.5,8.5 h 832 q 3,0 10.5,-8.5 7.5,-8.5 14.5,-27 7,-18.5 7,-40.5 z M 480,256 H 928 L 880,139 q -7,-9 -17,-11 H 546 q -10,2 -17,11 z m 928,32 v 64 q 0,14 -9,23 -9,9 -23,9 h -96 v 948 q 0,83 -47,143.5 -47,60.5 -113,60.5 H 288 q -66,0 -113,-58.5 Q 128,1419 128,1336 V 384 H 32 Q 18,384 9,375 0,366 0,352 v -64 q 0,-14 9,-23 9,-9 23,-9 H 341 L 411,89 Q 426,52 465,26 504,0 544,0 h 320 q 40,0 79,26 39,26 54,63 l 70,167 h 309 q 14,0 23,9 9,9 9,23 z' } ], + [ 'undo', { viewBox: '0 0 1536 1536', path: 'm 1536,768 q 0,156 -61,298 -61,142 -164,245 -103,103 -245,164 -142,61 -298,61 -172,0 -327,-72.5 Q 286,1391 177,1259 q -7,-10 -6.5,-22.5 0.5,-12.5 8.5,-20.5 l 137,-138 q 10,-9 25,-9 16,2 23,12 73,95 179,147 106,52 225,52 104,0 198.5,-40.5 Q 1061,1199 1130,1130 1199,1061 1239.5,966.5 1280,872 1280,768 1280,664 1239.5,569.5 1199,475 1130,406 1061,337 966.5,296.5 872,256 768,256 670,256 580,291.5 490,327 420,393 l 137,138 q 31,30 14,69 -17,40 -59,40 H 64 Q 38,640 19,621 0,602 0,576 V 128 Q 0,86 40,69 79,52 109,83 L 239,212 Q 346,111 483.5,55.5 621,0 768,0 q 156,0 298,61 142,61 245,164 103,103 164,245 61,142 61,298 z' } ], + [ 'unlink', { viewBox: '0 0 1664 1664', path: 'm 439,1271 -256,256 q -11,9 -23,9 -12,0 -23,-9 -9,-10 -9,-23 0,-13 9,-23 l 256,-256 q 10,-9 23,-9 13,0 23,9 9,10 9,23 0,13 -9,23 z m 169,41 v 320 q 0,14 -9,23 -9,9 -23,9 -14,0 -23,-9 -9,-9 -9,-23 v -320 q 0,-14 9,-23 9,-9 23,-9 14,0 23,9 9,9 9,23 z M 384,1088 q 0,14 -9,23 -9,9 -23,9 H 32 q -14,0 -23,-9 -9,-9 -9,-23 0,-14 9,-23 9,-9 23,-9 h 320 q 14,0 23,9 9,9 9,23 z m 1264,128 q 0,120 -85,203 l -147,146 q -83,83 -203,83 -121,0 -204,-85 L 675,1228 q -21,-21 -42,-56 l 239,-18 273,274 q 27,27 68,27.5 41,0.5 68,-26.5 l 147,-146 q 28,-28 28,-67 0,-40 -28,-68 l -274,-275 18,-239 q 35,21 56,42 l 336,336 q 84,86 84,204 z M 1031,492 792,510 519,236 q -28,-28 -68,-28 -39,0 -68,27 L 236,381 q -28,28 -28,67 0,40 28,68 l 274,274 -18,240 q -35,-21 -56,-42 L 100,652 Q 16,566 16,448 16,328 101,245 L 248,99 q 83,-83 203,-83 121,0 204,85 l 334,335 q 21,21 42,56 z m 633,84 q 0,14 -9,23 -9,9 -23,9 h -320 q -14,0 -23,-9 -9,-9 -9,-23 0,-14 9,-23 9,-9 23,-9 h 320 q 14,0 23,9 9,9 9,23 z M 1120,32 v 320 q 0,14 -9,23 -9,9 -23,9 -14,0 -23,-9 -9,-9 -9,-23 V 32 q 0,-14 9,-23 9,-9 23,-9 14,0 23,9 9,9 9,23 z m 407,151 -256,256 q -11,9 -23,9 -12,0 -23,-9 -9,-10 -9,-23 0,-13 9,-23 l 256,-256 q 10,-9 23,-9 13,0 23,9 9,10 9,23 0,13 -9,23 z' } ], + [ 'unlock-alt', { viewBox: '0 0 1152 1536', path: 'm 1056,768 q 40,0 68,28 28,28 28,68 v 576 q 0,40 -28,68 -28,28 -68,28 H 96 Q 56,1536 28,1508 0,1480 0,1440 V 864 q 0,-40 28,-68 28,-28 68,-28 h 32 V 448 Q 128,263 259.5,131.5 391,0 576,0 761,0 892.5,131.5 1024,263 1024,448 q 0,26 -19,45 -19,19 -45,19 h -64 q -26,0 -45,-19 -19,-19 -19,-45 0,-106 -75,-181 -75,-75 -181,-75 -106,0 -181,75 -75,75 -75,181 v 320 z' } ], + [ 'upload-alt', { viewBox: '0 0 1664 1600', path: 'm 1280,1408 q 0,-26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 -19,19 -19,45 0,26 19,45 19,19 45,19 26,0 45,-19 19,-19 19,-45 z m 256,0 q 0,-26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 -19,19 -19,45 0,26 19,45 19,19 45,19 26,0 45,-19 19,-19 19,-45 z m 128,-224 v 320 q 0,40 -28,68 -28,28 -68,28 H 96 q -40,0 -68,-28 -28,-28 -28,-68 v -320 q 0,-40 28,-68 28,-28 68,-28 h 427 q 21,56 70.5,92 49.5,36 110.5,36 h 256 q 61,0 110.5,-36 49.5,-36 70.5,-92 h 427 q 40,0 68,28 28,28 28,68 z M 1339,536 q -17,40 -59,40 h -256 v 448 q 0,26 -19,45 -19,19 -45,19 H 704 q -26,0 -45,-19 -19,-19 -19,-45 V 576 H 384 q -42,0 -59,-40 -17,-39 14,-69 L 787,19 q 18,-19 45,-19 27,0 45,19 l 448,448 q 31,30 14,69 z' } ], + [ 'zoom-in', { viewBox: '0 0 1664 1664', path: 'm 1024,672 v 64 q 0,13 -9.5,22.5 Q 1005,768 992,768 H 768 v 224 q 0,13 -9.5,22.5 -9.5,9.5 -22.5,9.5 h -64 q -13,0 -22.5,-9.5 Q 640,1005 640,992 V 768 H 416 q -13,0 -22.5,-9.5 Q 384,749 384,736 v -64 q 0,-13 9.5,-22.5 Q 403,640 416,640 H 640 V 416 q 0,-13 9.5,-22.5 Q 659,384 672,384 h 64 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 v 224 h 224 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 128,32 Q 1152,519 1020.5,387.5 889,256 704,256 519,256 387.5,387.5 256,519 256,704 256,889 387.5,1020.5 519,1152 704,1152 889,1152 1020.5,1020.5 1152,889 1152,704 Z m 512,832 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -54,0 -90,-38 L 1103,1284 Q 924,1408 704,1408 561,1408 430.5,1352.5 300,1297 205.5,1202.5 111,1108 55.5,977.5 0,847 0,704 0,561 55.5,430.5 111,300 205.5,205.5 300,111 430.5,55.5 561,0 704,0 q 143,0 273.5,55.5 130.5,55.5 225,150 94.5,94.5 150,225 55.5,130.5 55.5,273.5 0,220 -124,399 l 343,343 q 37,37 37,90 z' } ], + [ 'zoom-out', { viewBox: '0 0 1664 1664', path: 'm 1024,672 v 64 q 0,13 -9.5,22.5 Q 1005,768 992,768 H 416 q -13,0 -22.5,-9.5 Q 384,749 384,736 v -64 q 0,-13 9.5,-22.5 Q 403,640 416,640 h 576 q 13,0 22.5,9.5 9.5,9.5 9.5,22.5 z m 128,32 Q 1152,519 1020.5,387.5 889,256 704,256 519,256 387.5,387.5 256,519 256,704 256,889 387.5,1020.5 519,1152 704,1152 889,1152 1020.5,1020.5 1152,889 1152,704 Z m 512,832 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -54,0 -90,-38 L 1103,1284 Q 924,1408 704,1408 561,1408 430.5,1352.5 300,1297 205.5,1202.5 111,1108 55.5,977.5 0,847 0,704 0,561 55.5,430.5 111,300 205.5,205.5 300,111 430.5,55.5 561,0 704,0 q 143,0 273.5,55.5 130.5,55.5 225,150 94.5,94.5 150,225 55.5,130.5 55.5,273.5 0,220 -124,399 l 343,343 q 37,37 37,90 z' } ], + // See /img/photon.svg + [ 'ph-popups', { viewBox: '0 0 20 20', path: 'm 3.146,1.8546316 a 0.5006316,0.5006316 0 0 0 0.708,-0.708 l -1,-1 a 0.5006316,0.5006316 0 0 0 -0.708,0.708 z m -0.836,2.106 a 0.406,0.406 0 0 0 0.19,0.04 0.5,0.5 0 0 0 0.35,-0.851 0.493,0.493 0 0 0 -0.54,-0.109 0.361,0.361 0 0 0 -0.16,0.109 0.485,0.485 0 0 0 0,0.7 0.372,0.372 0 0 0 0.16,0.111 z m 3,-3 a 0.406,0.406 0 0 0 0.19,0.04 0.513,0.513 0 0 0 0.5,-0.5 0.473,0.473 0 0 0 -0.15,-0.351 0.5,0.5 0 0 0 -0.7,0 0.485,0.485 0 0 0 0,0.7 0.372,0.372 0 0 0 0.16,0.111 z m 13.19,1.04 a 0.5,0.5 0 0 0 0.354,-0.146 l 1,-1 a 0.5006316,0.5006316 0 0 0 -0.708,-0.708 l -1,1 a 0.5,0.5 0 0 0 0.354,0.854 z m 1.35,1.149 a 0.361,0.361 0 0 0 -0.16,-0.109 0.5,0.5 0 0 0 -0.38,0 0.361,0.361 0 0 0 -0.16,0.109 0.485,0.485 0 0 0 0,0.7 0.372,0.372 0 0 0 0.16,0.11 0.471,0.471 0 0 0 0.38,0 0.372,0.372 0 0 0 0.16,-0.11 0.469,0.469 0 0 0 0.15,-0.349 0.43,0.43 0 0 0 -0.04,-0.19 0.358,0.358 0 0 0 -0.11,-0.161 z m -3.54,-2.189 a 0.406,0.406 0 0 0 0.19,0.04 0.469,0.469 0 0 0 0.35,-0.15 0.353,0.353 0 0 0 0.11,-0.161 0.469,0.469 0 0 0 0,-0.379 0.358,0.358 0 0 0 -0.11,-0.161 0.361,0.361 0 0 0 -0.16,-0.109 0.493,0.493 0 0 0 -0.54,0.109 0.358,0.358 0 0 0 -0.11,0.161 0.43,0.43 0 0 0 -0.04,0.19 0.469,0.469 0 0 0 0.15,0.35 0.372,0.372 0 0 0 0.16,0.11 z m 2.544,15.1860004 a 0.5006316,0.5006316 0 0 0 -0.708,0.708 l 1,1 a 0.5006316,0.5006316 0 0 0 0.708,-0.708 z m 0.3,-2 a 0.473,0.473 0 0 0 -0.154,0.354 0.4,0.4 0 0 0 0.04,0.189 0.353,0.353 0 0 0 0.11,0.161 0.469,0.469 0 0 0 0.35,0.15 0.406,0.406 0 0 0 0.19,-0.04 0.372,0.372 0 0 0 0.16,-0.11 0.454,0.454 0 0 0 0.15,-0.35 0.473,0.473 0 0 0 -0.15,-0.351 0.5,0.5 0 0 0 -0.7,0 z m -3,3 a 0.473,0.473 0 0 0 -0.154,0.354 0.454,0.454 0 0 0 0.15,0.35 0.372,0.372 0 0 0 0.16,0.11 0.406,0.406 0 0 0 0.19,0.04 0.469,0.469 0 0 0 0.35,-0.15 0.353,0.353 0 0 0 0.11,-0.161 0.4,0.4 0 0 0 0.04,-0.189 0.473,0.473 0 0 0 -0.15,-0.351 0.5,0.5 0 0 0 -0.7,0 z M 18,5.0006316 a 3,3 0 0 0 -3,-3 H 7 a 3,3 0 0 0 -3,3 v 8.0000004 a 3,3 0 0 0 3,3 h 8 a 3,3 0 0 0 3,-3 z m -2,8.0000004 a 1,1 0 0 1 -1,1 H 7 a 1,1 0 0 1 -1,-1 V 7.0006316 H 16 Z M 16,6.0006316 H 6 v -1 a 1,1 0 0 1 1,-1 h 8 a 1,1 0 0 1 1,1 z M 11,18.000632 H 3 a 1,1 0 0 1 -1,-1 v -6 h 1 v -1 H 2 V 9.0006316 a 1,1 0 0 1 1,-1 v -2 a 3,3 0 0 0 -3,3 v 8.0000004 a 3,3 0 0 0 3,3 h 8 a 3,3 0 0 0 3,-3 h -2 a 1,1 0 0 1 -1,1 z' } ], + [ 'ph-readermode-text-size', { viewBox: '0 0 20 12.5', path: 'M 10.422,11.223 A 0.712,0.712 0 0 1 10.295,11.007 L 6.581,0 H 4.68 L 0.933,11.309 0,11.447 V 12.5 H 3.594 V 11.447 L 2.655,11.325 A 0.3,0.3 0 0 1 2.468,11.211 0.214,0.214 0 0 1 2.419,10.974 L 3.341,8.387 h 3.575 l 0.906,2.652 a 0.18,0.18 0 0 1 -0.016,0.18 0.217,0.217 0 0 1 -0.139,0.106 L 6.679,11.447 V 12.5 h 4.62 V 11.447 L 10.663,11.325 A 0.512,0.512 0 0 1 10.422,11.223 Z M 3.659,7.399 5.063,2.57 6.5,7.399 Z M 19.27,11.464 A 0.406,0.406 0 0 1 19.009,11.337 0.368,0.368 0 0 1 18.902,11.072 V 6.779 A 3.838,3.838 0 0 0 18.67,5.318 1.957,1.957 0 0 0 18.01,4.457 2.48,2.48 0 0 0 16.987,4.044 7.582,7.582 0 0 0 15.67,3.938 a 6.505,6.505 0 0 0 -1.325,0.139 5.2,5.2 0 0 0 -1.2,0.4 2.732,2.732 0 0 0 -0.864,0.624 1.215,1.215 0 0 0 -0.331,0.833 0.532,0.532 0 0 0 0.119,0.383 0.665,0.665 0 0 0 0.257,0.172 0.916,0.916 0 0 0 0.375,0.041 h 1.723 V 4.942 A 4.429,4.429 0 0 1 14.611,4.91 2.045,2.045 0 0 1 14.836,4.885 c 0.09,0 0.192,-0.008 0.306,-0.008 a 1.849,1.849 0 0 1 0.808,0.151 1.247,1.247 0 0 1 0.71,0.89 2.164,2.164 0 0 1 0.049,0.51 c 0,0.076 -0.008,0.152 -0.008,0.228 0,0.076 -0.008,0.139 -0.008,0.221 v 0.2 q -1.152,0.252 -1.976,0.489 a 12.973,12.973 0 0 0 -1.391,0.474 4.514,4.514 0 0 0 -0.91,0.485 2.143,2.143 0 0 0 -0.527,0.523 1.594,1.594 0 0 0 -0.245,0.592 3.739,3.739 0 0 0 -0.061,0.693 2.261,2.261 0 0 0 0.171,0.9 2.024,2.024 0 0 0 0.469,0.682 2.084,2.084 0 0 0 0.693,0.432 2.364,2.364 0 0 0 0.852,0.151 3.587,3.587 0 0 0 1.068,-0.159 6.441,6.441 0 0 0 1.835,-0.877 l 0.22,0.832 H 20 v -0.783 z m -2.588,-0.719 a 4.314,4.314 0 0 1 -0.5,0.188 5.909,5.909 0 0 1 -0.493,0.123 2.665,2.665 0 0 1 -0.543,0.057 1.173,1.173 0 0 1 -0.861,-0.363 1.166,1.166 0 0 1 -0.245,-0.392 1.357,1.357 0 0 1 -0.086,-0.486 1.632,1.632 0 0 1 0.123,-0.657 1.215,1.215 0 0 1 0.432,-0.5 3.151,3.151 0 0 1 0.837,-0.392 12.429,12.429 0 0 1 1.334,-0.334 z' } ], + ]); + + return function(root) { + const icons = (root || document).querySelectorAll('.fa-icon'); + if ( icons.length === 0 ) { return; } + const svgNS = 'http://www.w3.org/2000/svg'; + for ( const icon of icons ) { + if ( icon.firstChild === null || icon.firstChild.nodeType !== 3 ) { + continue; + } + const name = icon.firstChild.nodeValue.trim(); + if ( name === '' ) { continue; } + const svg = document.createElementNS(svgNS, 'svg'); + svg.classList.add('fa-icon_' + name); + const details = svgIcons.get(name); + if ( details === undefined ) { + let file; + if ( name.startsWith('ph-') ) { + file = 'photon'; + } else if ( name.startsWith('md-') ) { + file = 'material-design'; + } else { + continue; + } + const use = document.createElementNS(svgNS, 'use'); + use.setAttribute('href', `/img/${file}.svg#${name}`); + svg.appendChild(use); + } else { + svg.setAttribute('viewBox', details.viewBox); + const path = document.createElementNS(svgNS, 'path'); + path.setAttribute('d', details.path); + svg.appendChild(path); + } + icon.replaceChild(svg, icon.firstChild); + if ( icon.classList.contains('fa-icon-badged') ) { + const badge = document.createElement('span'); + badge.className = 'fa-icon-badge'; + icon.insertBefore(badge, icon.firstChild.nextSibling); + } + } + }; +})(); + +faIconsInit(); diff --git a/src/js/filtering-context.js b/src/js/filtering-context.js new file mode 100644 index 0000000..5bc9aa1 --- /dev/null +++ b/src/js/filtering-context.js @@ -0,0 +1,461 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2018-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import { + hostnameFromURI, + domainFromHostname, + originFromURI, +} from './uri-utils.js'; + +/******************************************************************************/ + +// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType + +// Long term, convert code wherever possible to work with integer-based type +// values -- the assumption being that integer operations are faster than +// string operations. + +export const NO_TYPE = 0; +export const BEACON = 1 << 0; +export const CSP_REPORT = 1 << 1; +export const FONT = 1 << 2; +export const IMAGE = 1 << 4; +export const IMAGESET = 1 << 4; +export const MAIN_FRAME = 1 << 5; +export const MEDIA = 1 << 6; +export const OBJECT = 1 << 7; +export const OBJECT_SUBREQUEST = 1 << 7; +export const PING = 1 << 8; +export const SCRIPT = 1 << 9; +export const STYLESHEET = 1 << 10; +export const SUB_FRAME = 1 << 11; +export const WEBSOCKET = 1 << 12; +export const XMLHTTPREQUEST = 1 << 13; +export const INLINE_FONT = 1 << 14; +export const INLINE_SCRIPT = 1 << 15; +export const OTHER = 1 << 16; +export const FRAME_ANY = MAIN_FRAME | SUB_FRAME; +export const FONT_ANY = FONT | INLINE_FONT; +export const INLINE_ANY = INLINE_FONT | INLINE_SCRIPT; +export const PING_ANY = BEACON | CSP_REPORT | PING; +export const SCRIPT_ANY = SCRIPT | INLINE_SCRIPT; + +const typeStrToIntMap = { + 'no_type': NO_TYPE, + 'beacon': BEACON, + 'csp_report': CSP_REPORT, + 'font': FONT, + 'image': IMAGE, + 'imageset': IMAGESET, + 'main_frame': MAIN_FRAME, + 'media': MEDIA, + 'object': OBJECT, + 'object_subrequest': OBJECT_SUBREQUEST, + 'ping': PING, + 'script': SCRIPT, + 'stylesheet': STYLESHEET, + 'sub_frame': SUB_FRAME, + 'websocket': WEBSOCKET, + 'xmlhttprequest': XMLHTTPREQUEST, + 'inline-font': INLINE_FONT, + 'inline-script': INLINE_SCRIPT, + 'other': OTHER, +}; + +export const METHOD_NONE = 0; +export const METHOD_CONNECT = 1 << 1; +export const METHOD_DELETE = 1 << 2; +export const METHOD_GET = 1 << 3; +export const METHOD_HEAD = 1 << 4; +export const METHOD_OPTIONS = 1 << 5; +export const METHOD_PATCH = 1 << 6; +export const METHOD_POST = 1 << 7; +export const METHOD_PUT = 1 << 8; + +const methodStrToBitMap = { + '': METHOD_NONE, + 'connect': METHOD_CONNECT, + 'delete': METHOD_DELETE, + 'get': METHOD_GET, + 'head': METHOD_HEAD, + 'options': METHOD_OPTIONS, + 'patch': METHOD_PATCH, + 'post': METHOD_POST, + 'put': METHOD_PUT, + 'CONNECT': METHOD_CONNECT, + 'DELETE': METHOD_DELETE, + 'GET': METHOD_GET, + 'HEAD': METHOD_HEAD, + 'OPTIONS': METHOD_OPTIONS, + 'PATCH': METHOD_PATCH, + 'POST': METHOD_POST, + 'PUT': METHOD_PUT, +}; + +const methodBitToStrMap = new Map([ + [ METHOD_NONE, '' ], + [ METHOD_CONNECT, 'connect' ], + [ METHOD_DELETE, 'delete' ], + [ METHOD_GET, 'get' ], + [ METHOD_HEAD, 'head' ], + [ METHOD_OPTIONS, 'options' ], + [ METHOD_PATCH, 'patch' ], + [ METHOD_POST, 'post' ], + [ METHOD_PUT, 'put' ], +]); + +/******************************************************************************/ + +export const FilteringContext = class { + constructor(other) { + if ( other instanceof FilteringContext ) { + return this.fromFilteringContext(other); + } + this.tstamp = 0; + this.realm = ''; + this.id = undefined; + this.method = 0; + this.itype = NO_TYPE; + this.stype = undefined; + this.url = undefined; + this.aliasURL = undefined; + this.hostname = undefined; + this.domain = undefined; + this.docId = -1; + this.frameId = -1; + this.docOrigin = undefined; + this.docHostname = undefined; + this.docDomain = undefined; + this.tabId = undefined; + this.tabOrigin = undefined; + this.tabHostname = undefined; + this.tabDomain = undefined; + this.redirectURL = undefined; + this.filter = undefined; + } + + get type() { + return this.stype; + } + + set type(a) { + this.itype = typeStrToIntMap[a] || NO_TYPE; + this.stype = a; + } + + isDocument() { + return (this.itype & FRAME_ANY) !== 0; + } + + isFont() { + return (this.itype & FONT_ANY) !== 0; + } + + fromFilteringContext(other) { + this.realm = other.realm; + this.id = other.id; + this.type = other.type; + this.method = other.method; + this.url = other.url; + this.hostname = other.hostname; + this.domain = other.domain; + this.docId = other.docId; + this.frameId = other.frameId; + this.docOrigin = other.docOrigin; + this.docHostname = other.docHostname; + this.docDomain = other.docDomain; + this.tabId = other.tabId; + this.tabOrigin = other.tabOrigin; + this.tabHostname = other.tabHostname; + this.tabDomain = other.tabDomain; + this.redirectURL = other.redirectURL; + this.filter = undefined; + return this; + } + + fromDetails({ originURL, url, type }) { + this.setDocOriginFromURL(originURL) + .setURL(url) + .setType(type); + return this; + } + + duplicate() { + return (new FilteringContext(this)); + } + + setRealm(a) { + this.realm = a; + return this; + } + + setType(a) { + this.type = a; + return this; + } + + setURL(a) { + if ( a !== this.url ) { + this.hostname = this.domain = undefined; + this.url = a; + } + return this; + } + + getHostname() { + if ( this.hostname === undefined ) { + this.hostname = hostnameFromURI(this.url); + } + return this.hostname; + } + + setHostname(a) { + if ( a !== this.hostname ) { + this.domain = undefined; + this.hostname = a; + } + return this; + } + + getDomain() { + if ( this.domain === undefined ) { + this.domain = domainFromHostname(this.getHostname()); + } + return this.domain; + } + + setDomain(a) { + this.domain = a; + return this; + } + + getDocOrigin() { + if ( this.docOrigin === undefined ) { + this.docOrigin = this.tabOrigin; + } + return this.docOrigin; + } + + setDocOrigin(a) { + if ( a !== this.docOrigin ) { + this.docHostname = this.docDomain = undefined; + this.docOrigin = a; + } + return this; + } + + setDocOriginFromURL(a) { + return this.setDocOrigin(originFromURI(a)); + } + + getDocHostname() { + if ( this.docHostname === undefined ) { + this.docHostname = hostnameFromURI(this.getDocOrigin()); + } + return this.docHostname; + } + + setDocHostname(a) { + if ( a !== this.docHostname ) { + this.docDomain = undefined; + this.docHostname = a; + } + return this; + } + + getDocDomain() { + if ( this.docDomain === undefined ) { + this.docDomain = domainFromHostname(this.getDocHostname()); + } + return this.docDomain; + } + + setDocDomain(a) { + this.docDomain = a; + return this; + } + + // The idea is to minimize the amount of work done to figure out whether + // the resource is 3rd-party to the document. + is3rdPartyToDoc() { + let docDomain = this.getDocDomain(); + if ( docDomain === '' ) { docDomain = this.docHostname; } + if ( this.domain !== undefined && this.domain !== '' ) { + return this.domain !== docDomain; + } + const hostname = this.getHostname(); + if ( hostname.endsWith(docDomain) === false ) { return true; } + const i = hostname.length - docDomain.length; + if ( i === 0 ) { return false; } + return hostname.charCodeAt(i - 1) !== 0x2E /* '.' */; + } + + setTabId(a) { + this.tabId = a; + return this; + } + + getTabOrigin() { + return this.tabOrigin; + } + + setTabOrigin(a) { + if ( a !== this.tabOrigin ) { + this.tabHostname = this.tabDomain = undefined; + this.tabOrigin = a; + } + return this; + } + + setTabOriginFromURL(a) { + return this.setTabOrigin(originFromURI(a)); + } + + getTabHostname() { + if ( this.tabHostname === undefined ) { + this.tabHostname = hostnameFromURI(this.getTabOrigin()); + } + return this.tabHostname; + } + + setTabHostname(a) { + if ( a !== this.tabHostname ) { + this.tabDomain = undefined; + this.tabHostname = a; + } + return this; + } + + getTabDomain() { + if ( this.tabDomain === undefined ) { + this.tabDomain = domainFromHostname(this.getTabHostname()); + } + return this.tabDomain; + } + + setTabDomain(a) { + this.docDomain = a; + return this; + } + + // The idea is to minimize the amount of work done to figure out whether + // the resource is 3rd-party to the top document. + is3rdPartyToTab() { + let tabDomain = this.getTabDomain(); + if ( tabDomain === '' ) { tabDomain = this.tabHostname; } + if ( this.domain !== undefined && this.domain !== '' ) { + return this.domain !== tabDomain; + } + const hostname = this.getHostname(); + if ( hostname.endsWith(tabDomain) === false ) { return true; } + const i = hostname.length - tabDomain.length; + if ( i === 0 ) { return false; } + return hostname.charCodeAt(i - 1) !== 0x2E /* '.' */; + } + + setFilter(a) { + this.filter = a; + return this; + } + + pushFilter(a) { + if ( this.filter === undefined ) { + return this.setFilter(a); + } + if ( Array.isArray(this.filter) ) { + this.filter.push(a); + } else { + this.filter = [ this.filter, a ]; + } + return this; + } + + pushFilters(a) { + if ( this.filter === undefined ) { + return this.setFilter(a); + } + if ( Array.isArray(this.filter) ) { + this.filter.push(...a); + } else { + this.filter = [ this.filter, ...a ]; + } + return this; + } + + setMethod(a) { + this.method = methodStrToBitMap[a] || 0; + return this; + } + + getMethodName() { + return FilteringContext.getMethodName(this.method); + } + + static getMethod(a) { + return methodStrToBitMap[a] || 0; + } + + static getMethodName(a) { + return methodBitToStrMap.get(a) || ''; + } +}; + +/******************************************************************************/ + +FilteringContext.prototype.BEACON = FilteringContext.BEACON = BEACON; +FilteringContext.prototype.CSP_REPORT = FilteringContext.CSP_REPORT = CSP_REPORT; +FilteringContext.prototype.FONT = FilteringContext.FONT = FONT; +FilteringContext.prototype.IMAGE = FilteringContext.IMAGE = IMAGE; +FilteringContext.prototype.IMAGESET = FilteringContext.IMAGESET = IMAGESET; +FilteringContext.prototype.MAIN_FRAME = FilteringContext.MAIN_FRAME = MAIN_FRAME; +FilteringContext.prototype.MEDIA = FilteringContext.MEDIA = MEDIA; +FilteringContext.prototype.OBJECT = FilteringContext.OBJECT = OBJECT; +FilteringContext.prototype.OBJECT_SUBREQUEST = FilteringContext.OBJECT_SUBREQUEST = OBJECT_SUBREQUEST; +FilteringContext.prototype.PING = FilteringContext.PING = PING; +FilteringContext.prototype.SCRIPT = FilteringContext.SCRIPT = SCRIPT; +FilteringContext.prototype.STYLESHEET = FilteringContext.STYLESHEET = STYLESHEET; +FilteringContext.prototype.SUB_FRAME = FilteringContext.SUB_FRAME = SUB_FRAME; +FilteringContext.prototype.WEBSOCKET = FilteringContext.WEBSOCKET = WEBSOCKET; +FilteringContext.prototype.XMLHTTPREQUEST = FilteringContext.XMLHTTPREQUEST = XMLHTTPREQUEST; +FilteringContext.prototype.INLINE_FONT = FilteringContext.INLINE_FONT = INLINE_FONT; +FilteringContext.prototype.INLINE_SCRIPT = FilteringContext.INLINE_SCRIPT = INLINE_SCRIPT; +FilteringContext.prototype.OTHER = FilteringContext.OTHER = OTHER; +FilteringContext.prototype.FRAME_ANY = FilteringContext.FRAME_ANY = FRAME_ANY; +FilteringContext.prototype.FONT_ANY = FilteringContext.FONT_ANY = FONT_ANY; +FilteringContext.prototype.INLINE_ANY = FilteringContext.INLINE_ANY = INLINE_ANY; +FilteringContext.prototype.PING_ANY = FilteringContext.PING_ANY = PING_ANY; +FilteringContext.prototype.SCRIPT_ANY = FilteringContext.SCRIPT_ANY = SCRIPT_ANY; + +FilteringContext.prototype.METHOD_NONE = FilteringContext.METHOD_NONE = METHOD_NONE; +FilteringContext.prototype.METHOD_CONNECT = FilteringContext.METHOD_CONNECT = METHOD_CONNECT; +FilteringContext.prototype.METHOD_DELETE = FilteringContext.METHOD_DELETE = METHOD_DELETE; +FilteringContext.prototype.METHOD_GET = FilteringContext.METHOD_GET = METHOD_GET; +FilteringContext.prototype.METHOD_HEAD = FilteringContext.METHOD_HEAD = METHOD_HEAD; +FilteringContext.prototype.METHOD_OPTIONS = FilteringContext.METHOD_OPTIONS = METHOD_OPTIONS; +FilteringContext.prototype.METHOD_PATCH = FilteringContext.METHOD_PATCH = METHOD_PATCH; +FilteringContext.prototype.METHOD_POST = FilteringContext.METHOD_POST = METHOD_POST; +FilteringContext.prototype.METHOD_PUT = FilteringContext.METHOD_PUT = METHOD_PUT; + +/******************************************************************************/ diff --git a/src/js/filtering-engines.js b/src/js/filtering-engines.js new file mode 100644 index 0000000..d72ff9d --- /dev/null +++ b/src/js/filtering-engines.js @@ -0,0 +1,50 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import DynamicHostRuleFiltering from './dynamic-net-filtering.js'; +import DynamicSwitchRuleFiltering from './hnswitches.js'; +import DynamicURLRuleFiltering from './url-net-filtering.js'; + +/******************************************************************************/ + +const permanentFirewall = new DynamicHostRuleFiltering(); +const sessionFirewall = new DynamicHostRuleFiltering(); + +const permanentURLFiltering = new DynamicURLRuleFiltering(); +const sessionURLFiltering = new DynamicURLRuleFiltering(); + +const permanentSwitches = new DynamicSwitchRuleFiltering(); +const sessionSwitches = new DynamicSwitchRuleFiltering(); + +/******************************************************************************/ + +export { + permanentFirewall, + sessionFirewall, + permanentURLFiltering, + sessionURLFiltering, + permanentSwitches, + sessionSwitches, +}; diff --git a/src/js/hnswitches.js b/src/js/hnswitches.js new file mode 100644 index 0000000..9e94a8e --- /dev/null +++ b/src/js/hnswitches.js @@ -0,0 +1,289 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +/* jshint bitwise: false */ + +'use strict'; + +/******************************************************************************/ + +import punycode from '../lib/punycode.js'; + +import { decomposeHostname } from './uri-utils.js'; +import { LineIterator } from './text-utils.js'; + +/******************************************************************************/ + +const decomposedSource = []; + +// Object.create(null) is used below to eliminate worries about unexpected +// property names in prototype chain -- and this way we don't have to use +// hasOwnProperty() to avoid this. + +const switchBitOffsets = Object.create(null); +Object.assign(switchBitOffsets, { + 'no-strict-blocking': 0, + 'no-popups': 2, + 'no-cosmetic-filtering': 4, + 'no-remote-fonts': 6, + 'no-large-media': 8, + 'no-csp-reports': 10, + 'no-scripting': 12, +}); + +const switchStateToNameMap = Object.create(null); +Object.assign(switchStateToNameMap, { + '1': 'true', + '2': 'false', +}); + +const nameToSwitchStateMap = Object.create(null); +Object.assign(nameToSwitchStateMap, { + 'true': 1, + 'false': 2, + 'on': 1, + 'off': 2, +}); + +/******************************************************************************/ + +// For performance purpose, as simple test as possible +const reNotASCII = /[^\x20-\x7F]/; + +// http://tools.ietf.org/html/rfc5952 +// 4.3: "MUST be represented in lowercase" +// Also: http://en.wikipedia.org/wiki/IPv6_address#Literal_IPv6_addresses_in_network_resource_identifiers + +/******************************************************************************/ + +class DynamicSwitchRuleFiltering { + constructor() { + this.reset(); + } + + reset() { + this.switches = new Map(); + this.n = ''; + this.z = ''; + this.r = 0; + this.changed = true; + } + + assign(from) { + // Remove rules not in other + for ( const hn of this.switches.keys() ) { + if ( from.switches.has(hn) === false ) { + this.switches.delete(hn); + this.changed = true; + } + } + // Add/change rules in other + for ( const [hn, bits] of from.switches ) { + if ( this.switches.get(hn) !== bits ) { + this.switches.set(hn, bits); + this.changed = true; + } + } + } + + copyRules(from, srcHostname) { + const thisBits = this.switches.get(srcHostname); + const fromBits = from.switches.get(srcHostname); + if ( fromBits !== thisBits ) { + if ( fromBits !== undefined ) { + this.switches.set(srcHostname, fromBits); + } else { + this.switches.delete(srcHostname); + } + this.changed = true; + } + return this.changed; + } + + hasSameRules(other, srcHostname) { + return this.switches.get(srcHostname) === other.switches.get(srcHostname); + } + + toggle(switchName, hostname, newVal) { + const bitOffset = switchBitOffsets[switchName]; + if ( bitOffset === undefined ) { return false; } + if ( newVal === this.evaluate(switchName, hostname) ) { return false; } + let bits = this.switches.get(hostname) || 0; + bits &= ~(3 << bitOffset); + bits |= newVal << bitOffset; + if ( bits === 0 ) { + this.switches.delete(hostname); + } else { + this.switches.set(hostname, bits); + } + this.changed = true; + return true; + } + + toggleOneZ(switchName, hostname, newState) { + const bitOffset = switchBitOffsets[switchName]; + if ( bitOffset === undefined ) { return false; } + let state = this.evaluateZ(switchName, hostname); + if ( newState === state ) { return false; } + if ( newState === undefined ) { + newState = !state; + } + let bits = this.switches.get(hostname) || 0; + bits &= ~(3 << bitOffset); + if ( bits === 0 ) { + this.switches.delete(hostname); + } else { + this.switches.set(hostname, bits); + } + state = this.evaluateZ(switchName, hostname); + if ( state !== newState ) { + this.switches.set(hostname, bits | ((newState ? 1 : 2) << bitOffset)); + } + this.changed = true; + return true; + } + + toggleBranchZ(switchName, targetHostname, newState) { + this.toggleOneZ(switchName, targetHostname, newState); + + // Turn off all descendant switches, they will inherit the state of the + // branch's origin. + const targetLen = targetHostname.length; + for ( const hostname of this.switches.keys() ) { + if ( hostname === targetHostname ) { continue; } + if ( hostname.length <= targetLen ) { continue; } + if ( hostname.endsWith(targetHostname) === false ) { continue; } + if ( hostname.charAt(hostname.length - targetLen - 1) !== '.' ) { + continue; + } + this.toggle(switchName, hostname, 0); + } + + return this.changed; + } + + toggleZ(switchName, hostname, deep, newState) { + if ( deep === true ) { + return this.toggleBranchZ(switchName, hostname, newState); + } + return this.toggleOneZ(switchName, hostname, newState); + } + + // 0 = inherit from broader scope, up to default state + // 1 = non-default state + // 2 = forced default state (to override a broader non-default state) + + evaluate(switchName, hostname) { + const bits = this.switches.get(hostname); + if ( bits === undefined ) { return 0; } + let bitOffset = switchBitOffsets[switchName]; + if ( bitOffset === undefined ) { return 0; } + return (bits >>> bitOffset) & 3; + } + + evaluateZ(switchName, hostname) { + const bitOffset = switchBitOffsets[switchName]; + if ( bitOffset === undefined ) { + this.r = 0; + return false; + } + this.n = switchName; + for ( const shn of decomposeHostname(hostname, decomposedSource) ) { + let bits = this.switches.get(shn); + if ( bits === undefined ) { continue; } + bits = bits >>> bitOffset & 3; + if ( bits === 0 ) { continue; } + this.z = shn; + this.r = bits; + return bits === 1; + } + this.r = 0; + return false; + } + + toLogData() { + return { + source: 'switch', + result: this.r, + raw: `${this.n}: ${this.z} true` + }; + } + + toArray() { + const out = []; + for ( const hostname of this.switches.keys() ) { + const prettyHn = hostname.includes('xn--') && punycode + ? punycode.toUnicode(hostname) + : hostname; + for ( const switchName in switchBitOffsets ) { + if ( switchBitOffsets[switchName] === undefined ) { continue; } + const val = this.evaluate(switchName, hostname); + if ( val === 0 ) { continue; } + out.push(`${switchName}: ${prettyHn} ${switchStateToNameMap[val]}`); + } + } + return out; + } + + toString() { + return this.toArray().join('\n'); + } + + fromString(text, append) { + const lineIter = new LineIterator(text); + if ( append !== true ) { this.reset(); } + while ( lineIter.eot() === false ) { + this.addFromRuleParts(lineIter.next().trim().split(/\s+/)); + } + } + + validateRuleParts(parts) { + if ( parts.length < 3 ) { return; } + if ( parts[0].endsWith(':') === false ) { return; } + if ( nameToSwitchStateMap[parts[2]] === undefined ) { return; } + if ( reNotASCII.test(parts[1]) && punycode !== undefined ) { + parts[1] = punycode.toASCII(parts[1]); + } + return parts; + } + + addFromRuleParts(parts) { + if ( this.validateRuleParts(parts) === undefined ) { return false; } + const switchName = parts[0].slice(0, -1); + if ( switchBitOffsets[switchName] === undefined ) { return false; } + this.toggle(switchName, parts[1], nameToSwitchStateMap[parts[2]]); + return true; + } + + removeFromRuleParts(parts) { + if ( this.validateRuleParts(parts) !== undefined ) { + this.toggle(parts[0].slice(0, -1), parts[1], 0); + return true; + } + return false; + } +} + +/******************************************************************************/ + +export default DynamicSwitchRuleFiltering; + +/******************************************************************************/ diff --git a/src/js/hntrie.js b/src/js/hntrie.js new file mode 100644 index 0000000..e8031a6 --- /dev/null +++ b/src/js/hntrie.js @@ -0,0 +1,780 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2017-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 +*/ + +/* globals WebAssembly */ + +'use strict'; + +/******************************************************************************* + + The original prototype was to develop an idea I had about using jump indices + in a TypedArray for quickly matching hostnames (or more generally strings)[1]. + Once I had a working, un-optimized prototype, I realized I had ended up + with something formally named a "trie": , + hence the name. I have no idea whether the implementation here or one + resembling it has been done elsewhere. + + "HN" in HNTrieContainer stands for "HostName", because the trie is + specialized to deal with matching hostnames -- which is a bit more + complicated than matching plain strings. + + For example, `www.abc.com` is deemed matching `abc.com`, because the former + is a subdomain of the latter. The opposite is of course not true. + + The resulting read-only tries created as a result of using HNTrieContainer + are simply just typed arrays filled with integers. The matching algorithm is + just a matter of reading/comparing these integers, and further using them as + indices in the array as a way to move around in the trie. + + [1] To solve + + Since this trie is specialized for matching hostnames, the stored + strings are reversed internally, because of hostname comparison logic: + + Correct matching: + index 0123456 + abc.com + | + www.abc.com + index 01234567890 + + Incorrect matching (typically used for plain strings): + index 0123456 + abc.com + | + www.abc.com + index 01234567890 + + ------------------------------------------------------------------------------ + + 1st iteration: + - https://github.com/gorhill/uBlock/blob/ff58107dac3a32607f8113e39ed5015584506813/src/js/hntrie.js + - Suitable for small to medium set of hostnames + - One buffer per trie + + 2nd iteration: goal was to make matches() method wasm-able + - https://github.com/gorhill/uBlock/blob/c3b0fd31f64bd7ffecdd282fb1208fe07aac3eb0/src/js/hntrie.js + - Suitable for small to medium set of hostnames + - Distinct tries all share same buffer: + - Reduced memory footprint + - https://stackoverflow.com/questions/45803829/memory-overhead-of-typed-arrays-vs-strings/45808835#45808835 + - Reusing needle character lookups for all tries + - This significantly reduce the number of String.charCodeAt() calls + - Slightly improved creation time + + This is the 3rd iteration: goal was to make add() method wasm-able and + further improve memory/CPU efficiency. + + This 3rd iteration has the following new traits: + - Suitable for small to large set of hostnames + - Support multiple trie containers (instanciable) + - Designed to hold large number of hostnames + - Hostnames can be added at any time (instead of all at once) + - This means pre-sorting is no longer a requirement + - The trie is always compact + - There is no longer a need for a `vacuum` method + - This makes the add() method wasm-able + - It can return the exact hostname which caused the match + - serializable/unserializable available for fast loading + - Distinct trie reference support the iteration protocol, thus allowing + to extract all the hostnames in the trie + + Its primary purpose is to replace the use of Set() as a mean to hold + large number of hostnames (ex. FilterHostnameDict in static filtering + engine). + + A HNTrieContainer is mostly a large buffer in which distinct but related + tries are stored. The memory layout of the buffer is as follow: + + 0-254: needle being processed + 255: length of needle + 256-259: offset to start of trie data section (=> trie0) + 260-263: offset to end of trie data section (=> trie1) + 264-267: offset to start of character data section (=> char0) + 268-271: offset to end of character data section (=> char1) + 272: start of trie data section + +*/ + +const PAGE_SIZE = 65536; + // i32 / i8 +const TRIE0_SLOT = 256 >>> 2; // 64 / 256 +const TRIE1_SLOT = TRIE0_SLOT + 1; // 65 / 260 +const CHAR0_SLOT = TRIE0_SLOT + 2; // 66 / 264 +const CHAR1_SLOT = TRIE0_SLOT + 3; // 67 / 268 +const TRIE0_START = TRIE0_SLOT + 4 << 2; // 272 + +const roundToPageSize = v => (v + PAGE_SIZE-1) & ~(PAGE_SIZE-1); + +class HNTrieContainer { + + constructor() { + const len = PAGE_SIZE * 2; + this.buf = new Uint8Array(len); + this.buf32 = new Uint32Array(this.buf.buffer); + this.needle = ''; + this.buf32[TRIE0_SLOT] = TRIE0_START; + this.buf32[TRIE1_SLOT] = this.buf32[TRIE0_SLOT]; + this.buf32[CHAR0_SLOT] = len >>> 1; + this.buf32[CHAR1_SLOT] = this.buf32[CHAR0_SLOT]; + this.wasmMemory = null; + + this.lastStored = ''; + this.lastStoredLen = this.lastStoredIndex = 0; + } + + //-------------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------------- + + reset(details) { + if ( + details instanceof Object && + typeof details.byteLength === 'number' && + typeof details.char0 === 'number' + ) { + if ( details.byteLength > this.buf.byteLength ) { + this.reallocateBuf(details.byteLength); + } + this.buf32[CHAR0_SLOT] = details.char0; + } + this.buf32[TRIE1_SLOT] = this.buf32[TRIE0_SLOT]; + this.buf32[CHAR1_SLOT] = this.buf32[CHAR0_SLOT]; + + this.lastStored = ''; + this.lastStoredLen = this.lastStoredIndex = 0; + } + + setNeedle(needle) { + if ( needle !== this.needle ) { + const buf = this.buf; + let i = needle.length; + if ( i > 255 ) { i = 255; } + buf[255] = i; + while ( i-- ) { + buf[i] = needle.charCodeAt(i); + } + this.needle = needle; + } + return this; + } + + matchesJS(iroot) { + const buf32 = this.buf32; + const buf8 = this.buf; + const char0 = buf32[CHAR0_SLOT]; + let ineedle = buf8[255]; + let icell = buf32[iroot+0]; + if ( icell === 0 ) { return -1; } + let c = 0, v = 0, i0 = 0, n = 0; + for (;;) { + if ( ineedle === 0 ) { return -1; } + ineedle -= 1; + c = buf8[ineedle]; + // find first segment with a first-character match + for (;;) { + v = buf32[icell+2]; + i0 = char0 + (v >>> 8); + if ( buf8[i0] === c ) { break; } + icell = buf32[icell+0]; + if ( icell === 0 ) { return -1; } + } + // all characters in segment must match + n = v & 0x7F; + if ( n > 1 ) { + n -= 1; + if ( n > ineedle ) { return -1; } + i0 += 1; + const i1 = i0 + n; + do { + ineedle -= 1; + if ( buf8[i0] !== buf8[ineedle] ) { return -1; } + i0 += 1; + } while ( i0 < i1 ); + } + // boundary at end of segment? + if ( (v & 0x80) !== 0 ) { + if ( ineedle === 0 || buf8[ineedle-1] === 0x2E /* '.' */ ) { + return ineedle; + } + } + // next segment + icell = buf32[icell+1]; + if ( icell === 0 ) { break; } + } + return -1; + } + + createTrie() { + // grow buffer if needed + if ( (this.buf32[CHAR0_SLOT] - this.buf32[TRIE1_SLOT]) < 12 ) { + this.growBuf(12, 0); + } + const iroot = this.buf32[TRIE1_SLOT] >>> 2; + this.buf32[TRIE1_SLOT] += 12; + this.buf32[iroot+0] = 0; + this.buf32[iroot+1] = 0; + this.buf32[iroot+2] = 0; + return iroot; + } + + createTrieFromIterable(hostnames) { + const itrie = this.createTrie(); + for ( const hn of hostnames ) { + if ( hn === '' ) { continue; } + this.setNeedle(hn).add(itrie); + } + return itrie; + } + + createTrieFromStoredDomainOpt(i, n) { + const itrie = this.createTrie(); + const jend = i + n; + let j = i, offset = 0, k = 0, c = 0; + while ( j !== jend ) { + offset = this.buf32[CHAR0_SLOT]; // Important + k = 0; + for (;;) { + if ( j === jend ) { break; } + c = this.buf[offset+j]; + j += 1; + if ( c === 0x7C /* '|' */ ) { break; } + if ( k === 255 ) { continue; } + this.buf[k] = c; + k += 1; + } + if ( k !== 0 ) { + this.buf[255] = k; + this.add(itrie); + } + } + this.needle = ''; // Important + this.buf[255] = 0; // Important + return itrie; + } + + dumpTrie(iroot) { + let hostnames = Array.from(this.trieIterator(iroot)); + if ( String.prototype.padStart instanceof Function ) { + const maxlen = Math.min( + hostnames.reduce((maxlen, hn) => Math.max(maxlen, hn.length), 0), + 64 + ); + hostnames = hostnames.map(hn => hn.padStart(maxlen)); + } + for ( const hn of hostnames ) { + console.log(hn); + } + } + + trieIterator(iroot) { + return { + value: undefined, + done: false, + next() { + if ( this.icell === 0 ) { + if ( this.forks.length === 0 ) { + this.value = undefined; + this.done = true; + return this; + } + this.charPtr = this.forks.pop(); + this.icell = this.forks.pop(); + } + for (;;) { + const idown = this.container.buf32[this.icell+0]; + if ( idown !== 0 ) { + this.forks.push(idown, this.charPtr); + } + const v = this.container.buf32[this.icell+2]; + let i0 = this.container.buf32[CHAR0_SLOT] + (v >>> 8); + const i1 = i0 + (v & 0x7F); + while ( i0 < i1 ) { + this.charPtr -= 1; + this.charBuf[this.charPtr] = this.container.buf[i0]; + i0 += 1; + } + this.icell = this.container.buf32[this.icell+1]; + if ( (v & 0x80) !== 0 ) { + return this.toHostname(); + } + } + }, + toHostname() { + this.value = this.textDecoder.decode( + new Uint8Array(this.charBuf.buffer, this.charPtr) + ); + return this; + }, + container: this, + icell: this.buf32[iroot], + charBuf: new Uint8Array(256), + charPtr: 256, + forks: [], + textDecoder: new TextDecoder(), + [Symbol.iterator]() { return this; }, + }; + } + + // TODO: + // Rework code to add from a string already present in the character + // buffer, i.e. not having to go through setNeedle() when adding a new + // hostname to a trie. This will require much work though, and probably + // changing the order in which string segments are stored in the + // character buffer. + addJS(iroot) { + let lhnchar = this.buf[255]; + if ( lhnchar === 0 ) { return 0; } + // grow buffer if needed + if ( + (this.buf32[CHAR0_SLOT] - this.buf32[TRIE1_SLOT]) < 24 || + (this.buf.length - this.buf32[CHAR1_SLOT]) < 256 + ) { + this.growBuf(24, 256); + } + let icell = this.buf32[iroot+0]; + // special case: first node in trie + if ( icell === 0 ) { + this.buf32[iroot+0] = this.addLeafCell(lhnchar); + return 1; + } + // + const char0 = this.buf32[CHAR0_SLOT]; + let isegchar, lsegchar, boundaryBit, inext; + // find a matching cell: move down + for (;;) { + const v = this.buf32[icell+2]; + let isegchar0 = char0 + (v >>> 8); + // if first character is no match, move to next descendant + if ( this.buf[isegchar0] !== this.buf[lhnchar-1] ) { + inext = this.buf32[icell+0]; + if ( inext === 0 ) { + this.buf32[icell+0] = this.addLeafCell(lhnchar); + return 1; + } + icell = inext; + continue; + } + // 1st character was tested + isegchar = 1; + lhnchar -= 1; + // find 1st mismatch in rest of segment + lsegchar = v & 0x7F; + if ( lsegchar !== 1 ) { + for (;;) { + if ( isegchar === lsegchar ) { break; } + if ( lhnchar === 0 ) { break; } + if ( this.buf[isegchar0+isegchar] !== this.buf[lhnchar-1] ) { break; } + isegchar += 1; + lhnchar -= 1; + } + } + boundaryBit = v & 0x80; + // all segment characters matched + if ( isegchar === lsegchar ) { + // needle remainder: no + if ( lhnchar === 0 ) { + // boundary: yes, already present + if ( boundaryBit !== 0 ) { return 0; } + // boundary: no, mark as boundary + this.buf32[icell+2] = v | 0x80; + } + // needle remainder: yes + else { + // remainder is at label boundary? if yes, no need to add + // the rest since the shortest match is always reported + if ( boundaryBit !== 0 ) { + if ( this.buf[lhnchar-1] === 0x2E /* '.' */ ) { return -1; } + } + inext = this.buf32[icell+1]; + if ( inext !== 0 ) { + icell = inext; + continue; + } + // add needle remainder + this.buf32[icell+1] = this.addLeafCell(lhnchar); + } + } + // some segment characters matched + else { + // split current cell + isegchar0 -= char0; + this.buf32[icell+2] = isegchar0 << 8 | isegchar; + inext = this.addCell( + 0, + this.buf32[icell+1], + isegchar0 + isegchar << 8 | boundaryBit | lsegchar - isegchar + ); + this.buf32[icell+1] = inext; + // needle remainder: yes, need new cell for remaining characters + if ( lhnchar !== 0 ) { + this.buf32[inext+0] = this.addLeafCell(lhnchar); + } + // needle remainder: no, need boundary cell + else { + this.buf32[icell+2] |= 0x80; + } + } + return 1; + } + } + + optimize() { + this.shrinkBuf(); + return { + byteLength: this.buf.byteLength, + char0: this.buf32[CHAR0_SLOT], + }; + } + + serialize(encoder) { + if ( encoder instanceof Object ) { + return encoder.encode( + this.buf32.buffer, + this.buf32[CHAR1_SLOT] + ); + } + return Array.from( + new Uint32Array( + this.buf32.buffer, + 0, + this.buf32[CHAR1_SLOT] + 3 >>> 2 + ) + ); + } + + unserialize(selfie, decoder) { + this.needle = ''; + const shouldDecode = typeof selfie === 'string'; + let byteLength = shouldDecode + ? decoder.decodeSize(selfie) + : selfie.length << 2; + if ( byteLength === 0 ) { return false; } + byteLength = roundToPageSize(byteLength); + if ( this.wasmMemory !== null ) { + const pageCountBefore = this.buf.length >>> 16; + const pageCountAfter = byteLength >>> 16; + if ( pageCountAfter > pageCountBefore ) { + this.wasmMemory.grow(pageCountAfter - pageCountBefore); + this.buf = new Uint8Array(this.wasmMemory.buffer); + this.buf32 = new Uint32Array(this.buf.buffer); + } + } else if ( byteLength > this.buf.length ) { + this.buf = new Uint8Array(byteLength); + this.buf32 = new Uint32Array(this.buf.buffer); + } + if ( shouldDecode ) { + decoder.decode(selfie, this.buf.buffer); + } else { + this.buf32.set(selfie); + } + // https://github.com/uBlockOrigin/uBlock-issues/issues/2925 + this.buf[255] = 0; + return true; + } + + // The following *Hostname() methods can be used to store hostname strings + // outside the trie. This is useful to store/match hostnames which are + // not part of a collection, and yet still benefit from storing the strings + // into a trie container's character buffer. + // TODO: WASM version of matchesHostname() + + storeHostname(hn) { + let n = hn.length; + if ( n > 255 ) { + hn = hn.slice(-255); + n = 255; + } + if ( n === this.lastStoredLen && hn === this.lastStored ) { + return this.lastStoredIndex; + } + this.lastStored = hn; + this.lastStoredLen = n; + if ( (this.buf.length - this.buf32[CHAR1_SLOT]) < n ) { + this.growBuf(0, n); + } + const offset = this.buf32[CHAR1_SLOT]; + this.buf32[CHAR1_SLOT] = offset + n; + const buf8 = this.buf; + for ( let i = 0; i < n; i++ ) { + buf8[offset+i] = hn.charCodeAt(i); + } + return (this.lastStoredIndex = offset - this.buf32[CHAR0_SLOT]); + } + + extractHostname(i, n) { + const textDecoder = new TextDecoder(); + const offset = this.buf32[CHAR0_SLOT] + i; + return textDecoder.decode(this.buf.subarray(offset, offset + n)); + } + + storeDomainOpt(s) { + let n = s.length; + if ( n === this.lastStoredLen && s === this.lastStored ) { + return this.lastStoredIndex; + } + this.lastStored = s; + this.lastStoredLen = n; + if ( (this.buf.length - this.buf32[CHAR1_SLOT]) < n ) { + this.growBuf(0, n); + } + const offset = this.buf32[CHAR1_SLOT]; + this.buf32[CHAR1_SLOT] = offset + n; + const buf8 = this.buf; + for ( let i = 0; i < n; i++ ) { + buf8[offset+i] = s.charCodeAt(i); + } + return (this.lastStoredIndex = offset - this.buf32[CHAR0_SLOT]); + } + + extractDomainOpt(i, n) { + const textDecoder = new TextDecoder(); + const offset = this.buf32[CHAR0_SLOT] + i; + return textDecoder.decode(this.buf.subarray(offset, offset + n)); + } + + matchesHostname(hn, i, n) { + this.setNeedle(hn); + const buf8 = this.buf; + const hr = buf8[255]; + if ( n > hr ) { return false; } + const hl = hr - n; + const nl = this.buf32[CHAR0_SLOT] + i; + for ( let j = 0; j < n; j++ ) { + if ( buf8[nl+j] !== buf8[hl+j] ) { return false; } + } + return n === hr || hn.charCodeAt(hl-1) === 0x2E /* '.' */; + } + + async enableWASM(wasmModuleFetcher, path) { + if ( typeof WebAssembly === 'undefined' ) { return false; } + if ( this.wasmMemory instanceof WebAssembly.Memory ) { return true; } + const module = await getWasmModule(wasmModuleFetcher, path); + if ( module instanceof WebAssembly.Module === false ) { return false; } + const memory = new WebAssembly.Memory({ initial: 2 }); + const instance = await WebAssembly.instantiate(module, { + imports: { + memory, + growBuf: this.growBuf.bind(this, 24, 256) + } + }); + if ( instance instanceof WebAssembly.Instance === false ) { return false; } + this.wasmMemory = memory; + const curPageCount = memory.buffer.byteLength >>> 16; + const newPageCount = roundToPageSize(this.buf.byteLength) >>> 16; + if ( newPageCount > curPageCount ) { + memory.grow(newPageCount - curPageCount); + } + const buf = new Uint8Array(memory.buffer); + buf.set(this.buf); + this.buf = buf; + this.buf32 = new Uint32Array(this.buf.buffer); + this.matches = this.matchesWASM = instance.exports.matches; + this.add = this.addWASM = instance.exports.add; + return true; + } + + dumpInfo() { + return [ + `Buffer size (Uint8Array): ${this.buf32[CHAR1_SLOT].toLocaleString('en')}`, + `WASM: ${this.wasmMemory === null ? 'disabled' : 'enabled'}`, + ].join('\n'); + } + + //-------------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------------- + + addCell(idown, iright, v) { + let icell = this.buf32[TRIE1_SLOT]; + this.buf32[TRIE1_SLOT] = icell + 12; + icell >>>= 2; + this.buf32[icell+0] = idown; + this.buf32[icell+1] = iright; + this.buf32[icell+2] = v; + return icell; + } + + addLeafCell(lsegchar) { + const r = this.buf32[TRIE1_SLOT] >>> 2; + let i = r; + while ( lsegchar > 127 ) { + this.buf32[i+0] = 0; + this.buf32[i+1] = i + 3; + this.buf32[i+2] = this.addSegment(lsegchar, lsegchar - 127); + lsegchar -= 127; + i += 3; + } + this.buf32[i+0] = 0; + this.buf32[i+1] = 0; + this.buf32[i+2] = this.addSegment(lsegchar, 0) | 0x80; + this.buf32[TRIE1_SLOT] = i + 3 << 2; + return r; + } + + addSegment(lsegchar, lsegend) { + if ( lsegchar === 0 ) { return 0; } + let char1 = this.buf32[CHAR1_SLOT]; + const isegchar = char1 - this.buf32[CHAR0_SLOT]; + let i = lsegchar; + do { + this.buf[char1++] = this.buf[--i]; + } while ( i !== lsegend ); + this.buf32[CHAR1_SLOT] = char1; + return isegchar << 8 | lsegchar - lsegend; + } + + growBuf(trieGrow, charGrow) { + const char0 = Math.max( + roundToPageSize(this.buf32[TRIE1_SLOT] + trieGrow), + this.buf32[CHAR0_SLOT] + ); + const char1 = char0 + this.buf32[CHAR1_SLOT] - this.buf32[CHAR0_SLOT]; + const bufLen = Math.max( + roundToPageSize(char1 + charGrow), + this.buf.length + ); + this.resizeBuf(bufLen, char0); + } + + shrinkBuf() { + // Can't shrink WebAssembly.Memory + if ( this.wasmMemory !== null ) { return; } + const char0 = this.buf32[TRIE1_SLOT] + 24; + const char1 = char0 + this.buf32[CHAR1_SLOT] - this.buf32[CHAR0_SLOT]; + const bufLen = char1 + 256; + this.resizeBuf(bufLen, char0); + } + + resizeBuf(bufLen, char0) { + bufLen = roundToPageSize(bufLen); + if ( bufLen === this.buf.length && char0 === this.buf32[CHAR0_SLOT] ) { + return; + } + const charDataLen = this.buf32[CHAR1_SLOT] - this.buf32[CHAR0_SLOT]; + if ( this.wasmMemory !== null ) { + const pageCount = (bufLen >>> 16) - (this.buf.byteLength >>> 16); + if ( pageCount > 0 ) { + this.wasmMemory.grow(pageCount); + this.buf = new Uint8Array(this.wasmMemory.buffer); + this.buf32 = new Uint32Array(this.wasmMemory.buffer); + } + } else if ( bufLen !== this.buf.length ) { + const newBuf = new Uint8Array(bufLen); + newBuf.set( + new Uint8Array( + this.buf.buffer, + 0, + this.buf32[TRIE1_SLOT] + ), + 0 + ); + newBuf.set( + new Uint8Array( + this.buf.buffer, + this.buf32[CHAR0_SLOT], + charDataLen + ), + char0 + ); + this.buf = newBuf; + this.buf32 = new Uint32Array(this.buf.buffer); + this.buf32[CHAR0_SLOT] = char0; + this.buf32[CHAR1_SLOT] = char0 + charDataLen; + } + if ( char0 !== this.buf32[CHAR0_SLOT] ) { + this.buf.set( + new Uint8Array( + this.buf.buffer, + this.buf32[CHAR0_SLOT], + charDataLen + ), + char0 + ); + this.buf32[CHAR0_SLOT] = char0; + this.buf32[CHAR1_SLOT] = char0 + charDataLen; + } + } + + reallocateBuf(newSize) { + newSize = roundToPageSize(newSize); + if ( newSize === this.buf.length ) { return; } + if ( this.wasmMemory === null ) { + const newBuf = new Uint8Array(newSize); + newBuf.set( + newBuf.length < this.buf.length + ? this.buf.subarray(0, newBuf.length) + : this.buf + ); + this.buf = newBuf; + } else { + const growBy = + ((newSize + 0xFFFF) >>> 16) - (this.buf.length >>> 16); + if ( growBy <= 0 ) { return; } + this.wasmMemory.grow(growBy); + this.buf = new Uint8Array(this.wasmMemory.buffer); + } + this.buf32 = new Uint32Array(this.buf.buffer); + } +} + +HNTrieContainer.prototype.matches = HNTrieContainer.prototype.matchesJS; +HNTrieContainer.prototype.matchesWASM = null; + +HNTrieContainer.prototype.add = HNTrieContainer.prototype.addJS; +HNTrieContainer.prototype.addWASM = null; + +/******************************************************************************/ + +// Code below is to attempt to load a WASM module which implements: +// +// - HNTrieContainer.add() +// - HNTrieContainer.matches() +// +// The WASM module is entirely optional, the JS implementations will be +// used should the WASM module be unavailable for whatever reason. + +const getWasmModule = (( ) => { + let wasmModulePromise; + + return async function(wasmModuleFetcher, path) { + if ( wasmModulePromise instanceof Promise ) { + return wasmModulePromise; + } + + // The wasm module will work only if CPU is natively little-endian, + // as we use native uint32 array in our js code. + const uint32s = new Uint32Array(1); + const uint8s = new Uint8Array(uint32s.buffer); + uint32s[0] = 1; + if ( uint8s[0] !== 1 ) { return; } + + wasmModulePromise = wasmModuleFetcher(`${path}hntrie`).catch(reason => { + console.info(reason); + }); + + return wasmModulePromise; + }; +})(); + +/******************************************************************************/ + +export default HNTrieContainer; diff --git a/src/js/html-filtering.js b/src/js/html-filtering.js new file mode 100644 index 0000000..81d66ee --- /dev/null +++ b/src/js/html-filtering.js @@ -0,0 +1,465 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2017-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import logger from './logger.js'; +import µb from './background.js'; +import { sessionFirewall } from './filtering-engines.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; +import { entityFromDomain } from './uri-utils.js'; + +/******************************************************************************/ + +const pselectors = new Map(); +const duplicates = new Set(); + +const filterDB = new StaticExtFilteringHostnameDB(2); + +let acceptedCount = 0; +let discardedCount = 0; +let docRegister; + +const htmlFilteringEngine = { + get acceptedCount() { + return acceptedCount; + }, + get discardedCount() { + return discardedCount; + }, + getFilterCount() { + return filterDB.size; + }, +}; + +const regexFromString = (s, exact = false) => { + if ( s === '' ) { return /^/; } + const match = /^\/(.+)\/([i]?)$/.exec(s); + if ( match !== null ) { + return new RegExp(match[1], match[2] || undefined); + } + const reStr = s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return new RegExp(exact ? `^${reStr}$` : reStr, 'i'); +}; + +class PSelectorVoidTask { + constructor(task) { + console.info(`[uBO] HTML filtering: :${task[0]}() operator is not supported`); + } + transpose() { + } +} +class PSelectorHasTextTask { + constructor(task) { + this.needle = regexFromString(task[1]); + } + transpose(node, output) { + if ( this.needle.test(node.textContent) ) { + output.push(node); + } + } +} + +const PSelectorIfTask = class { + constructor(task) { + this.pselector = new PSelector(task[1]); + } + transpose(node, output) { + if ( this.pselector.test(node) === this.target ) { + output.push(node); + } + } +}; +PSelectorIfTask.prototype.target = true; + +class PSelectorIfNotTask extends PSelectorIfTask { +} +PSelectorIfNotTask.prototype.target = false; + +class PSelectorMinTextLengthTask { + constructor(task) { + this.min = task[1]; + } + transpose(node, output) { + if ( node.textContent.length >= this.min ) { + output.push(node); + } + } +} + +class PSelectorSpathTask { + constructor(task) { + this.spath = task[1]; + this.nth = /^(?:\s*[+~]|:)/.test(this.spath); + if ( this.nth ) { return; } + if ( /^\s*>/.test(this.spath) ) { + this.spath = `:scope ${this.spath.trim()}`; + } + } + transpose(node, output) { + const nodes = this.nth + ? PSelectorSpathTask.qsa(node, this.spath) + : node.querySelectorAll(this.spath); + for ( const node of nodes ) { + output.push(node); + } + } + // Helper method for other operators. + static qsa(node, selector) { + const parent = node.parentElement; + if ( parent === null ) { return []; } + let pos = 1; + for (;;) { + node = node.previousElementSibling; + if ( node === null ) { break; } + pos += 1; + } + return parent.querySelectorAll( + `:scope > :nth-child(${pos})${selector}` + ); + } +} + +class PSelectorUpwardTask { + constructor(task) { + const arg = task[1]; + if ( typeof arg === 'number' ) { + this.i = arg; + } else { + this.s = arg; + } + } + transpose(node, output) { + if ( this.s !== '' ) { + const parent = node.parentElement; + if ( parent === null ) { return; } + node = parent.closest(this.s); + if ( node === null ) { return; } + } else { + let nth = this.i; + for (;;) { + node = node.parentElement; + if ( node === null ) { return; } + nth -= 1; + if ( nth === 0 ) { break; } + } + } + output.push(node); + } +} +PSelectorUpwardTask.prototype.i = 0; +PSelectorUpwardTask.prototype.s = ''; + +class PSelectorXpathTask { + constructor(task) { + this.xpe = task[1]; + } + transpose(node, output) { + const xpr = docRegister.evaluate( + this.xpe, + node, + null, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null + ); + let j = xpr.snapshotLength; + while ( j-- ) { + const node = xpr.snapshotItem(j); + if ( node.nodeType === 1 ) { + output.push(node); + } + } + } +} + +class PSelector { + constructor(o) { + this.raw = o.raw; + this.selector = o.selector; + this.tasks = []; + if ( !o.tasks ) { return; } + for ( const task of o.tasks ) { + const ctor = this.operatorToTaskMap.get(task[0]) || PSelectorVoidTask; + const pselector = new ctor(task); + this.tasks.push(pselector); + } + } + prime(input) { + const root = input || docRegister; + if ( this.selector === '' ) { return [ root ]; } + if ( input !== docRegister && /^ ?[>+~]/.test(this.selector) ) { + return Array.from(PSelectorSpathTask.qsa(input, this.selector)); + } + return Array.from(root.querySelectorAll(this.selector)); + } + exec(input) { + let nodes = this.prime(input); + for ( const task of this.tasks ) { + if ( nodes.length === 0 ) { break; } + const transposed = []; + for ( const node of nodes ) { + task.transpose(node, transposed); + } + nodes = transposed; + } + return nodes; + } + test(input) { + const nodes = this.prime(input); + for ( const node of nodes ) { + let output = [ node ]; + for ( const task of this.tasks ) { + const transposed = []; + for ( const node of output ) { + task.transpose(node, transposed); + } + output = transposed; + if ( output.length === 0 ) { break; } + } + if ( output.length !== 0 ) { return true; } + } + return false; + } +} +PSelector.prototype.operatorToTaskMap = new Map([ + [ 'has', PSelectorIfTask ], + [ 'has-text', PSelectorHasTextTask ], + [ 'if', PSelectorIfTask ], + [ 'if-not', PSelectorIfNotTask ], + [ 'min-text-length', PSelectorMinTextLengthTask ], + [ 'not', PSelectorIfNotTask ], + [ 'nth-ancestor', PSelectorUpwardTask ], + [ 'spath', PSelectorSpathTask ], + [ 'upward', PSelectorUpwardTask ], + [ 'xpath', PSelectorXpathTask ], +]); + +function logOne(details, exception, selector) { + µb.filteringContext + .duplicate() + .fromTabId(details.tabId) + .setRealm('extended') + .setType('dom') + .setURL(details.url) + .setDocOriginFromURL(details.url) + .setFilter({ + source: 'extended', + raw: `${exception === 0 ? '##' : '#@#'}^${selector}` + }) + .toLogger(); +} + +function applyProceduralSelector(details, selector) { + let pselector = pselectors.get(selector); + if ( pselector === undefined ) { + pselector = new PSelector(JSON.parse(selector)); + pselectors.set(selector, pselector); + } + const nodes = pselector.exec(); + let modified = false; + for ( const node of nodes ) { + node.remove(); + modified = true; + } + if ( modified && logger.enabled ) { + logOne(details, 0, pselector.raw); + } + return modified; +} + +function applyCSSSelector(details, selector) { + const nodes = docRegister.querySelectorAll(selector); + let modified = false; + for ( const node of nodes ) { + node.remove(); + modified = true; + } + if ( modified && logger.enabled ) { + logOne(details, 0, selector); + } + return modified; +} + +function logError(writer, msg) { + logger.writeOne({ + realm: 'message', + type: 'error', + text: msg.replace('{who}', writer.properties.get('name') || '?') + }); +} + +htmlFilteringEngine.reset = function() { + filterDB.clear(); + pselectors.clear(); + duplicates.clear(); + acceptedCount = 0; + discardedCount = 0; +}; + +htmlFilteringEngine.freeze = function() { + duplicates.clear(); + filterDB.collectGarbage(); +}; + +htmlFilteringEngine.compile = function(parser, writer) { + const isException = parser.isException(); + const { raw, compiled } = parser.result; + if ( compiled === undefined ) { + return logError(writer, `Invalid HTML filter in {who}: ##${raw}`); + } + + writer.select('HTML_FILTERS'); + + // Only exception filters are allowed to be global. + if ( parser.hasOptions() === false ) { + if ( isException ) { + writer.push([ 64, '', 1, compiled ]); + } + return; + } + + const compiledFilters = []; + let hasOnlyNegated = true; + for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { + if ( bad ) { continue; } + let kind = isException ? 0b01 : 0b00; + if ( not ) { + kind ^= 0b01; + } else { + hasOnlyNegated = false; + } + if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) { + kind |= 0b10; + } + compiledFilters.push([ 64, hn, kind, compiled ]); + } + + // Not allowed since it's equivalent to forbidden generic HTML filters + if ( isException === false && hasOnlyNegated ) { + return logError(writer, `Invalid HTML filter in {who}: ##${raw}`); + } + + writer.pushMany(compiledFilters); +}; + +htmlFilteringEngine.fromCompiledContent = function(reader) { + // Don't bother loading filters if stream filtering is not supported. + if ( µb.canFilterResponseData === false ) { return; } + + reader.select('HTML_FILTERS'); + + while ( reader.next() ) { + acceptedCount += 1; + const fingerprint = reader.fingerprint(); + if ( duplicates.has(fingerprint) ) { + discardedCount += 1; + continue; + } + duplicates.add(fingerprint); + const args = reader.args(); + filterDB.store(args[1], args[2], args[3]); + } +}; + +htmlFilteringEngine.retrieve = function(fctxt) { + const plains = new Set(); + const procedurals = new Set(); + const exceptions = new Set(); + const retrieveSets = [ plains, exceptions, procedurals, exceptions ]; + + const hostname = fctxt.getHostname(); + filterDB.retrieve(hostname, retrieveSets); + + const domain = fctxt.getDomain(); + const entity = entityFromDomain(domain); + const hostnameEntity = entity !== '' + ? `${hostname.slice(0, -domain.length)}${entity}` + : '*'; + filterDB.retrieve(hostnameEntity, retrieveSets, 1); + + if ( plains.size === 0 && procedurals.size === 0 ) { return; } + + // https://github.com/gorhill/uBlock/issues/2835 + // Do not filter if the site is under an `allow` rule. + if ( + µb.userSettings.advancedUserEnabled && + sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2 + ) { + return; + } + + const out = { plains, procedurals }; + + if ( exceptions.size === 0 ) { + return out; + } + + for ( const selector of exceptions ) { + if ( plains.has(selector) ) { + plains.delete(selector); + logOne(fctxt, 1, selector); + continue; + } + if ( procedurals.has(selector) ) { + procedurals.delete(selector); + logOne(fctxt, 1, JSON.parse(selector).raw); + continue; + } + } + + if ( plains.size !== 0 || procedurals.size !== 0 ) { + return out; + } +}; + +htmlFilteringEngine.apply = function(doc, details, selectors) { + docRegister = doc; + let modified = false; + for ( const selector of selectors.plains ) { + if ( applyCSSSelector(details, selector) ) { + modified = true; + } + } + for ( const selector of selectors.procedurals ) { + if ( applyProceduralSelector(details, selector) ) { + modified = true; + } + } + docRegister = undefined; + return modified; +}; + +htmlFilteringEngine.toSelfie = function() { + return filterDB.toSelfie(); +}; + +htmlFilteringEngine.fromSelfie = function(selfie) { + filterDB.fromSelfie(selfie); + pselectors.clear(); +}; + +/******************************************************************************/ + +export default htmlFilteringEngine; + +/******************************************************************************/ diff --git a/src/js/httpheader-filtering.js b/src/js/httpheader-filtering.js new file mode 100644 index 0000000..522ea21 --- /dev/null +++ b/src/js/httpheader-filtering.js @@ -0,0 +1,213 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2021-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import logger from './logger.js'; +import µb from './background.js'; +import { entityFromDomain } from './uri-utils.js'; +import { sessionFirewall } from './filtering-engines.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; +import * as sfp from './static-filtering-parser.js'; + +/******************************************************************************/ + +const duplicates = new Set(); +const filterDB = new StaticExtFilteringHostnameDB(1); + +const $headers = new Set(); +const $exceptions = new Set(); + +let acceptedCount = 0; +let discardedCount = 0; + +const headerIndexFromName = function(name, headers, start = 0) { + for ( let i = start; i < headers.length; i++ ) { + if ( headers[i].name.toLowerCase() !== name ) { continue; } + return i; + } + return -1; +}; + +const logOne = function(isException, token, fctxt) { + fctxt.duplicate() + .setRealm('extended') + .setType('header') + .setFilter({ + modifier: true, + result: isException ? 2 : 1, + source: 'extended', + raw: `${(isException ? '#@#' : '##')}^responseheader(${token})` + }) + .toLogger(); +}; + +const httpheaderFilteringEngine = { + get acceptedCount() { + return acceptedCount; + }, + get discardedCount() { + return discardedCount; + } +}; + +httpheaderFilteringEngine.reset = function() { + filterDB.clear(); + duplicates.clear(); + acceptedCount = 0; + discardedCount = 0; +}; + +httpheaderFilteringEngine.freeze = function() { + duplicates.clear(); + filterDB.collectGarbage(); +}; + +httpheaderFilteringEngine.compile = function(parser, writer) { + writer.select('HTTPHEADER_FILTERS'); + + const isException = parser.isException(); + const root = parser.getBranchFromType(sfp.NODE_TYPE_EXT_PATTERN_RESPONSEHEADER); + const headerName = parser.getNodeString(root); + + // Tokenless is meaningful only for exception filters. + if ( headerName === '' && isException === false ) { return; } + + // Only exception filters are allowed to be global. + if ( parser.hasOptions() === false ) { + if ( isException ) { + writer.push([ 64, '', 1, headerName ]); + } + return; + } + + // https://github.com/gorhill/uBlock/issues/3375 + // Ignore instances of exception filter with negated hostnames, + // because there is no way to create an exception to an exception. + + for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { + if ( bad ) { continue; } + let kind = 0; + if ( isException ) { + if ( not ) { continue; } + kind |= 1; + } else if ( not ) { + kind |= 1; + } + writer.push([ 64, hn, kind, headerName ]); + } +}; + +// 01234567890123456789 +// responseheader(name) +// ^ ^ +// 15 -1 + +httpheaderFilteringEngine.fromCompiledContent = function(reader) { + reader.select('HTTPHEADER_FILTERS'); + + while ( reader.next() ) { + acceptedCount += 1; + const fingerprint = reader.fingerprint(); + if ( duplicates.has(fingerprint) ) { + discardedCount += 1; + continue; + } + duplicates.add(fingerprint); + const args = reader.args(); + if ( args.length < 4 ) { continue; } + filterDB.store(args[1], args[2], args[3]); + } +}; + +httpheaderFilteringEngine.apply = function(fctxt, headers) { + if ( filterDB.size === 0 ) { return; } + + const hostname = fctxt.getHostname(); + if ( hostname === '' ) { return; } + + const domain = fctxt.getDomain(); + let entity = entityFromDomain(domain); + if ( entity !== '' ) { + entity = `${hostname.slice(0, -domain.length)}${entity}`; + } else { + entity = '*'; + } + + $headers.clear(); + $exceptions.clear(); + + filterDB.retrieve(hostname, [ $headers, $exceptions ]); + filterDB.retrieve(entity, [ $headers, $exceptions ], 1); + if ( $headers.size === 0 ) { return; } + + // https://github.com/gorhill/uBlock/issues/2835 + // Do not filter response headers if the site is under an `allow` rule. + if ( + µb.userSettings.advancedUserEnabled && + sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2 + ) { + return; + } + + const hasGlobalException = $exceptions.has(''); + + let modified = false; + let i = 0; + + for ( const name of $headers ) { + const isExcepted = hasGlobalException || $exceptions.has(name); + if ( isExcepted ) { + if ( logger.enabled ) { + logOne(true, hasGlobalException ? '' : name, fctxt); + } + continue; + } + i = 0; + for (;;) { + i = headerIndexFromName(name, headers, i); + if ( i === -1 ) { break; } + headers.splice(i, 1); + if ( logger.enabled ) { + logOne(false, name, fctxt); + } + modified = true; + } + } + + return modified; +}; + +httpheaderFilteringEngine.toSelfie = function() { + return filterDB.toSelfie(); +}; + +httpheaderFilteringEngine.fromSelfie = function(selfie) { + filterDB.fromSelfie(selfie); +}; + +/******************************************************************************/ + +export default httpheaderFilteringEngine; + +/******************************************************************************/ diff --git a/src/js/i18n.js b/src/js/i18n.js new file mode 100644 index 0000000..6302b35 --- /dev/null +++ b/src/js/i18n.js @@ -0,0 +1,346 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +const i18n = + self.browser instanceof Object && + self.browser instanceof Element === false + ? self.browser.i18n + : self.chrome.i18n; + +/******************************************************************************/ + +function i18n$(...args) { + return i18n.getMessage(...args); +} + +/******************************************************************************/ + +const isBackgroundProcess = document.title === 'uBlock Origin Background Page'; + +if ( isBackgroundProcess !== true ) { + + // http://www.w3.org/International/questions/qa-scripts#directions + document.body.setAttribute( + 'dir', + ['ar', 'he', 'fa', 'ps', 'ur'].indexOf(i18n$('@@ui_locale')) !== -1 + ? 'rtl' + : 'ltr' + ); + + // https://github.com/gorhill/uBlock/issues/2084 + // Anything else than , , , , , and will + // be rendered as plain text. + // For , only href attribute must be present, and it MUST starts with + // `https://`, and includes no single- or double-quotes. + // No HTML entities are allowed, there is code to handle existing HTML + // entities already present in translation files until they are all gone. + + const allowedTags = new Set([ + 'a', + 'b', + 'code', + 'em', + 'i', + 'span', + 'u', + ]); + + const expandHtmlEntities = (( ) => { + const entities = new Map([ + // TODO: Remove quote entities once no longer present in translation + // files. Other entities must stay. + [ '­', '\u00AD' ], + [ '“', '“' ], + [ '”', '”' ], + [ '‘', '‘' ], + [ '’', '’' ], + [ '<', '<' ], + [ '>', '>' ], + ]); + const decodeEntities = match => { + return entities.get(match) || match; + }; + return function(text) { + if ( text.indexOf('&') !== -1 ) { + text = text.replace(/&[a-z]+;/g, decodeEntities); + } + return text; + }; + })(); + + const safeTextToTextNode = function(text) { + return document.createTextNode(expandHtmlEntities(text)); + }; + + const sanitizeElement = function(node) { + if ( allowedTags.has(node.localName) === false ) { return null; } + node.removeAttribute('style'); + let child = node.firstElementChild; + while ( child !== null ) { + const next = child.nextElementSibling; + if ( sanitizeElement(child) === null ) { + child.remove(); + } + child = next; + } + return node; + }; + + const safeTextToDOM = function(text, parent) { + if ( text === '' ) { return; } + + // Fast path (most common). + if ( text.indexOf('<') === -1 ) { + const toInsert = safeTextToTextNode(text); + let toReplace = parent.childCount !== 0 + ? parent.firstChild + : null; + while ( toReplace !== null ) { + if ( toReplace.nodeType === 3 && toReplace.nodeValue === '_' ) { + break; + } + toReplace = toReplace.nextSibling; + } + if ( toReplace !== null ) { + parent.replaceChild(toInsert, toReplace); + } else { + parent.appendChild(toInsert); + } + return; + } + + // Slow path. + // `

` no longer allowed. Code below can be removed once all

's are + // gone from translation files. + text = text.replace(/^

|<\/p>/g, '') + .replace(/

/g, '\n\n'); + // Parse allowed HTML tags. + const domParser = new DOMParser(); + const parsedDoc = domParser.parseFromString(text, 'text/html'); + let node = parsedDoc.body.firstChild; + while ( node !== null ) { + const next = node.nextSibling; + switch ( node.nodeType ) { + case 1: // element + if ( sanitizeElement(node) === null ) { break; } + parent.appendChild(node); + break; + case 3: // text + parent.appendChild(node); + break; + default: + break; + } + node = next; + } + }; + + i18n.safeTemplateToDOM = function(id, dict, parent) { + if ( parent === undefined ) { + parent = document.createDocumentFragment(); + } + let textin = i18n$(id); + if ( textin === '' ) { + return parent; + } + if ( textin.indexOf('{{') === -1 ) { + safeTextToDOM(textin, parent); + return parent; + } + const re = /\{\{\w+\}\}/g; + let textout = ''; + for (;;) { + let match = re.exec(textin); + if ( match === null ) { + textout += textin; + break; + } + textout += textin.slice(0, match.index); + let prop = match[0].slice(2, -2); + if ( dict.hasOwnProperty(prop) ) { + textout += dict[prop].replace(//g, '>'); + } else { + textout += prop; + } + textin = textin.slice(re.lastIndex); + } + safeTextToDOM(textout, parent); + return parent; + }; + + // Helper to deal with the i18n'ing of HTML files. + i18n.render = function(context) { + const docu = document; + const root = context || docu; + + for ( const elem of root.querySelectorAll('[data-i18n]') ) { + let text = i18n$(elem.getAttribute('data-i18n')); + if ( !text ) { continue; } + if ( text.indexOf('{{') === -1 ) { + safeTextToDOM(text, elem); + continue; + } + // Handle selector-based placeholders: these placeholders tell where + // existing child DOM element are to be positioned relative to the + // localized text nodes. + const parts = text.split(/(\{\{[^}]+\}\})/); + const fragment = document.createDocumentFragment(); + let textBefore = ''; + for ( let part of parts ) { + if ( part === '' ) { continue; } + if ( part.startsWith('{{') && part.endsWith('}}') ) { + // TODO: remove detection of ':' once it no longer appears + // in translation files. + const pos = part.indexOf(':'); + if ( pos !== -1 ) { + part = part.slice(0, pos) + part.slice(-2); + } + const selector = part.slice(2, -2); + let node; + // Ideally, the i18n strings explicitly refer to the + // class of the element to insert. However for now we + // will create a class from what is currently found in + // the placeholder and first try to lookup the resulting + // selector. This way we don't have to revisit all + // translations just for the sake of declaring the proper + // selector in the placeholder field. + if ( selector.charCodeAt(0) !== 0x2E /* '.' */ ) { + node = elem.querySelector(`.${selector}`); + } + if ( node instanceof Element === false ) { + node = elem.querySelector(selector); + } + if ( node instanceof Element ) { + safeTextToDOM(textBefore, fragment); + fragment.appendChild(node); + textBefore = ''; + continue; + } + } + textBefore += part; + } + if ( textBefore !== '' ) { + safeTextToDOM(textBefore, fragment); + } + elem.appendChild(fragment); + } + + for ( const elem of root.querySelectorAll('[data-i18n-title]') ) { + const text = i18n$(elem.getAttribute('data-i18n-title')); + if ( !text ) { continue; } + elem.setAttribute('title', expandHtmlEntities(text)); + } + + for ( const elem of root.querySelectorAll('[placeholder]') ) { + const text = i18n$(elem.getAttribute('placeholder')); + if ( text === '' ) { continue; } + elem.setAttribute('placeholder', text); + } + + for ( const elem of root.querySelectorAll('[data-i18n-tip]') ) { + const text = i18n$(elem.getAttribute('data-i18n-tip')) + .replace(/
/g, '\n') + .replace(/\n{3,}/g, '\n\n'); + elem.setAttribute('data-tip', text); + if ( elem.getAttribute('aria-label') === 'data-tip' ) { + elem.setAttribute('aria-label', text); + } + } + }; + + i18n.renderElapsedTimeToString = function(tstamp) { + let value = (Date.now() - tstamp) / 60000; + if ( value < 2 ) { + return i18n$('elapsedOneMinuteAgo'); + } + if ( value < 60 ) { + return i18n$('elapsedManyMinutesAgo').replace('{{value}}', Math.floor(value).toLocaleString()); + } + value /= 60; + if ( value < 2 ) { + return i18n$('elapsedOneHourAgo'); + } + if ( value < 24 ) { + return i18n$('elapsedManyHoursAgo').replace('{{value}}', Math.floor(value).toLocaleString()); + } + value /= 24; + if ( value < 2 ) { + return i18n$('elapsedOneDayAgo'); + } + return i18n$('elapsedManyDaysAgo').replace('{{value}}', Math.floor(value).toLocaleString()); + }; + + const unicodeFlagToImageSrc = new Map([ + [ '🇦🇱', 'al' ], [ '🇦🇷', 'ar' ], [ '🇦🇹', 'at' ], [ '🇧🇦', 'ba' ], + [ '🇧🇬', 'bg' ], [ '🇧🇷', 'br' ], [ '🇨🇦', 'ca' ], [ '🇨🇭', 'ch' ], + [ '🇨🇳', 'cn' ], [ '🇨🇴', 'co' ], [ '🇨🇾', 'cy' ], [ '🇨🇿', 'cz' ], + [ '🇩🇪', 'de' ], [ '🇩🇰', 'dk' ], [ '🇩🇿', 'dz' ], [ '🇪🇪', 'ee' ], + [ '🇪🇬', 'eg' ], [ '🇪🇸', 'es' ], [ '🇫🇮', 'fi' ], [ '🇫🇴', 'fo' ], + [ '🇫🇷', 'fr' ], [ '🇬🇷', 'gr' ], [ '🇭🇷', 'hr' ], [ '🇭🇺', 'hu' ], + [ '🇮🇩', 'id' ], [ '🇮🇱', 'il' ], [ '🇮🇳', 'in' ], [ '🇮🇷', 'ir' ], + [ '🇮🇸', 'is' ], [ '🇮🇹', 'it' ], [ '🇯🇵', 'jp' ], [ '🇰🇷', 'kr' ], + [ '🇰🇿', 'kz' ], [ '🇱🇰', 'lk' ], [ '🇱🇹', 'lt' ], [ '🇱🇻', 'lv' ], + [ '🇲🇦', 'ma' ], [ '🇲🇩', 'md' ], [ '🇲🇰', 'mk' ], [ '🇲🇽', 'mx' ], + [ '🇲🇾', 'my' ], [ '🇳🇱', 'nl' ], [ '🇳🇴', 'no' ], [ '🇳🇵', 'np' ], + [ '🇵🇱', 'pl' ], [ '🇵🇹', 'pt' ], [ '🇷🇴', 'ro' ], [ '🇷🇸', 'rs' ], + [ '🇷🇺', 'ru' ], [ '🇸🇦', 'sa' ], [ '🇸🇮', 'si' ], [ '🇸🇰', 'sk' ], + [ '🇸🇪', 'se' ], [ '🇸🇷', 'sr' ], [ '🇹🇭', 'th' ], [ '🇹🇯', 'tj' ], + [ '🇹🇼', 'tw' ], [ '🇹🇷', 'tr' ], [ '🇺🇦', 'ua' ], [ '🇺🇿', 'uz' ], + [ '🇻🇳', 'vn' ], [ '🇽🇰', 'xk' ], + ]); + const reUnicodeFlags = new RegExp( + Array.from(unicodeFlagToImageSrc).map(a => a[0]).join('|'), + 'gu' + ); + i18n.patchUnicodeFlags = function(text) { + const fragment = document.createDocumentFragment(); + let i = 0; + for (;;) { + const match = reUnicodeFlags.exec(text); + if ( match === null ) { break; } + if ( match.index > i ) { + fragment.append(text.slice(i, match.index)); + } + const img = document.createElement('img'); + const countryCode = unicodeFlagToImageSrc.get(match[0]); + img.src = `/img/flags-of-the-world/${countryCode}.png`; + img.title = countryCode; + img.classList.add('countryFlag'); + fragment.append(img, '\u200A'); + i = reUnicodeFlags.lastIndex; + } + if ( i < text.length ) { + fragment.append(text.slice(i)); + } + return fragment; + }; + + i18n.render(); +} + +/******************************************************************************/ + +export { i18n, i18n$ }; diff --git a/src/js/logger-ui-inspector.js b/src/js/logger-ui-inspector.js new file mode 100644 index 0000000..092baf8 --- /dev/null +++ b/src/js/logger-ui-inspector.js @@ -0,0 +1,710 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +/* globals browser */ + +'use strict'; + +import { dom, qs$, qsa$ } from './dom.js'; + +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +const logger = self.logger; +const showdomButton = qs$('#showdom'); +const inspector = qs$('#domInspector'); +const domTree = qs$('#domTree'); +const filterToIdMap = new Map(); + +let inspectedTabId = 0; +let inspectedURL = ''; +let inspectedHostname = ''; +let uidGenerator = 1; + +/******************************************************************************* + * + * How it works: + * + * 1. The logger/inspector is enabled from the logger window + * + * 2. The inspector content script is injected in the root frame of the tab + * currently selected in the logger + * + * 3. The inspector content script asks the logger/inspector to establish + * a two-way communication channel + * + * 3. The inspector content script embed an inspector frame in the document + * being inspected and waits for the inspector frame to be fully loaded + * + * 4. The inspector content script sends a messaging port object to the + * embedded inspector frame for a two-way communication channel between + * the inspector frame and the inspector content script + * + * 5. The inspector content script sends dom information to the + * logger/inspector + * + * */ + +const contentInspectorChannel = (( ) => { + let bcChannel; + let toContentPort; + + const start = ( ) => { + bcChannel = new globalThis.BroadcastChannel('contentInspectorChannel'); + bcChannel.onmessage = ev => { + const msg = ev.data || {}; + connect(msg.tabId, msg.frameId); + }; + browser.webNavigation.onDOMContentLoaded.addListener(onContentLoaded); + }; + + const shutdown = ( ) => { + browser.webNavigation.onDOMContentLoaded.removeListener(onContentLoaded); + disconnect(); + bcChannel.close(); + bcChannel.onmessage = null; + bcChannel = undefined; + }; + + const connect = (tabId, frameId) => { + disconnect(); + try { + toContentPort = browser.tabs.connect(tabId, { frameId }); + toContentPort.onMessage.addListener(onContentMessage); + toContentPort.onDisconnect.addListener(onContentDisconnect); + } catch(_) { + } + }; + + const disconnect = ( ) => { + if ( toContentPort === undefined ) { return; } + toContentPort.onMessage.removeListener(onContentMessage); + toContentPort.onDisconnect.removeListener(onContentDisconnect); + toContentPort.disconnect(); + toContentPort = undefined; + }; + + const send = msg => { + if ( toContentPort === undefined ) { return; } + toContentPort.postMessage(msg); + }; + + const onContentMessage = msg => { + if ( msg.what === 'domLayoutFull' ) { + inspectedURL = msg.url; + inspectedHostname = msg.hostname; + renderDOMFull(msg); + } else if ( msg.what === 'domLayoutIncremental' ) { + renderDOMIncremental(msg); + } + }; + + const onContentDisconnect = ( ) => { + disconnect(); + }; + + const onContentLoaded = details => { + if ( details.tabId !== inspectedTabId ) { return; } + if ( details.frameId !== 0 ) { return; } + disconnect(); + injectInspector(); + }; + + return { start, disconnect, send, shutdown }; +})(); + +/******************************************************************************/ + +const nodeFromDomEntry = entry => { + const li = document.createElement('li'); + dom.attr(li, 'id', entry.nid); + // expander/collapser + li.appendChild(document.createElement('span')); + // selector + let node = document.createElement('code'); + node.textContent = entry.sel; + li.appendChild(node); + // descendant count + let value = entry.cnt || 0; + node = document.createElement('span'); + node.textContent = value !== 0 ? value.toLocaleString() : ''; + dom.attr(node, 'data-cnt', value); + li.appendChild(node); + // cosmetic filter + if ( entry.filter === undefined ) { + return li; + } + node = document.createElement('code'); + dom.cl.add(node, 'filter'); + value = filterToIdMap.get(entry.filter); + if ( value === undefined ) { + value = `${uidGenerator}`; + filterToIdMap.set(entry.filter, value); + uidGenerator += 1; + } + dom.attr(node, 'data-filter-id', value); + node.textContent = entry.filter; + li.appendChild(node); + dom.cl.add(li, 'isCosmeticHide'); + return li; +}; + +/******************************************************************************/ + +const appendListItem = (ul, li) => { + ul.appendChild(li); + // Ancestor nodes of a node which is affected by a cosmetic filter will + // be marked as "containing cosmetic filters", for user convenience. + if ( dom.cl.has(li, 'isCosmeticHide') === false ) { return; } + for (;;) { + li = li.parentElement.parentElement; + if ( li === null ) { break; } + dom.cl.add(li, 'hasCosmeticHide'); + } +}; + +/******************************************************************************/ + +const renderDOMFull = response => { + const domTreeParent = domTree.parentElement; + let ul = domTreeParent.removeChild(domTree); + logger.removeAllChildren(domTree); + + filterToIdMap.clear(); + + let lvl = 0; + let li; + for ( const entry of response.layout ) { + if ( entry.lvl === lvl ) { + li = nodeFromDomEntry(entry); + appendListItem(ul, li); + continue; + } + if ( entry.lvl > lvl ) { + ul = document.createElement('ul'); + li.appendChild(ul); + dom.cl.add(li, 'branch'); + li = nodeFromDomEntry(entry); + appendListItem(ul, li); + lvl = entry.lvl; + continue; + } + // entry.lvl < lvl + while ( entry.lvl < lvl ) { + ul = li.parentNode; + li = ul.parentNode; + ul = li.parentNode; + lvl -= 1; + } + li = nodeFromDomEntry(entry); + appendListItem(ul, li); + } + while ( ul.parentNode !== null ) { + ul = ul.parentNode; + } + dom.cl.add(ul.firstElementChild, 'show'); + + domTreeParent.appendChild(domTree); +}; + +/******************************************************************************/ + +const patchIncremental = (from, delta) => { + let li = from.parentElement.parentElement; + const patchCosmeticHide = delta >= 0 && + dom.cl.has(from, 'isCosmeticHide') && + dom.cl.has(li, 'hasCosmeticHide') === false; + // Include descendants count when removing a node + if ( delta < 0 ) { + delta -= countFromNode(from); + } + for ( ; li.localName === 'li'; li = li.parentElement.parentElement ) { + const span = li.children[2]; + if ( delta !== 0 ) { + const cnt = countFromNode(li) + delta; + span.textContent = cnt !== 0 ? cnt.toLocaleString() : ''; + dom.attr(span, 'data-cnt', cnt); + } + if ( patchCosmeticHide ) { + dom.cl.add(li, 'hasCosmeticHide'); + } + } +}; + +/******************************************************************************/ + +const renderDOMIncremental = response => { + // Process each journal entry: + // 1 = node added + // -1 = node removed + const nodes = new Map(response.nodes); + let li = null; + let ul = null; + for ( const entry of response.journal ) { + // Remove node + if ( entry.what === -1 ) { + li = qs$(`#${entry.nid}`); + if ( li === null ) { continue; } + patchIncremental(li, -1); + li.parentNode.removeChild(li); + continue; + } + // Modify node + if ( entry.what === 0 ) { + // TODO: update selector/filter + continue; + } + // Add node as sibling + if ( entry.what === 1 && entry.l ) { + const previous = qs$(`#${entry.l}`); + // This should not happen + if ( previous === null ) { + // throw new Error('No left sibling!?'); + continue; + } + ul = previous.parentElement; + li = nodeFromDomEntry(nodes.get(entry.nid)); + ul.insertBefore(li, previous.nextElementSibling); + patchIncremental(li, 1); + continue; + } + // Add node as child + if ( entry.what === 1 && entry.u ) { + li = qs$(`#${entry.u}`); + // This should not happen + if ( li === null ) { + // throw new Error('No parent!?'); + continue; + } + ul = qs$(li, 'ul'); + if ( ul === null ) { + ul = document.createElement('ul'); + li.appendChild(ul); + dom.cl.add(li, 'branch'); + } + li = nodeFromDomEntry(nodes.get(entry.nid)); + ul.appendChild(li); + patchIncremental(li, 1); + continue; + } + } +}; + +/******************************************************************************/ + +const countFromNode = li => { + const span = li.children[2]; + const cnt = parseInt(dom.attr(span, 'data-cnt'), 10); + return isNaN(cnt) ? 0 : cnt; +}; + +/******************************************************************************/ + +const selectorFromNode = node => { + let selector = ''; + while ( node !== null ) { + if ( node.localName === 'li' ) { + const code = qs$(node, 'code'); + if ( code !== null ) { + selector = `${code.textContent} > ${selector}`; + if ( selector.includes('#') ) { break; } + } + } + node = node.parentElement; + } + return selector.slice(0, -3); +}; + +/******************************************************************************/ + +const selectorFromFilter = node => { + while ( node !== null ) { + if ( node.localName === 'li' ) { + const code = qs$(node, 'code:nth-of-type(2)'); + if ( code !== null ) { + return code.textContent; + } + } + node = node.parentElement; + } + return ''; +}; + +/******************************************************************************/ + +const nidFromNode = node => { + let li = node; + while ( li !== null ) { + if ( li.localName === 'li' ) { + return li.id || ''; + } + li = li.parentElement; + } + return ''; +}; + +/******************************************************************************/ + +const startDialog = (( ) => { + let dialog; + let textarea; + let hideSelectors = []; + let unhideSelectors = []; + + const parse = function() { + hideSelectors = []; + unhideSelectors = []; + + const re = /^([^#]*)(#@?#)(.+)$/; + for ( let line of textarea.value.split(/\s*\n\s*/) ) { + line = line.trim(); + if ( line === '' || line.charAt(0) === '!' ) { continue; } + const matches = re.exec(line); + if ( matches === null || matches.length !== 4 ) { continue; } + if ( inspectedHostname.lastIndexOf(matches[1]) === -1 ) { + continue; + } + if ( matches[2] === '##' ) { + hideSelectors.push(matches[3]); + } else { + unhideSelectors.push(matches[3]); + } + } + + showCommitted(); + }; + + const inputTimer = vAPI.defer.create(parse); + + const onInputChanged = ( ) => { + inputTimer.on(743); + }; + + const onClicked = function(ev) { + const target = ev.target; + + ev.stopPropagation(); + + if ( target.id === 'createCosmeticFilters' ) { + vAPI.messaging.send('loggerUI', { + what: 'createUserFilter', + filters: textarea.value, + }); + // Force a reload for the new cosmetic filter(s) to take effect + vAPI.messaging.send('loggerUI', { + what: 'reloadTab', + tabId: inspectedTabId, + }); + return stop(); + } + }; + + const showCommitted = function() { + contentInspectorChannel.send({ + what: 'showCommitted', + hide: hideSelectors.join(',\n'), + unhide: unhideSelectors.join(',\n') + }); + }; + + const showInteractive = function() { + contentInspectorChannel.send({ + what: 'showInteractive', + hide: hideSelectors.join(',\n'), + unhide: unhideSelectors.join(',\n') + }); + }; + + const start = function() { + dialog = logger.modalDialog.create('#cosmeticFilteringDialog', stop); + textarea = qs$(dialog, 'textarea'); + hideSelectors = []; + for ( const node of qsa$(domTree, 'code.off') ) { + if ( dom.cl.has(node, 'filter') ) { continue; } + hideSelectors.push(selectorFromNode(node)); + } + const taValue = []; + for ( const selector of hideSelectors ) { + taValue.push(inspectedHostname + '##' + selector); + } + const ids = new Set(); + for ( const node of qsa$(domTree, 'code.filter.off') ) { + const id = dom.attr(node, 'data-filter-id'); + if ( ids.has(id) ) { continue; } + ids.add(id); + unhideSelectors.push(node.textContent); + taValue.push(inspectedHostname + '#@#' + node.textContent); + } + textarea.value = taValue.join('\n'); + textarea.addEventListener('input', onInputChanged); + dialog.addEventListener('click', onClicked, true); + showCommitted(); + logger.modalDialog.show(); + }; + + const stop = function() { + inputTimer.off(); + showInteractive(); + textarea.removeEventListener('input', onInputChanged); + dialog.removeEventListener('click', onClicked, true); + dialog = undefined; + textarea = undefined; + hideSelectors = []; + unhideSelectors = []; + }; + + return start; +})(); + +/******************************************************************************/ + +const onClicked = ev => { + ev.stopPropagation(); + + if ( inspectedTabId === 0 ) { return; } + + const target = ev.target; + const parent = target.parentElement; + + // Expand/collapse branch + if ( + target.localName === 'span' && + parent instanceof HTMLLIElement && + dom.cl.has(parent, 'branch') && + target === parent.firstElementChild + ) { + const state = dom.cl.toggle(parent, 'show'); + if ( !state ) { + for ( const node of qsa$(parent, '.branch') ) { + dom.cl.remove(node, 'show'); + } + } + return; + } + + // Not a node or filter + if ( target.localName !== 'code' ) { return; } + + // Toggle cosmetic filter + if ( dom.cl.has(target, 'filter') ) { + contentInspectorChannel.send({ + what: 'toggleFilter', + original: false, + target: dom.cl.toggle(target, 'off'), + selector: selectorFromNode(target), + filter: selectorFromFilter(target), + nid: nidFromNode(target) + }); + dom.cl.toggle( + qsa$(inspector, `[data-filter-id="${dom.attr(target, 'data-filter-id')}"]`), + 'off', + dom.cl.has(target, 'off') + ); + } + // Toggle node + else { + contentInspectorChannel.send({ + what: 'toggleNodes', + original: true, + target: dom.cl.toggle(target, 'off') === false, + selector: selectorFromNode(target), + nid: nidFromNode(target) + }); + } + + const cantCreate = qs$(domTree, '.off') === null; + dom.cl.toggle(qs$(inspector, '.permatoolbar .revert'), 'disabled', cantCreate); + dom.cl.toggle(qs$(inspector, '.permatoolbar .commit'), 'disabled', cantCreate); +}; + +/******************************************************************************/ + +const onMouseOver = (( ) => { + let mouseoverTarget = null; + + const mouseoverTimer = vAPI.defer.create(( ) => { + contentInspectorChannel.send({ + what: 'highlightOne', + selector: selectorFromNode(mouseoverTarget), + nid: nidFromNode(mouseoverTarget), + scrollTo: true + }); + }); + + return ev => { + if ( inspectedTabId === 0 ) { return; } + // Convenience: skip real-time highlighting if shift key is pressed. + if ( ev.shiftKey ) { return; } + // Find closest `li` + const target = ev.target.closest('li'); + if ( target === mouseoverTarget ) { return; } + mouseoverTarget = target; + mouseoverTimer.on(50); + }; +})(); + +/******************************************************************************/ + +const currentTabId = ( ) => { + if ( dom.cl.has(showdomButton, 'active') === false ) { return 0; } + return logger.tabIdFromPageSelector(); +}; + +/******************************************************************************/ + +const injectInspector = (( ) => { + const timer = vAPI.defer.create(( ) => { + const tabId = currentTabId(); + if ( tabId <= 0 ) { return; } + inspectedTabId = tabId; + vAPI.messaging.send('loggerUI', { + what: 'scriptlet', + tabId, + scriptlet: 'dom-inspector', + }); + }); + return ( ) => { + shutdownInspector(); + timer.offon(353); + }; +})(); + +/******************************************************************************/ + +const shutdownInspector = ( ) => { + contentInspectorChannel.disconnect(); + logger.removeAllChildren(domTree); + dom.cl.remove(inspector, 'vExpanded'); + inspectedTabId = 0; +}; + +/******************************************************************************/ + +const onTabIdChanged = ( ) => { + const tabId = currentTabId(); + if ( tabId <= 0 ) { + return toggleOff(); + } + if ( inspectedTabId !== tabId ) { + injectInspector(); + } +}; + +/******************************************************************************/ + +const toggleVExpandView = ( ) => { + const branches = qsa$('#domTree li.branch.show > ul > li.branch:not(.show)'); + for ( const branch of branches ) { + dom.cl.add(branch, 'show'); + } +}; + +const toggleVCompactView = ( ) => { + const branches = qsa$('#domTree li.branch.show > ul > li:not(.show)'); + const tohideSet = new Set(); + for ( const branch of branches ) { + const node = branch.closest('li.branch.show'); + if ( node.id === 'n1' ) { continue; } + tohideSet.add(node); + } + const tohideList = Array.from(tohideSet); + let i = tohideList.length - 1; + while ( i > 0 ) { + if ( tohideList[i-1].contains(tohideList[i]) ) { + tohideList.splice(i-1, 1); + } else if ( tohideList[i].contains(tohideList[i-1]) ) { + tohideList.splice(i, 1); + } + i -= 1; + } + for ( const node of tohideList ) { + dom.cl.remove(node, 'show'); + } +}; + +const toggleHCompactView = ( ) => { + dom.cl.toggle(inspector, 'hCompact'); +}; + +/******************************************************************************/ + +const revert = ( ) => { + dom.cl.remove('#domTree .off', 'off'); + contentInspectorChannel.send({ what: 'resetToggledNodes' }); + dom.cl.add(qs$(inspector, '.permatoolbar .revert'), 'disabled'); + dom.cl.add(qs$(inspector, '.permatoolbar .commit'), 'disabled'); +}; + +/******************************************************************************/ + +const toggleOn = ( ) => { + dom.cl.add('#inspectors', 'dom'); + window.addEventListener('beforeunload', toggleOff); + document.addEventListener('tabIdChanged', onTabIdChanged); + domTree.addEventListener('click', onClicked, true); + domTree.addEventListener('mouseover', onMouseOver, true); + dom.on('#domInspector .vExpandToggler', 'click', toggleVExpandView); + dom.on('#domInspector .vCompactToggler', 'click', toggleVCompactView); + dom.on('#domInspector .hCompactToggler', 'click', toggleHCompactView); + dom.on('#domInspector .permatoolbar .revert', 'click', revert); + dom.on('#domInspector .permatoolbar .commit', 'click', startDialog); + contentInspectorChannel.start(); + injectInspector(); +}; + +/******************************************************************************/ + +const toggleOff = ( ) => { + dom.cl.remove(showdomButton, 'active'); + dom.cl.remove('#inspectors', 'dom'); + shutdownInspector(); + window.removeEventListener('beforeunload', toggleOff); + document.removeEventListener('tabIdChanged', onTabIdChanged); + domTree.removeEventListener('click', onClicked, true); + domTree.removeEventListener('mouseover', onMouseOver, true); + dom.off('#domInspector .vExpandToggler', 'click', toggleVExpandView); + dom.off('#domInspector .vCompactToggler', 'click', toggleVCompactView); + dom.off('#domInspector .hCompactToggler', 'click', toggleHCompactView); + dom.off('#domInspector .permatoolbar .revert', 'click', revert); + dom.off('#domInspector .permatoolbar .commit', 'click', startDialog); + contentInspectorChannel.shutdown(); + inspectedTabId = 0; +}; + +/******************************************************************************/ + +const toggle = ( ) => { + if ( dom.cl.toggle(showdomButton, 'active') ) { + toggleOn(); + } else { + toggleOff(); + } + logger.resize(); +}; + +dom.on(showdomButton, 'click', toggle); + +/******************************************************************************/ + +})(); diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js new file mode 100644 index 0000000..177632e --- /dev/null +++ b/src/js/logger-ui.js @@ -0,0 +1,3044 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +import { hostnameFromURI } from './uri-utils.js'; +import { i18n, i18n$ } from './i18n.js'; +import { dom, qs$, qsa$ } from './dom.js'; + +/******************************************************************************/ + +// TODO: fix the inconsistencies re. realm vs. filter source which have +// accumulated over time. + +const messaging = vAPI.messaging; +const logger = self.logger = { ownerId: Date.now() }; +const logDate = new Date(); +const logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000; +const loggerEntries = []; + +const COLUMN_TIMESTAMP = 0; +const COLUMN_FILTER = 1; +const COLUMN_MESSAGE = 1; +const COLUMN_RESULT = 2; +const COLUMN_INITIATOR = 3; +const COLUMN_PARTYNESS = 4; +const COLUMN_METHOD = 5; +const COLUMN_TYPE = 6; +const COLUMN_URL = 7; + +let filteredLoggerEntries = []; +let filteredLoggerEntryVoidedCount = 0; + +let popupLoggerBox; +let popupLoggerTooltips; +let activeTabId = 0; +let selectedTabId = 0; +let netInspectorPaused = false; +let cnameOfEnabled = false; + +/******************************************************************************/ + +// Various helpers. + +const tabIdFromPageSelector = logger.tabIdFromPageSelector = function() { + const value = qs$('#pageSelector').value; + return value !== '_' ? (parseInt(value, 10) || 0) : activeTabId; +}; + +const tabIdFromAttribute = function(elem) { + const value = dom.attr(elem, 'data-tabid') || ''; + const tabId = parseInt(value, 10); + return isNaN(tabId) ? 0 : tabId; +}; + + +/******************************************************************************/ +/******************************************************************************/ + +const onStartMovingWidget = (( ) => { + let widget = null; + let ondone = null; + let mx0 = 0, my0 = 0; + let mx1 = 0, my1 = 0; + let l0 = 0, t0 = 0; + let pw = 0, ph = 0; + let cw = 0, ch = 0; + let timer; + + const xyFromEvent = ev => { + if ( ev.type.startsWith('mouse') ) { + return { x: ev.pageX, y: ev.pageY }; + } + const touch = ev.touches[0]; + return { x: touch.pageX, y: touch.pageY }; + }; + + const eatEvent = function(ev) { + ev.stopPropagation(); + if ( ev.touches !== undefined ) { return; } + ev.preventDefault(); + }; + + const move = ( ) => { + timer = undefined; + const l1 = Math.min(Math.max(l0 + mx1 - mx0, 0), Math.max(pw - cw, 0)); + if ( (l1+cw/2) < (pw/2) ) { + widget.style.left = `${l1/pw*100}%`; + widget.style.right = ''; + } else { + widget.style.right = `${(pw-l1-cw)/pw*100}%`; + widget.style.left = ''; + } + const t1 = Math.min(Math.max(t0 + my1 - my0, 0), Math.max(ph - ch, 0)); + widget.style.top = `${t1/ph*100}%`; + widget.style.bottom = ''; + }; + + const moveAsync = ev => { + if ( timer !== undefined ) { return; } + const coord = xyFromEvent(ev); + mx1 = coord.x; my1 = coord.y; + timer = self.requestAnimationFrame(move); + eatEvent(ev); + }; + + const stop = ev => { + if ( timer !== undefined ) { + self.cancelAnimationFrame(timer); + timer = undefined; + } + if ( widget === null ) { return; } + if ( widget.classList.contains('moving') === false ) { return; } + widget.classList.remove('moving'); + self.removeEventListener('mousemove', moveAsync, { capture: true }); + self.removeEventListener('touchmove', moveAsync, { capture: true }); + eatEvent(ev); + widget = null; + if ( ondone !== null ) { + ondone(); + ondone = null; + } + }; + + return function(ev, target, callback) { + if ( dom.cl.has(target, 'moving') ) { return; } + widget = target; + ondone = callback || null; + const coord = xyFromEvent(ev); + mx0 = coord.x; my0 = coord.y; + const widgetParent = widget.parentElement; + const crect = widget.getBoundingClientRect(); + const prect = widgetParent.getBoundingClientRect(); + pw = prect.width; ph = prect.height; + cw = crect.width; ch = crect.height; + l0 = crect.x - prect.x; t0 = crect.y - prect.y; + widget.classList.add('moving'); + self.addEventListener('mousemove', moveAsync, { capture: true }); + self.addEventListener('mouseup', stop, { capture: true, once: true }); + self.addEventListener('touchmove', moveAsync, { capture: true }); + self.addEventListener('touchend', stop, { capture: true, once: true }); + eatEvent(ev); + }; +})(); + +/******************************************************************************/ +/******************************************************************************/ + +// Current design allows for only one modal DOM-based dialog at any given time. +// +const modalDialog = (( ) => { + const overlay = qs$('#modalOverlay'); + const container = qs$('#modalOverlayContainer'); + const closeButton = qs$(overlay, ':scope .closeButton'); + let onDestroyed; + + const removeChildren = logger.removeAllChildren = function(node) { + while ( node.firstChild ) { + node.removeChild(node.firstChild); + } + }; + + const create = function(selector, destroyListener) { + const template = qs$(selector); + const dialog = dom.clone(template); + removeChildren(container); + container.appendChild(dialog); + onDestroyed = destroyListener; + return dialog; + }; + + const show = function() { + dom.cl.add(overlay, 'on'); + }; + + const destroy = function() { + dom.cl.remove(overlay, 'on'); + const dialog = container.firstElementChild; + removeChildren(container); + if ( typeof onDestroyed === 'function' ) { + onDestroyed(dialog); + } + onDestroyed = undefined; + }; + + const onClose = function(ev) { + if ( ev.target === overlay || ev.target === closeButton ) { + destroy(); + } + }; + dom.on(overlay, 'click', onClose); + dom.on(closeButton, 'click', onClose); + + return { create, show, destroy }; +})(); + +self.logger.modalDialog = modalDialog; + + +/******************************************************************************/ +/******************************************************************************/ + +const prettyRequestTypes = { + 'main_frame': 'doc', + 'stylesheet': 'css', + 'sub_frame': 'frame', + 'xmlhttprequest': 'xhr' +}; + +const uglyRequestTypes = { + 'doc': 'main_frame', + 'css': 'stylesheet', + 'frame': 'sub_frame', + 'xhr': 'xmlhttprequest' +}; + +let allTabIds = new Map(); +let allTabIdsToken; + +/******************************************************************************/ +/******************************************************************************/ + +const regexFromURLFilteringResult = function(result) { + const beg = result.indexOf(' '); + const end = result.indexOf(' ', beg + 1); + const url = result.slice(beg + 1, end); + if ( url === '*' ) { + return new RegExp('^.*$', 'gi'); + } + return new RegExp('^' + url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'); +}; + +/******************************************************************************/ + +// Emphasize hostname in URL, as this is what matters in uMatrix's rules. + +const nodeFromURL = function(parent, url, re, type) { + const fragment = document.createDocumentFragment(); + if ( re === undefined ) { + fragment.textContent = url; + } else { + if ( typeof re === 'string' ) { + re = new RegExp(re.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'); + } + const matches = re.exec(url); + if ( matches === null || matches[0].length === 0 ) { + fragment.textContent = url; + } else { + if ( matches.index !== 0 ) { + fragment.appendChild( + document.createTextNode(url.slice(0, matches.index)) + ); + } + const b = document.createElement('b'); + b.textContent = url.slice(matches.index, re.lastIndex); + fragment.appendChild(b); + if ( re.lastIndex !== url.length ) { + fragment.appendChild( + document.createTextNode(url.slice(re.lastIndex)) + ); + } + } + } + if ( /^https?:\/\//.test(url) ) { + const a = document.createElement('a'); + let href = url; + switch ( type ) { + case 'css': + case 'doc': + case 'frame': + case 'object': + case 'other': + case 'script': + case 'xhr': + href = `code-viewer.html?url=${encodeURIComponent(href)}`; + break; + default: + break; + } + dom.attr(a, 'href', href); + dom.attr(a, 'target', '_blank'); + fragment.appendChild(a); + } + parent.appendChild(fragment); +}; + +/******************************************************************************/ + +const padTo2 = function(v) { + return v < 10 ? '0' + v : v; +}; + +const normalizeToStr = function(s) { + return typeof s === 'string' && s !== '' ? s : ''; +}; + +/******************************************************************************/ + +const LogEntry = function(details) { + if ( details instanceof Object === false ) { return; } + const receiver = LogEntry.prototype; + for ( const prop in receiver ) { + if ( + details.hasOwnProperty(prop) && + details[prop] !== receiver[prop] + ) { + this[prop] = details[prop]; + } + } + if ( details.aliasURL !== undefined ) { + this.aliased = true; + } + if ( this.tabDomain === '' ) { + this.tabDomain = this.tabHostname || ''; + } + if ( this.docDomain === '' ) { + this.docDomain = this.docHostname || ''; + } + if ( this.domain === '' ) { + this.domain = details.hostname || ''; + } +}; +LogEntry.prototype = { + aliased: false, + dead: false, + docDomain: '', + docHostname: '', + domain: '', + filter: undefined, + id: '', + method: '', + realm: '', + tabDomain: '', + tabHostname: '', + tabId: undefined, + textContent: '', + tstamp: 0, + type: '', + voided: false, +}; + +/******************************************************************************/ + +const createLogSeparator = function(details, text) { + const separator = new LogEntry(); + separator.tstamp = details.tstamp; + separator.realm = 'message'; + separator.tabId = details.tabId; + separator.type = 'tabLoad'; + separator.textContent = ''; + + const textContent = []; + logDate.setTime(separator.tstamp - logDateTimezoneOffset); + textContent.push( + // cell 0 + padTo2(logDate.getUTCHours()) + ':' + + padTo2(logDate.getUTCMinutes()) + ':' + + padTo2(logDate.getSeconds()), + // cell 1 + text + ); + separator.textContent = textContent.join('\t'); + + if ( details.voided ) { + separator.voided = true; + } + + return separator; +}; + +/******************************************************************************/ + +// TODO: once refactoring is mature, consider using push() instead of +// unshift(). This will require inverting the access logic +// throughout the code. +// +const processLoggerEntries = function(response) { + const entries = response.entries; + if ( entries.length === 0 ) { return; } + + const autoDeleteVoidedRows = qs$('#pageSelector').value === '_'; + const previousCount = filteredLoggerEntries.length; + + for ( const entry of entries ) { + const unboxed = JSON.parse(entry); + if ( unboxed.filter instanceof Object ){ + loggerStats.processFilter(unboxed.filter); + } + if ( netInspectorPaused ) { continue; } + const parsed = parseLogEntry(unboxed); + if ( + parsed.tabId !== undefined && + allTabIds.has(parsed.tabId) === false + ) { + if ( autoDeleteVoidedRows ) { continue; } + parsed.voided = true; + } + if ( + parsed.type === 'main_frame' && + parsed.aliased === false && ( + parsed.filter === undefined || + parsed.filter.modifier !== true + ) + ) { + const separator = createLogSeparator(parsed, unboxed.url); + loggerEntries.unshift(separator); + if ( rowFilterer.filterOne(separator) ) { + filteredLoggerEntries.unshift(separator); + if ( separator.voided ) { + filteredLoggerEntryVoidedCount += 1; + } + } + } + if ( cnameOfEnabled === false && parsed.aliased ) { + qs$('#filterExprCnameOf').style.display = ''; + cnameOfEnabled = true; + } + loggerEntries.unshift(parsed); + if ( rowFilterer.filterOne(parsed) ) { + filteredLoggerEntries.unshift(parsed); + if ( parsed.voided ) { + filteredLoggerEntryVoidedCount += 1; + } + } + } + + const addedCount = filteredLoggerEntries.length - previousCount; + if ( addedCount !== 0 ) { + viewPort.updateContent(addedCount); + rowJanitor.inserted(addedCount); + } +}; + +/******************************************************************************/ + +const parseLogEntry = function(details) { + // Patch realm until changed all over codebase to make this unnecessary + if ( details.realm === 'cosmetic' ) { + details.realm = 'extended'; + } + + const entry = new LogEntry(details); + + // Assemble the text content, i.e. the pre-built string which will be + // used to match logger output filtering expressions. + const textContent = []; + + // Cell 0 + logDate.setTime(details.tstamp - logDateTimezoneOffset); + textContent.push( + padTo2(logDate.getUTCHours()) + ':' + + padTo2(logDate.getUTCMinutes()) + ':' + + padTo2(logDate.getSeconds()) + ); + + // Cell 1 + if ( details.realm === 'message' ) { + textContent.push(details.text); + entry.textContent = textContent.join('\t'); + return entry; + } + + // Cell 1, 2 + if ( entry.filter !== undefined ) { + textContent.push(entry.filter.raw); + if ( entry.filter.result === 1 ) { + textContent.push('--'); + } else if ( entry.filter.result === 2 ) { + textContent.push('++'); + } else if ( entry.filter.result === 3 ) { + textContent.push('**'); + } else if ( entry.filter.source === 'redirect' ) { + textContent.push('<<'); + } else { + textContent.push(''); + } + } else { + textContent.push('', ''); + } + + // Cell 3 + textContent.push(normalizeToStr(entry.docHostname)); + + // Cell 4: partyness + if ( + entry.realm === 'network' && + typeof entry.domain === 'string' && + entry.domain !== '' + ) { + let partyness = ''; + if ( entry.tabDomain !== undefined ) { + if ( entry.tabId < 0 ) { + partyness += '0,'; + } + partyness += entry.domain === entry.tabDomain ? '1' : '3'; + } else { + partyness += '?'; + } + if ( entry.docDomain !== entry.tabDomain ) { + partyness += ','; + if ( entry.docDomain !== undefined ) { + partyness += entry.domain === entry.docDomain ? '1' : '3'; + } else { + partyness += '?'; + } + } + textContent.push(partyness); + } else { + textContent.push(''); + } + + // Cell 5: method + textContent.push(entry.method || ''); + + // Cell 6 + textContent.push( + normalizeToStr(prettyRequestTypes[entry.type] || entry.type) + ); + + // Cell 7 + textContent.push(normalizeToStr(details.url)); + + // Hidden cells -- useful for row-filtering purpose + + // Cell 8 + if ( entry.aliased ) { + textContent.push(`aliasURL=${details.aliasURL}`); + } + + entry.textContent = textContent.join('\t'); + return entry; +}; + +/******************************************************************************/ + +const viewPort = (( ) => { + const vwRenderer = qs$('#vwRenderer'); + const vwScroller = qs$('#vwScroller'); + const vwVirtualContent = qs$('#vwVirtualContent'); + const vwContent = qs$('#vwContent'); + const vwLineSizer = qs$('#vwLineSizer'); + const vwLogEntryTemplate = qs$('#logEntryTemplate > div'); + const vwEntries = []; + + const detailableRealms = new Set([ 'network', 'extended' ]); + + let vwHeight = 0; + let lineHeight = 0; + let wholeHeight = 0; + let lastTopPix = 0; + let lastTopRow = 0; + + const ViewEntry = function() { + this.div = document.createElement('div'); + this.div.className = 'logEntry'; + vwContent.appendChild(this.div); + this.logEntry = undefined; + }; + ViewEntry.prototype = { + dispose: function() { + vwContent.removeChild(this.div); + }, + }; + + const rowFromScrollTopPix = function(px) { + return lineHeight !== 0 ? Math.floor(px / lineHeight) : 0; + }; + + // This is called when the browser fired scroll events + const onScrollChanged = function() { + const newScrollTopPix = vwScroller.scrollTop; + const delta = newScrollTopPix - lastTopPix; + if ( delta === 0 ) { return; } + lastTopPix = newScrollTopPix; + if ( filteredLoggerEntries.length <= 2 ) { return; } + // No entries were rolled = all entries keep their current details + if ( rollLines(rowFromScrollTopPix(newScrollTopPix)) ) { + fillLines(); + } + positionLines(); + vwContent.style.top = `${lastTopPix}px`; + }; + + // Coalesce scroll events + const scrollTimer = vAPI.defer.create(onScrollChanged); + const onScroll = ( ) => { + scrollTimer.onvsync(1000/32); + }; + dom.on(vwScroller, 'scroll', onScroll, { passive: true }); + + const onLayoutChanged = function() { + vwHeight = vwRenderer.clientHeight; + vwContent.style.height = `${vwScroller.clientHeight}px`; + + const vExpanded = + dom.cl.has('#netInspector .vCompactToggler', 'vExpanded'); + + let newLineHeight = qs$(vwLineSizer, '.oneLine').clientHeight; + + if ( vExpanded ) { + newLineHeight *= loggerSettings.linesPerEntry; + } + + const lineCount = newLineHeight !== 0 + ? Math.ceil(vwHeight / newLineHeight) + 1 + : 0; + if ( lineCount > vwEntries.length ) { + do { + vwEntries.push(new ViewEntry()); + } while ( lineCount > vwEntries.length ); + } else if ( lineCount < vwEntries.length ) { + do { + vwEntries.pop().dispose(); + } while ( lineCount < vwEntries.length ); + } + + const cellWidths = Array.from( + qsa$(vwLineSizer, '.oneLine span') + ).map((el, i) => { + return loggerSettings.columns[i] !== false + ? el.clientWidth + 1 + : 0; + }); + const reservedWidth = + cellWidths[COLUMN_TIMESTAMP] + + cellWidths[COLUMN_RESULT] + + cellWidths[COLUMN_PARTYNESS] + + cellWidths[COLUMN_METHOD] + + cellWidths[COLUMN_TYPE]; + cellWidths[COLUMN_URL] = 0.5; + if ( cellWidths[COLUMN_FILTER] === 0 && cellWidths[COLUMN_INITIATOR] === 0 ) { + cellWidths[COLUMN_URL] = 1; + } else if ( cellWidths[COLUMN_FILTER] === 0 ) { + cellWidths[COLUMN_INITIATOR] = 0.35; + cellWidths[COLUMN_URL] = 0.65; + } else if ( cellWidths[COLUMN_INITIATOR] === 0 ) { + cellWidths[COLUMN_FILTER] = 0.35; + cellWidths[COLUMN_URL] = 0.65; + } else { + cellWidths[COLUMN_FILTER] = 0.25; + cellWidths[COLUMN_INITIATOR] = 0.25; + cellWidths[COLUMN_URL] = 0.5; + } + const style = qs$('#vwRendererRuntimeStyles'); + const cssRules = [ + '#vwContent .logEntry {', + ` height: ${newLineHeight}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_TIMESTAMP+1}) {`, + ` width: ${cellWidths[COLUMN_TIMESTAMP]}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_FILTER+1}) {`, + ` width: calc(calc(100% - ${reservedWidth}px) * ${cellWidths[COLUMN_FILTER]});`, + '}', + `#vwContent .logEntry > div.messageRealm > span:nth-of-type(${COLUMN_MESSAGE+1}) {`, + ` width: calc(100% - ${cellWidths[COLUMN_TIMESTAMP]}px);`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_RESULT+1}) {`, + ` width: ${cellWidths[COLUMN_RESULT]}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_INITIATOR+1}) {`, + ` width: calc(calc(100% - ${reservedWidth}px) * ${cellWidths[COLUMN_INITIATOR]});`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_PARTYNESS+1}) {`, + ` width: ${cellWidths[COLUMN_PARTYNESS]}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_METHOD+1}) {`, + ` width: ${cellWidths[COLUMN_METHOD]}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_TYPE+1}) {`, + ` width: ${cellWidths[COLUMN_TYPE]}px;`, + '}', + `#vwContent .logEntry > div > span:nth-of-type(${COLUMN_URL+1}) {`, + ` width: calc(calc(100% - ${reservedWidth}px) * ${cellWidths[COLUMN_URL]});`, + '}', + '', + ]; + for ( let i = 0; i < cellWidths.length; i++ ) { + if ( cellWidths[i] !== 0 ) { continue; } + cssRules.push( + `#vwContent .logEntry > div > span:nth-of-type(${i + 1}) {`, + ' display: none;', + '}' + ); + } + style.textContent = cssRules.join('\n'); + + lineHeight = newLineHeight; + positionLines(); + dom.cl.toggle('#netInspector', 'vExpanded', vExpanded); + + updateContent(0); + }; + + const resizeTimer = vAPI.defer.create(onLayoutChanged); + const updateLayout = function() { + resizeTimer.onvsync(1000/8); + }; + dom.on(window, 'resize', updateLayout, { passive: true }); + + updateLayout(); + + const renderFilterToSpan = function(span, filter) { + if ( filter.charCodeAt(0) !== 0x23 /* '#' */ ) { return false; } + const match = /^#@?#/.exec(filter); + if ( match === null ) { return false; } + let child = document.createElement('span'); + child.textContent = match[0]; + span.appendChild(child); + child = document.createElement('span'); + child.textContent = filter.slice(match[0].length); + span.appendChild(child); + return true; + }; + + const renderToDiv = function(vwEntry, i) { + if ( i >= filteredLoggerEntries.length ) { + vwEntry.logEntry = undefined; + return null; + } + + const details = filteredLoggerEntries[i]; + if ( vwEntry.logEntry === details ) { + return vwEntry.div.firstElementChild; + } + + vwEntry.logEntry = details; + + const cells = details.textContent.split('\t'); + const div = dom.clone(vwLogEntryTemplate); + const divcl = div.classList; + let span; + + // Realm + if ( details.realm !== undefined ) { + divcl.add(details.realm + 'Realm'); + } + + // Timestamp + span = div.children[COLUMN_TIMESTAMP]; + span.textContent = cells[COLUMN_TIMESTAMP]; + + // Tab id + if ( details.tabId !== undefined ) { + dom.attr(div, 'data-tabid', details.tabId); + if ( details.voided ) { + divcl.add('voided'); + } + } + + if ( details.realm === 'message' ) { + if ( details.type !== undefined ) { + dom.attr(div, 'data-type', details.type); + } + span = div.children[COLUMN_MESSAGE]; + span.textContent = cells[COLUMN_MESSAGE]; + return div; + } + + if ( detailableRealms.has(details.realm) ) { + divcl.add('canDetails'); + } + + // Filter + const filter = details.filter || undefined; + let filteringType; + if ( filter !== undefined ) { + if ( typeof filter.source === 'string' ) { + filteringType = filter.source; + } + if ( filteringType === 'static' ) { + divcl.add('canLookup'); + } else if ( details.realm === 'extended' ) { + divcl.toggle('canLookup', /^#@?#/.test(filter.raw)); + divcl.toggle('isException', filter.raw.startsWith('#@#')); + } + if ( filter.modifier === true ) { + dom.attr(div, 'data-modifier', ''); + } + } + span = div.children[COLUMN_FILTER]; + if ( renderFilterToSpan(span, cells[COLUMN_FILTER]) ) { + if ( /^\+js\(.*\)$/.test(span.children[1].textContent) ) { + divcl.add('scriptlet'); + } + } else { + span.textContent = cells[COLUMN_FILTER]; + } + + // Event + if ( cells[COLUMN_RESULT] === '--' ) { + dom.attr(div, 'data-status', '1'); + } else if ( cells[COLUMN_RESULT] === '++' ) { + dom.attr(div, 'data-status', '2'); + } else if ( cells[COLUMN_RESULT] === '**' ) { + dom.attr(div, 'data-status', '3'); + } else if ( cells[COLUMN_RESULT] === '<<' ) { + divcl.add('redirect'); + } + span = div.children[COLUMN_RESULT]; + span.textContent = cells[COLUMN_RESULT]; + + // Origins + if ( details.tabHostname ) { + dom.attr(div, 'data-tabhn', details.tabHostname); + } + if ( details.docHostname ) { + dom.attr(div, 'data-dochn', details.docHostname); + } + span = div.children[COLUMN_INITIATOR]; + span.textContent = cells[COLUMN_INITIATOR]; + + // Partyness + if ( + cells[COLUMN_PARTYNESS] !== '' && + details.realm === 'network' && + details.domain !== undefined + ) { + let text = `${details.tabDomain}`; + if ( details.docDomain !== details.tabDomain ) { + text += ` \u22ef ${details.docDomain}`; + } + text += ` \u21d2 ${details.domain}`; + dom.attr(div, 'data-parties', text); + } + span = div.children[COLUMN_PARTYNESS]; + span.textContent = cells[COLUMN_PARTYNESS]; + + // Method + span = div.children[COLUMN_METHOD]; + span.textContent = cells[COLUMN_METHOD]; + + // Type + span = div.children[COLUMN_TYPE]; + span.textContent = cells[COLUMN_TYPE]; + + // URL + let re; + if ( filteringType === 'static' ) { + re = new RegExp(filter.regex, 'gi'); + } else if ( filteringType === 'dynamicUrl' ) { + re = regexFromURLFilteringResult(filter.rule.join(' ')); + } + nodeFromURL(div.children[COLUMN_URL], cells[COLUMN_URL], re, cells[COLUMN_TYPE]); + + // Alias URL (CNAME, etc.) + if ( cells.length > 8 ) { + const pos = details.textContent.lastIndexOf('\taliasURL='); + if ( pos !== -1 ) { + dom.attr(div, 'data-aliasid', details.id); + } + } + + return div; + }; + + // The idea is that positioning DOM elements is faster than + // removing/inserting DOM elements. + const positionLines = function() { + if ( lineHeight === 0 ) { return; } + let y = -(lastTopPix % lineHeight); + for ( const vwEntry of vwEntries ) { + vwEntry.div.style.top = `${y}px`; + y += lineHeight; + } + }; + + const rollLines = function(topRow) { + let delta = topRow - lastTopRow; + let deltaLength = Math.abs(delta); + // No point rolling if no rows can be reused + if ( deltaLength > 0 && deltaLength < vwEntries.length ) { + if ( delta < 0 ) { // Move bottom rows to the top + vwEntries.unshift(...vwEntries.splice(delta)); + } else { // Move top rows to the bottom + vwEntries.push(...vwEntries.splice(0, delta)); + } + } + lastTopRow = topRow; + return delta; + }; + + const fillLines = function() { + let rowBeg = lastTopRow; + for ( const vwEntry of vwEntries ) { + const newDiv = renderToDiv(vwEntry, rowBeg); + const container = vwEntry.div; + const oldDiv = container.firstElementChild; + if ( newDiv !== null ) { + if ( oldDiv === null ) { + container.appendChild(newDiv); + } else if ( newDiv !== oldDiv ) { + container.removeChild(oldDiv); + container.appendChild(newDiv); + } + } else if ( oldDiv !== null ) { + container.removeChild(oldDiv); + } + rowBeg += 1; + } + }; + + const contentChanged = function(addedCount) { + lastTopRow += addedCount; + const newWholeHeight = Math.max( + filteredLoggerEntries.length * lineHeight, + vwRenderer.clientHeight + ); + if ( newWholeHeight !== wholeHeight ) { + vwVirtualContent.style.height = `${newWholeHeight}px`; + wholeHeight = newWholeHeight; + } + }; + + const updateContent = function(addedCount) { + contentChanged(addedCount); + // Content changed + if ( addedCount === 0 ) { + if ( + lastTopRow !== 0 && + lastTopRow + vwEntries.length > filteredLoggerEntries.length + ) { + lastTopRow = filteredLoggerEntries.length - vwEntries.length; + if ( lastTopRow < 0 ) { lastTopRow = 0; } + lastTopPix = lastTopRow * lineHeight; + vwContent.style.top = `${lastTopPix}px`; + vwScroller.scrollTop = lastTopPix; + positionLines(); + } + fillLines(); + return; + } + + // Content added + // Preserve scroll position + if ( lastTopPix === 0 ) { + rollLines(0); + positionLines(); + fillLines(); + return; + } + + // Preserve row position + lastTopPix += lineHeight * addedCount; + vwContent.style.top = `${lastTopPix}px`; + vwScroller.scrollTop = lastTopPix; + }; + + return { updateContent, updateLayout, }; +})(); + +/******************************************************************************/ + +const updateCurrentTabTitle = (( ) => { + const i18nCurrentTab = i18n$('loggerCurrentTab'); + + return ( ) => { + const select = qs$('#pageSelector'); + if ( select.value !== '_' || activeTabId === 0 ) { return; } + const opt0 = qs$(select, '[value="_"]'); + const opt1 = qs$(select, `[value="${activeTabId}"]`); + let text = i18nCurrentTab; + if ( opt1 !== null ) { + text += ' / ' + opt1.textContent; + } + opt0.textContent = text; + }; +})(); + +/******************************************************************************/ + +const synchronizeTabIds = function(newTabIds) { + const select = qs$('#pageSelector'); + const selectedTabValue = select.value; + const oldTabIds = allTabIds; + + // Collate removed tab ids. + const toVoid = new Set(); + for ( const tabId of oldTabIds.keys() ) { + if ( newTabIds.has(tabId) ) { continue; } + toVoid.add(tabId); + } + allTabIds = newTabIds; + + // Mark as "void" all logger entries which are linked to now invalid + // tab ids. + // When an entry is voided without being removed, we re-create a new entry + // in order to ensure the entry has a new identity. A new identify ensures + // that identity-based associations elsewhere are automatically + // invalidated. + if ( toVoid.size !== 0 ) { + const autoDeleteVoidedRows = selectedTabValue === '_'; + let rowVoided = false; + for ( let i = 0, n = loggerEntries.length; i < n; i++ ) { + const entry = loggerEntries[i]; + if ( toVoid.has(entry.tabId) === false ) { continue; } + if ( entry.voided ) { continue; } + rowVoided = entry.voided = true; + if ( autoDeleteVoidedRows ) { + entry.dead = true; + } + loggerEntries[i] = new LogEntry(entry); + } + if ( rowVoided ) { + rowFilterer.filterAll(); + } + } + + // Remove popup if it is currently bound to a removed tab. + if ( toVoid.has(popupManager.tabId) ) { + popupManager.toggleOff(); + } + + const tabIds = Array.from(newTabIds.keys()).sort(function(a, b) { + return newTabIds.get(a).localeCompare(newTabIds.get(b)); + }); + let j = 3; + for ( const tabId of tabIds ) { + if ( tabId <= 0 ) { continue; } + if ( j === select.options.length ) { + select.appendChild(document.createElement('option')); + } + const option = select.options[j]; + // Truncate too long labels. + option.textContent = newTabIds.get(tabId).slice(0, 80); + dom.attr(option, 'value', tabId); + if ( option.value === selectedTabValue ) { + select.selectedIndex = j; + dom.attr(option, 'selected', ''); + } else { + dom.attr(option, 'selected', null); + } + j += 1; + } + while ( j < select.options.length ) { + select.removeChild(select.options[j]); + } + if ( select.value !== selectedTabValue ) { + select.selectedIndex = 0; + select.value = ''; + dom.attr(select.options[0], 'selected', ''); + pageSelectorChanged(); + } + + updateCurrentTabTitle(); +}; + +/******************************************************************************/ + +const onLogBufferRead = function(response) { + if ( !response || response.unavailable ) { return; } + + // Disable tooltips? + if ( + popupLoggerTooltips === undefined && + response.tooltips !== undefined + ) { + popupLoggerTooltips = response.tooltips; + if ( popupLoggerTooltips === false ) { + dom.attr('[data-i18n-title]', 'title', ''); + } + } + + // Tab id of currently active tab + let activeTabIdChanged = false; + if ( response.activeTabId ) { + activeTabIdChanged = response.activeTabId !== activeTabId; + activeTabId = response.activeTabId; + } + + if ( Array.isArray(response.tabIds) ) { + response.tabIds = new Map(response.tabIds); + } + + // List of tab ids has changed + if ( response.tabIds !== undefined ) { + synchronizeTabIds(response.tabIds); + allTabIdsToken = response.tabIdsToken; + } + + if ( activeTabIdChanged ) { + pageSelectorFromURLHash(); + } + + processLoggerEntries(response); + + // Synchronize DOM with sent logger data + dom.cl.toggle(dom.html, 'colorBlind', response.colorBlind === true); + dom.cl.toggle('#clean', 'disabled', filteredLoggerEntryVoidedCount === 0); + dom.cl.toggle('#clear', 'disabled', filteredLoggerEntries.length === 0); +}; + +/******************************************************************************/ + +const readLogBuffer = (( ) => { + let reading = false; + + const readLogBufferNow = async function() { + if ( logger.ownerId === undefined ) { return; } + if ( reading ) { return; } + + reading = true; + + const msg = { + what: 'readAll', + ownerId: logger.ownerId, + tabIdsToken: allTabIdsToken, + }; + + // This is to detect changes in the position or size of the logger + // popup window (if in use). + if ( + popupLoggerBox instanceof Object && + ( + self.screenX !== popupLoggerBox.x || + self.screenY !== popupLoggerBox.y || + self.outerWidth !== popupLoggerBox.w || + self.outerHeight !== popupLoggerBox.h + ) + ) { + popupLoggerBox.x = self.screenX; + popupLoggerBox.y = self.screenY; + popupLoggerBox.w = self.outerWidth; + popupLoggerBox.h = self.outerHeight; + msg.popupLoggerBoxChanged = true; + } + + const response = await vAPI.messaging.send('loggerUI', msg); + + onLogBufferRead(response); + + reading = false; + + timer.on(1200); + }; + + const timer = vAPI.defer.create(readLogBufferNow); + + readLogBufferNow(); + + return ( ) => { + timer.on(1200); + }; +})(); + +/******************************************************************************/ + +const pageSelectorChanged = function() { + const select = qs$('#pageSelector'); + window.location.replace('#' + select.value); + pageSelectorFromURLHash(); +}; + +const pageSelectorFromURLHash = (( ) => { + let lastHash; + let lastSelectedTabId; + + return function() { + let hash = window.location.hash.slice(1); + let match = /^([^+]+)\+(.+)$/.exec(hash); + if ( match !== null ) { + hash = match[1]; + activeTabId = parseInt(match[2], 10) || 0; + window.location.hash = '#' + hash; + } + + if ( hash !== lastHash ) { + const select = qs$('#pageSelector'); + let option = qs$(select, `option[value="${hash}"]`); + if ( option === null ) { + hash = '0'; + option = select.options[0]; + } + select.selectedIndex = option.index; + select.value = option.value; + lastHash = hash; + } + + selectedTabId = hash === '_' + ? activeTabId + : parseInt(hash, 10) || 0; + + if ( lastSelectedTabId === selectedTabId ) { return; } + + rowFilterer.filterAll(); + document.dispatchEvent(new Event('tabIdChanged')); + updateCurrentTabTitle(); + dom.cl.toggle('.needdom', 'disabled', selectedTabId <= 0); + dom.cl.toggle('.needscope', 'disabled', selectedTabId <= 0); + lastSelectedTabId = selectedTabId; + }; +})(); + +/******************************************************************************/ + +const reloadTab = function(bypassCache = false) { + const tabId = tabIdFromPageSelector(); + if ( tabId <= 0 ) { return; } + messaging.send('loggerUI', { + what: 'reloadTab', + tabId, + bypassCache, + }); +}; + +dom.on('#refresh', 'click', ev => { + reloadTab(ev.ctrlKey || ev.metaKey || ev.shiftKey); +}); + +dom.on(document, 'keydown', ev => { + if ( ev.isComposing ) { return; } + let bypassCache = false; + switch ( ev.key ) { + case 'F5': + bypassCache = ev.ctrlKey || ev.metaKey || ev.shiftKey; + break; + case 'r': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + break; + case 'R': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + bypassCache = true; + break; + default: + return; + } + reloadTab(bypassCache); + ev.preventDefault(); + ev.stopPropagation(); +}, { capture: true }); + +/******************************************************************************/ +/******************************************************************************/ + +(( ) => { + const reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; + const reSchemeOnly = /^[\w-]+:$/; + const staticFilterTypes = { + 'beacon': 'ping', + 'doc': 'document', + 'css': 'stylesheet', + 'frame': 'subdocument', + 'object_subrequest': 'object', + 'csp_report': 'other', + }; + const createdStaticFilters = {}; + const reIsExceptionFilter = /^@@|^[\w.-]*?#@#/; + + let dialog = null; + let targetRow = null; + let targetType; + let targetURLs = []; + let targetFrameHostname; + let targetPageHostname; + let targetTabId; + let targetDomain; + let targetPageDomain; + let targetFrameDomain; + + const uglyTypeFromSelector = pane => { + const prettyType = selectValue('select.type.' + pane); + if ( pane === 'static' ) { + return staticFilterTypes[prettyType] || prettyType; + } + return uglyRequestTypes[prettyType] || prettyType; + }; + + const selectNode = selector => { + return qs$(dialog, selector); + }; + + const selectValue = selector => { + return selectNode(selector).value || ''; + }; + + const staticFilterNode = ( ) => { + return qs$(dialog, 'div.panes > div.static textarea'); + }; + + const toExceptionFilter = (filter, extended) => { + if ( reIsExceptionFilter.test(filter) ) { return filter; } + return extended ? filter.replace('##', '#@#') : `@@${filter}`; + }; + + const onColorsReady = function(response) { + dom.cl.toggle(dom.body, 'dirty', response.dirty); + for ( const url in response.colors ) { + if ( response.colors.hasOwnProperty(url) === false ) { continue; } + const colorEntry = response.colors[url]; + const node = qs$(dialog, `.dynamic .entry .action[data-url="${url}"]`); + if ( node === null ) { continue; } + dom.cl.toggle(node, 'allow', colorEntry.r === 2); + dom.cl.toggle(node, 'noop', colorEntry.r === 3); + dom.cl.toggle(node, 'block', colorEntry.r === 1); + dom.cl.toggle(node, 'own', colorEntry.own); + } + }; + + const colorize = async function() { + const response = await messaging.send('loggerUI', { + what: 'getURLFilteringData', + context: selectValue('select.dynamic.origin'), + urls: targetURLs, + type: uglyTypeFromSelector('dynamic'), + }); + onColorsReady(response); + }; + + const parseStaticInputs = function() { + const options = []; + const block = selectValue('select.static.action') === ''; + let filter = ''; + if ( !block ) { + filter = '@@'; + } + let value = selectValue('select.static.url'); + if ( value !== '' ) { + if ( reSchemeOnly.test(value) ) { + value = `|${value}`; + } else { + if ( value.endsWith('/') ) { + value += '*'; + } else if ( /[/?]/.test(value) === false ) { + value += '^'; + } + value = `||${value}`; + } + } + filter += value; + value = selectValue('select.static.type'); + if ( value !== '' ) { + options.push(uglyTypeFromSelector('static')); + } + value = selectValue('select.static.origin'); + if ( value !== '' ) { + if ( value === targetDomain ) { + options.push('1p'); + } else { + options.push('domain=' + value); + } + } + if ( block && selectValue('select.static.importance') !== '' ) { + options.push('important'); + } + if ( options.length ) { + filter += '$' + options.join(','); + } + staticFilterNode().value = filter; + updateWidgets(); + }; + + const updateWidgets = function() { + const value = staticFilterNode().value; + dom.cl.toggle( + qs$(dialog, '#createStaticFilter'), + 'disabled', + createdStaticFilters.hasOwnProperty(value) || value === '' + ); + }; + + const onClick = async function(ev) { + const target = ev.target; + const tcl = target.classList; + + // Close entry tools + if ( tcl.contains('closeButton') ) { + ev.stopPropagation(); + toggleOff(); + return; + } + + // Select a pane + if ( tcl.contains('header') ) { + ev.stopPropagation(); + dom.attr(dialog, 'data-pane', dom.attr(target, 'data-pane')); + return; + } + + // Toggle temporary exception filter + if ( tcl.contains('exceptor') ) { + ev.stopPropagation(); + const filter = filterFromTargetRow(); + const status = await messaging.send('loggerUI', { + what: 'toggleInMemoryFilter', + filter: toExceptionFilter(filter, dom.cl.has(targetRow, 'extendedRealm')), + }); + const row = target.closest('div'); + dom.cl.toggle(row, 'exceptored', status); + return; + } + + // Create static filter + if ( target.id === 'createStaticFilter' ) { + ev.stopPropagation(); + const value = staticFilterNode().value; + // Avoid duplicates + if ( createdStaticFilters.hasOwnProperty(value) ) { return; } + createdStaticFilters[value] = true; + // https://github.com/uBlockOrigin/uBlock-issues/issues/1281#issuecomment-704217175 + // TODO: + // Figure a way to use the actual document URL. Currently using + // a synthetic URL derived from the document hostname. + if ( value !== '' ) { + messaging.send('loggerUI', { + what: 'createUserFilter', + autoComment: true, + filters: value, + docURL: `https://${targetFrameHostname}/`, + }); + } + updateWidgets(); + return; + } + + // Save url filtering rule(s) + if ( target.id === 'saveRules' ) { + ev.stopPropagation(); + await messaging.send('loggerUI', { + what: 'saveURLFilteringRules', + context: selectValue('select.dynamic.origin'), + urls: targetURLs, + type: uglyTypeFromSelector('dynamic'), + }); + colorize(); + return; + } + + const persist = !!ev.ctrlKey || !!ev.metaKey; + + // Remove url filtering rule + if ( tcl.contains('action') ) { + ev.stopPropagation(); + await messaging.send('loggerUI', { + what: 'setURLFilteringRule', + context: selectValue('select.dynamic.origin'), + url: dom.attr(target, 'data-url'), + type: uglyTypeFromSelector('dynamic'), + action: 0, + persist: persist, + }); + colorize(); + return; + } + + // add "allow" url filtering rule + if ( tcl.contains('allow') ) { + ev.stopPropagation(); + await messaging.send('loggerUI', { + what: 'setURLFilteringRule', + context: selectValue('select.dynamic.origin'), + url: dom.attr(target.parentNode, 'data-url'), + type: uglyTypeFromSelector('dynamic'), + action: 2, + persist: persist, + }); + colorize(); + return; + } + + // add "block" url filtering rule + if ( tcl.contains('noop') ) { + ev.stopPropagation(); + await messaging.send('loggerUI', { + what: 'setURLFilteringRule', + context: selectValue('select.dynamic.origin'), + url: dom.attr(target.parentNode, 'data-url'), + type: uglyTypeFromSelector('dynamic'), + action: 3, + persist: persist, + }); + colorize(); + return; + } + + // add "block" url filtering rule + if ( tcl.contains('block') ) { + ev.stopPropagation(); + await messaging.send('loggerUI', { + what: 'setURLFilteringRule', + context: selectValue('select.dynamic.origin'), + url: dom.attr(target.parentNode, 'data-url'), + type: uglyTypeFromSelector('dynamic'), + action: 1, + persist: persist, + }); + colorize(); + return; + } + + // Highlight corresponding element in target web page + if ( tcl.contains('picker') ) { + ev.stopPropagation(); + messaging.send('loggerUI', { + what: 'launchElementPicker', + tabId: targetTabId, + targetURL: 'img\t' + targetURLs[0], + select: true, + }); + return; + } + + // Reload tab associated with event + if ( tcl.contains('reload') ) { + ev.stopPropagation(); + messaging.send('loggerUI', { + what: 'reloadTab', + tabId: targetTabId, + bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey, + }); + return; + } + }; + + const onSelectChange = function(ev) { + const tcl = ev.target.classList; + + if ( tcl.contains('dynamic') ) { + colorize(); + return; + } + + if ( tcl.contains('static') ) { + parseStaticInputs(); + return; + } + }; + + const onInputChange = function() { + updateWidgets(); + }; + + const createPreview = function(type, url) { + const cantPreview = + type !== 'image' || + dom.cl.has(targetRow, 'networkRealm') === false || + dom.attr(targetRow, 'data-status') === '1'; + + // Whether picker can be used + dom.cl.toggle( + qs$(dialog, '.picker'), + 'hide', + targetTabId < 0 || cantPreview + ); + + // Whether the resource can be previewed + if ( cantPreview ) { return; } + + const container = qs$(dialog, '.preview'); + dom.on(qs$(container, 'span'), 'click', ( ) => { + const preview = dom.create('img'); + dom.attr(preview, 'src', url); + container.replaceChild(preview, container.firstElementChild); + }, { once: true }); + + dom.cl.remove(container, 'hide'); + }; + + // https://github.com/gorhill/uBlock/issues/1511 + const shortenLongString = function(url, max) { + const urlLen = url.length; + if ( urlLen <= max ) { + return url; + } + const n = urlLen - max - 1; + const i = (urlLen - n) / 2 | 0; + return url.slice(0, i) + '…' + url.slice(i + n); + }; + + // Build list of candidate URLs + const createTargetURLs = function(url) { + const matches = reRFC3986.exec(url); + if ( matches === null ) { return []; } + if ( typeof matches[2] !== 'string' || matches[2].length === 0 ) { + return [ matches[1] ]; + } + // Shortest URL for a valid URL filtering rule + const urls = []; + const rootURL = matches[1] + matches[2]; + urls.unshift(rootURL); + const path = matches[3] || ''; + let pos = path.charAt(0) === '/' ? 1 : 0; + while ( pos < path.length ) { + pos = path.indexOf('/', pos); + if ( pos === -1 ) { + pos = path.length; + } else { + pos += 1; + } + urls.unshift(rootURL + path.slice(0, pos)); + } + const query = matches[4] || ''; + if ( query !== '' ) { + urls.unshift(rootURL + path + query); + } + return urls; + }; + + const filterFromTargetRow = function() { + return dom.text(targetRow.children[COLUMN_FILTER]); + }; + + const aliasURLFromID = function(id) { + if ( id === '' ) { return ''; } + for ( const entry of loggerEntries ) { + if ( entry.id !== id || entry.aliased ) { continue; } + const fields = entry.textContent.split('\t'); + return fields[COLUMN_URL] || ''; + } + return ''; + }; + + const toSummaryPaneFilterNode = async function(receiver, filter) { + receiver.children[COLUMN_FILTER].textContent = filter; + if ( dom.cl.has(targetRow, 'canLookup') === false ) { return; } + const isException = reIsExceptionFilter.test(filter); + let isExcepted = false; + if ( isException ) { + isExcepted = await messaging.send('loggerUI', { + what: 'hasInMemoryFilter', + filter: toExceptionFilter(filter, dom.cl.has(targetRow, 'extendedRealm')), + }); + } + if ( isException && isExcepted === false ) { return; } + dom.cl.toggle(receiver, 'exceptored', isExcepted); + receiver.children[2].style.visibility = ''; + }; + + const fillSummaryPaneFilterList = async function(rows) { + const rawFilter = targetRow.children[COLUMN_FILTER].textContent; + + const nodeFromFilter = function(filter, lists) { + const fragment = document.createDocumentFragment(); + const template = qs$('#filterFinderListEntry > span'); + for ( const list of lists ) { + const span = dom.clone(template); + let a = qs$(span, 'a:nth-of-type(1)'); + a.href += encodeURIComponent(list.assetKey); + a.append(i18n.patchUnicodeFlags(list.title)); + a = qs$(span, 'a:nth-of-type(2)'); + if ( list.supportURL ) { + dom.attr(a, 'href', list.supportURL); + } else { + a.style.display = 'none'; + } + if ( fragment.childElementCount !== 0 ) { + fragment.appendChild(document.createTextNode('\n')); + } + fragment.appendChild(span); + } + return fragment; + }; + + const handleResponse = function(response) { + if ( response instanceof Object === false ) { + response = {}; + } + let bestMatchFilter = ''; + for ( const filter in response ) { + if ( filter.length > bestMatchFilter.length ) { + bestMatchFilter = filter; + } + } + if ( + bestMatchFilter !== '' && + Array.isArray(response[bestMatchFilter]) + ) { + toSummaryPaneFilterNode(rows[0], bestMatchFilter); + rows[1].children[1].appendChild(nodeFromFilter( + bestMatchFilter, + response[bestMatchFilter] + )); + } + // https://github.com/gorhill/uBlock/issues/2179 + if ( rows[1].children[1].childElementCount === 0 ) { + i18n.safeTemplateToDOM( + 'loggerStaticFilteringFinderSentence2', + { filter: rawFilter }, + rows[1].children[1] + ); + } + }; + + if ( dom.cl.has(targetRow, 'networkRealm') ) { + const response = await messaging.send('loggerUI', { + what: 'listsFromNetFilter', + rawFilter: rawFilter, + }); + handleResponse(response); + } else if ( dom.cl.has(targetRow, 'extendedRealm') ) { + const response = await messaging.send('loggerUI', { + what: 'listsFromCosmeticFilter', + url: targetRow.children[COLUMN_URL].textContent, + rawFilter: rawFilter, + }); + handleResponse(response); + } + }; + + const fillSummaryPane = function() { + const rows = qsa$(dialog, '.pane.details > div'); + const tr = targetRow; + const trcl = tr.classList; + const trch = tr.children; + let text; + // Filter and context + text = filterFromTargetRow(); + if ( + (text !== '') && + (trcl.contains('extendedRealm') || trcl.contains('networkRealm')) + ) { + toSummaryPaneFilterNode(rows[0], text); + } else { + rows[0].style.display = 'none'; + } + // Rule + if ( + (text !== '') && + ( + trcl.contains('dynamicHost') || + trcl.contains('dynamicUrl') || + trcl.contains('switchRealm') + ) + ) { + rows[2].children[1].textContent = text; + } else { + rows[2].style.display = 'none'; + } + // Filter list + if ( trcl.contains('canLookup') ) { + fillSummaryPaneFilterList(rows); + } else { + rows[1].style.display = 'none'; + } + // Root and immediate contexts + const tabhn = dom.attr(tr, 'data-tabhn') || ''; + const dochn = dom.attr(tr, 'data-dochn') || ''; + if ( tabhn !== '' && tabhn !== dochn ) { + rows[3].children[1].textContent = tabhn; + } else { + rows[3].style.display = 'none'; + } + if ( dochn !== '' ) { + rows[4].children[1].textContent = dochn; + } else { + rows[4].style.display = 'none'; + } + // Partyness + text = dom.attr(tr, 'data-parties') || ''; + if ( text !== '' ) { + rows[5].children[1].textContent = `(${trch[COLUMN_PARTYNESS].textContent})\u2002${text}`; + } else { + rows[5].style.display = 'none'; + } + // Type + text = trch[COLUMN_TYPE].textContent; + if ( text !== '' ) { + rows[6].children[1].textContent = text; + } else { + rows[6].style.display = 'none'; + } + // URL + const canonicalURL = trch[COLUMN_URL].textContent; + if ( canonicalURL !== '' ) { + const attr = dom.attr(tr, 'data-status') || ''; + if ( attr !== '' ) { + dom.attr(rows[7], 'data-status', attr); + if ( tr.hasAttribute('data-modifier') ) { + dom.attr(rows[7], 'data-modifier', ''); + } + } + rows[7].children[1].appendChild(dom.clone(trch[COLUMN_URL])); + } else { + rows[7].style.display = 'none'; + } + // Alias URL + text = dom.attr(tr, 'data-aliasid'); + const aliasURL = text ? aliasURLFromID(text) : ''; + if ( aliasURL !== '' ) { + rows[8].children[1].textContent = + hostnameFromURI(aliasURL) + ' \u21d2\n\u2003' + + hostnameFromURI(canonicalURL); + rows[9].children[1].textContent = aliasURL; + } else { + rows[8].style.display = 'none'; + rows[9].style.display = 'none'; + } + }; + + // Fill dynamic URL filtering pane + const fillDynamicPane = function() { + if ( dom.cl.has(targetRow, 'extendedRealm') ) { return; } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/662#issuecomment-509220702 + if ( targetType === 'doc' ) { return; } + + // https://github.com/gorhill/uBlock/issues/2469 + if ( targetURLs.length === 0 || reSchemeOnly.test(targetURLs[0]) ) { + return; + } + + // Fill context selector + let select = selectNode('select.dynamic.origin'); + fillOriginSelect(select, targetPageHostname, targetPageDomain); + const option = document.createElement('option'); + option.textContent = '*'; + dom.attr(option, 'value', '*'); + select.appendChild(option); + + // Fill type selector + select = selectNode('select.dynamic.type'); + select.options[0].textContent = targetType; + dom.attr(select.options[0], 'value', targetType); + select.selectedIndex = 0; + + // Fill entries + const menuEntryTemplate = qs$(dialog, '.dynamic .toolbar .entry'); + const tbody = qs$(dialog, '.dynamic .entries'); + for ( const targetURL of targetURLs ) { + const menuEntry = dom.clone(menuEntryTemplate); + dom.attr(menuEntry.children[0], 'data-url', targetURL); + menuEntry.children[1].textContent = shortenLongString(targetURL, 128); + tbody.appendChild(menuEntry); + } + + colorize(); + }; + + const fillOriginSelect = function(select, hostname, domain) { + const template = i18n$('loggerStaticFilteringSentencePartOrigin'); + let value = hostname; + for (;;) { + const option = document.createElement('option'); + dom.attr(option, 'value', value); + option.textContent = template.replace('{{origin}}', value); + select.appendChild(option); + if ( value === domain ) { break; } + const pos = value.indexOf('.'); + if ( pos === -1 ) { break; } + value = value.slice(pos + 1); + } + }; + + // Fill static filtering pane + const fillStaticPane = function() { + if ( dom.cl.has(targetRow, 'extendedRealm') ) { return; } + + const template = i18n$('loggerStaticFilteringSentence'); + const rePlaceholder = /\{\{[^}]+?\}\}/g; + const nodes = []; + let pos = 0; + for (;;) { + const match = rePlaceholder.exec(template); + if ( match === null ) { break; } + if ( pos !== match.index ) { + nodes.push(document.createTextNode(template.slice(pos, match.index))); + } + pos = rePlaceholder.lastIndex; + let select, option; + switch ( match[0] ) { + case '{{br}}': + nodes.push(document.createElement('br')); + break; + + case '{{action}}': + select = document.createElement('select'); + select.className = 'static action'; + option = document.createElement('option'); + dom.attr(option, 'value', ''); + option.textContent = i18n$('loggerStaticFilteringSentencePartBlock'); + select.appendChild(option); + option = document.createElement('option'); + dom.attr(option, 'value', '@@'); + option.textContent = i18n$('loggerStaticFilteringSentencePartAllow'); + select.appendChild(option); + nodes.push(select); + break; + + case '{{type}}': { + const filterType = staticFilterTypes[targetType] || targetType; + select = document.createElement('select'); + select.className = 'static type'; + option = document.createElement('option'); + dom.attr(option, 'value', filterType); + option.textContent = i18n$('loggerStaticFilteringSentencePartType').replace('{{type}}', filterType); + select.appendChild(option); + option = document.createElement('option'); + dom.attr(option, 'value', ''); + option.textContent = i18n$('loggerStaticFilteringSentencePartAnyType'); + select.appendChild(option); + nodes.push(select); + break; + } + case '{{url}}': + select = document.createElement('select'); + select.className = 'static url'; + for ( const targetURL of targetURLs ) { + const value = targetURL.replace(/^[a-z-]+:\/\//, ''); + option = document.createElement('option'); + dom.attr(option, 'value', value); + option.textContent = shortenLongString(value, 128); + select.appendChild(option); + } + nodes.push(select); + break; + + case '{{origin}}': + select = document.createElement('select'); + select.className = 'static origin'; + fillOriginSelect(select, targetFrameHostname, targetFrameDomain); + option = document.createElement('option'); + dom.attr(option, 'value', ''); + option.textContent = i18n$('loggerStaticFilteringSentencePartAnyOrigin'); + select.appendChild(option); + nodes.push(select); + break; + + case '{{importance}}': + select = document.createElement('select'); + select.className = 'static importance'; + option = document.createElement('option'); + dom.attr(option, 'value', ''); + option.textContent = i18n$('loggerStaticFilteringSentencePartNotImportant'); + select.appendChild(option); + option = document.createElement('option'); + dom.attr(option, 'value', 'important'); + option.textContent = i18n$('loggerStaticFilteringSentencePartImportant'); + select.appendChild(option); + nodes.push(select); + break; + + default: + break; + } + } + if ( pos < template.length ) { + nodes.push(document.createTextNode(template.slice(pos))); + } + const parent = qs$(dialog, 'div.panes > .static > div:first-of-type'); + for ( let i = 0; i < nodes.length; i++ ) { + parent.appendChild(nodes[i]); + } + parseStaticInputs(); + }; + + const moveDialog = ev => { + if ( ev.button !== 0 && ev.touches === undefined ) { return; } + const widget = qs$('#netInspector .entryTools'); + onStartMovingWidget(ev, widget, ( ) => { + vAPI.localStorage.setItem( + 'loggerUI.entryTools', + JSON.stringify({ + bottom: widget.style.bottom, + left: widget.style.left, + right: widget.style.right, + top: widget.style.top, + }) + ); + }); + }; + + const fillDialog = function(domains) { + dialog = dom.clone('#templates .netFilteringDialog'); + dom.cl.toggle( + dialog, + 'extendedRealm', + dom.cl.has(targetRow, 'extendedRealm') + ); + targetDomain = domains[0]; + targetPageDomain = domains[1]; + targetFrameDomain = domains[2]; + createPreview(targetType, targetURLs[0]); + fillSummaryPane(); + fillDynamicPane(); + fillStaticPane(); + dom.on(dialog, 'click', ev => { onClick(ev); }, true); + dom.on(dialog, 'change', onSelectChange, true); + dom.on(dialog, 'input', onInputChange, true); + const container = qs$('#netInspector .entryTools'); + if ( container.firstChild ) { + container.replaceChild(dialog, container.firstChild); + } else { + container.append(dialog); + } + const moveBand = qs$(dialog, '.moveBand'); + dom.on(moveBand, 'mousedown', moveDialog); + dom.on(moveBand, 'touchstart', moveDialog); + }; + + const toggleOn = async function(ev) { + targetRow = ev.target.closest('.canDetails'); + if ( targetRow === null ) { return; } + ev.stopPropagation(); + targetTabId = tabIdFromAttribute(targetRow); + targetType = targetRow.children[COLUMN_TYPE].textContent.trim() || ''; + targetURLs = createTargetURLs(targetRow.children[COLUMN_URL].textContent); + targetPageHostname = dom.attr(targetRow, 'data-tabhn') || ''; + targetFrameHostname = dom.attr(targetRow, 'data-dochn') || ''; + + // We need the root domain names for best user experience. + const domains = await messaging.send('loggerUI', { + what: 'getDomainNames', + targets: [ + targetURLs[0], + targetPageHostname, + targetFrameHostname + ], + }); + fillDialog(domains); + }; + + const toggleOff = function() { + const container = qs$('#netInspector .entryTools'); + if ( container.firstChild ) { + container.firstChild.remove(); + } + targetURLs = []; + targetRow = null; + dialog = null; + }; + + // Restore position of entry tools dialog + vAPI.localStorage.getItemAsync( + 'loggerUI.entryTools', + ).then(response => { + if ( typeof response !== 'string' ) { return; } + const settings = JSON.parse(response); + const widget = qs$('#netInspector .entryTools'); + widget.style.bottom = ''; + widget.style.left = settings.left || ''; + widget.style.right = settings.right || ''; + widget.style.top = settings.top || ''; + if ( /^-/.test(widget.style.top) ) { + widget.style.top = '0'; + } + }); + + dom.on( + '#netInspector', + 'click', + '.canDetails > span:not(:nth-of-type(4)):not(:nth-of-type(8))', + ev => { toggleOn(ev); } + ); + + dom.on( + '#netInspector', + 'click', + '.logEntry > div > span:nth-of-type(8) a', + ev => { + vAPI.messaging.send('codeViewer', { + what: 'gotoURL', + details: { + url: ev.target.getAttribute('href'), + select: true, + }, + }); + ev.preventDefault(); + ev.stopPropagation(); + } + ); +})(); + +/******************************************************************************/ +/******************************************************************************/ + +const rowFilterer = (( ) => { + const userFilters = []; + const builtinFilters = []; + + let masterFilterSwitch = true; + let filters = []; + + const parseInput = function() { + userFilters.length = 0; + + const rawParts = qs$('#filterInput > input').value.trim().split(/\s+/); + const n = rawParts.length; + const reStrs = []; + let not = false; + for ( let i = 0; i < n; i++ ) { + let rawPart = rawParts[i]; + if ( rawPart.charAt(0) === '!' ) { + if ( reStrs.length === 0 ) { + not = true; + } + rawPart = rawPart.slice(1); + } + let reStr = ''; + if ( rawPart.startsWith('/') && rawPart.endsWith('/') ) { + reStr = rawPart.slice(1, -1); + try { + new RegExp(reStr); + } catch(ex) { + reStr = ''; + } + } + if ( reStr === '' ) { + const hardBeg = rawPart.startsWith('|'); + if ( hardBeg ) { + rawPart = rawPart.slice(1); + } + const hardEnd = rawPart.endsWith('|'); + if ( hardEnd ) { + rawPart = rawPart.slice(0, -1); + } + // https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions + reStr = rawPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + // https://github.com/orgs/uBlockOrigin/teams/ublock-issues-volunteers/discussions/51 + // Be more flexible when interpreting leading/trailing pipes, + // as leading/trailing pipes are often used in static filters. + if ( hardBeg ) { + reStr = reStr !== '' ? '(?:^|\\s|\\|)' + reStr : '\\|'; + } + if ( hardEnd ) { + reStr += '(?:\\||\\s|$)'; + } + } + if ( reStr === '' ) { continue; } + reStrs.push(reStr); + if ( i < (n - 1) && rawParts[i + 1] === '||' ) { + i += 1; + continue; + } + reStr = reStrs.length === 1 ? reStrs[0] : reStrs.join('|'); + userFilters.push({ + re: new RegExp(reStr, 'i'), + r: !not + }); + reStrs.length = 0; + not = false; + } + filters = builtinFilters.concat(userFilters); + }; + + const filterOne = function(logEntry) { + if ( + logEntry.dead || + selectedTabId !== 0 && + ( + logEntry.tabId === undefined || + logEntry.tabId > 0 && logEntry.tabId !== selectedTabId + ) + ) { + return false; + } + + if ( masterFilterSwitch === false || filters.length === 0 ) { + return true; + } + + // Do not filter out tab load event, they help separate key sections + // of logger. + if ( logEntry.type === 'tabLoad' ) { return true; } + + for ( const f of filters ) { + if ( f.re.test(logEntry.textContent) !== f.r ) { return false; } + } + return true; + }; + + const filterAll = function() { + filteredLoggerEntries = []; + filteredLoggerEntryVoidedCount = 0; + for ( const entry of loggerEntries ) { + if ( filterOne(entry) === false ) { continue; } + filteredLoggerEntries.push(entry); + if ( entry.voided ) { + filteredLoggerEntryVoidedCount += 1; + } + } + viewPort.updateContent(0); + dom.cl.toggle('#filterButton', 'active', filters.length !== 0); + dom.cl.toggle('#clean', 'disabled', filteredLoggerEntryVoidedCount === 0); + dom.cl.toggle('#clear', 'disabled', filteredLoggerEntries.length === 0); + }; + + const onFilterChangedAsync = (( ) => { + const commit = ( ) => { + parseInput(); + filterAll(); + }; + const timer = vAPI.defer.create(commit); + return ( ) => { + timer.offon(750); + }; + })(); + + const onFilterButton = function() { + masterFilterSwitch = !masterFilterSwitch; + dom.cl.toggle('#netInspector', 'f', masterFilterSwitch); + filterAll(); + }; + + const onToggleExtras = function(ev) { + dom.cl.toggle(ev.target, 'expanded'); + }; + + const builtinFilterExpression = function() { + builtinFilters.length = 0; + const filtexElems = qsa$('#filterExprPicker [data-filtex]'); + const orExprs = []; + let not = false; + for ( const filtexElem of filtexElems ) { + const filtex = filtexElem.dataset.filtex; + const active = dom.cl.has(filtexElem, 'on'); + if ( filtex === '!' ) { + if ( orExprs.length !== 0 ) { + builtinFilters.push({ + re: new RegExp(orExprs.join('|')), + r: !not + }); + orExprs.length = 0; + } + not = active; + } else if ( active ) { + orExprs.push(filtex); + } + } + if ( orExprs.length !== 0 ) { + builtinFilters.push({ + re: new RegExp(orExprs.join('|')), + r: !not + }); + } + filters = builtinFilters.concat(userFilters); + dom.cl.toggle('#filterExprButton', 'active', builtinFilters.length !== 0); + filterAll(); + }; + + dom.on('#filterButton', 'click', onFilterButton); + dom.on('#filterInput > input', 'input', onFilterChangedAsync); + dom.on('#filterExprButton', 'click', onToggleExtras); + dom.on('#filterExprPicker', 'click', '[data-filtex]', ev => { + dom.cl.toggle(ev.target, 'on'); + builtinFilterExpression(); + }); + dom.on('#filterInput > input', 'drop', ev => { + const dropItem = item => { + if ( item.kind !== 'string' ) { return false; } + if ( item.type !== 'text/plain' ) { return false; } + item.getAsString(s => { + qs$('#filterInput > input').value = s; + parseInput(); + filterAll(); + }); + return true; + }; + for ( const item of ev.dataTransfer.items ) { + if ( dropItem(item) === false ) { continue; } + ev.preventDefault(); + break; + } + }); + + // https://github.com/gorhill/uBlock/issues/404 + // Ensure page state is in sync with the state of its various widgets. + parseInput(); + builtinFilterExpression(); + filterAll(); + + return { filterOne, filterAll }; +})(); + +/******************************************************************************/ + +// Discard logger entries to prevent undue memory usage growth. The criteria +// to discard are multiple and user configurable: +// +// - Max number of page load per distinct tab +// - Max number of entry per distinct tab +// - Max entry age + +const rowJanitor = (( ) => { + const tabIdToDiscard = new Set(); + const tabIdToLoadCountMap = new Map(); + const tabIdToEntryCountMap = new Map(); + + let rowIndex = 0; + + const discard = function(deadline) { + const opts = loggerSettings.discard; + const maxLoadCount = typeof opts.maxLoadCount === 'number' + ? opts.maxLoadCount + : 0; + const maxEntryCount = typeof opts.maxEntryCount === 'number' + ? opts.maxEntryCount + : 0; + const obsolete = typeof opts.maxAge === 'number' + ? Date.now() - opts.maxAge * 60000 + : 0; + + let i = rowIndex; + // TODO: below should not happen -- remove when confirmed. + if ( i >= loggerEntries.length ) { + i = 0; + } + + if ( i === 0 ) { + tabIdToDiscard.clear(); + tabIdToLoadCountMap.clear(); + tabIdToEntryCountMap.clear(); + } + + let idel = -1; + let bufferedTabId = 0; + let bufferedEntryCount = 0; + let modified = false; + + while ( i < loggerEntries.length ) { + + if ( i % 64 === 0 && deadline.timeRemaining() === 0 ) { break; } + + const entry = loggerEntries[i]; + const tabId = entry.tabId || 0; + + if ( entry.dead || tabIdToDiscard.has(tabId) ) { + if ( idel === -1 ) { idel = i; } + i += 1; + continue; + } + + if ( maxLoadCount !== 0 && entry.type === 'tabLoad' ) { + let count = (tabIdToLoadCountMap.get(tabId) || 0) + 1; + tabIdToLoadCountMap.set(tabId, count); + if ( count >= maxLoadCount ) { + tabIdToDiscard.add(tabId); + } + } + + if ( maxEntryCount !== 0 ) { + if ( bufferedTabId !== tabId ) { + if ( bufferedEntryCount !== 0 ) { + tabIdToEntryCountMap.set(bufferedTabId, bufferedEntryCount); + } + bufferedTabId = tabId; + bufferedEntryCount = tabIdToEntryCountMap.get(tabId) || 0; + } + bufferedEntryCount += 1; + if ( bufferedEntryCount >= maxEntryCount ) { + tabIdToDiscard.add(bufferedTabId); + } + } + + // Since entries in the logger are chronologically ordered, + // everything below obsolete is to be discarded. + if ( obsolete !== 0 && entry.tstamp <= obsolete ) { + if ( idel === -1 ) { idel = i; } + break; + } + + if ( idel !== -1 ) { + loggerEntries.copyWithin(idel, i); + loggerEntries.length -= i - idel; + idel = -1; + modified = true; + } + + i += 1; + } + + if ( idel !== -1 ) { + loggerEntries.length = idel; + modified = true; + } + + if ( i >= loggerEntries.length ) { i = 0; } + rowIndex = i; + + if ( rowIndex === 0 ) { + tabIdToDiscard.clear(); + tabIdToLoadCountMap.clear(); + tabIdToEntryCountMap.clear(); + } + + if ( modified === false ) { return; } + + rowFilterer.filterAll(); + }; + + const discardAsync = function(deadline) { + if ( deadline ) { + discard(deadline); + } + janitorTimer.onidle(1889); + }; + + const janitorTimer = vAPI.defer.create(discardAsync); + + // Clear voided entries from the logger's visible content. + // + // Voided entries should be visible only from the "All" option of the + // tab selector. + // + const clean = function() { + if ( filteredLoggerEntries.length === 0 ) { return; } + + let j = 0; + let targetEntry = filteredLoggerEntries[0]; + for ( const entry of loggerEntries ) { + if ( entry !== targetEntry ) { continue; } + if ( entry.voided ) { + entry.dead = true; + } + j += 1; + if ( j === filteredLoggerEntries.length ) { break; } + targetEntry = filteredLoggerEntries[j]; + } + rowFilterer.filterAll(); + }; + + // Clear the logger's visible content. + // + // "Unrelated" entries -- shown for convenience -- will be also cleared + // if and only if the filtered logger content is made entirely of unrelated + // entries. In effect, this means clicking a second time on the eraser will + // cause unrelated entries to also be cleared. + // + const clear = function() { + if ( filteredLoggerEntries.length === 0 ) { return; } + + let clearUnrelated = true; + if ( selectedTabId !== 0 ) { + for ( const entry of filteredLoggerEntries ) { + if ( entry.tabId === selectedTabId ) { + clearUnrelated = false; + break; + } + } + } + + let j = 0; + let targetEntry = filteredLoggerEntries[0]; + for ( const entry of loggerEntries ) { + if ( entry !== targetEntry ) { continue; } + if ( entry.tabId === selectedTabId || clearUnrelated ) { + entry.dead = true; + } + j += 1; + if ( j === filteredLoggerEntries.length ) { break; } + targetEntry = filteredLoggerEntries[j]; + } + rowFilterer.filterAll(); + }; + + discardAsync(); + + dom.on('#clean', 'click', clean); + dom.on('#clear', 'click', clear); + + return { + inserted: function(count) { + if ( rowIndex !== 0 ) { + rowIndex += count; + } + }, + }; +})(); + +/******************************************************************************/ + +const pauseNetInspector = function() { + netInspectorPaused = dom.cl.toggle('#netInspector', 'paused'); +}; + +/******************************************************************************/ + +const toggleVCompactView = function() { + dom.cl.toggle('#netInspector .vCompactToggler', 'vExpanded'); + viewPort.updateLayout(); +}; + +/******************************************************************************/ + +const popupManager = (( ) => { + let realTabId = 0; + let popup = null; + let popupObserver = null; + + const resizePopup = function() { + if ( popup === null ) { return; } + const popupBody = popup.contentWindow.document.body; + if ( popupBody.clientWidth !== 0 && popup.clientWidth !== popupBody.clientWidth ) { + popup.style.setProperty('width', popupBody.clientWidth + 'px'); + } + if ( popupBody.clientHeight !== 0 && popup.clientHeight !== popupBody.clientHeight ) { + popup.style.setProperty('height', popupBody.clientHeight + 'px'); + } + }; + + const onLoad = function() { + resizePopup(); + popupObserver.observe(popup.contentDocument.body, { + subtree: true, + attributes: true + }); + }; + + const setTabId = function(tabId) { + if ( popup === null ) { return; } + dom.attr(popup, 'src', `popup-fenix.html?portrait=1&tabId=${tabId}`); + }; + + const onTabIdChanged = function() { + const tabId = tabIdFromPageSelector(); + if ( tabId === 0 ) { return toggleOff(); } + realTabId = tabId; + setTabId(realTabId); + }; + + const toggleOn = function() { + const tabId = tabIdFromPageSelector(); + if ( tabId === 0 ) { return; } + realTabId = tabId; + + popup = qs$('#popupContainer'); + + dom.on(popup, 'load', onLoad); + popupObserver = new MutationObserver(resizePopup); + + const parent = qs$('#inspectors'); + const rect = parent.getBoundingClientRect(); + popup.style.setProperty('right', `${rect.right - parent.clientWidth}px`); + dom.cl.add(parent, 'popupOn'); + + dom.on(document, 'tabIdChanged', onTabIdChanged); + + setTabId(realTabId); + dom.cl.add('#showpopup', 'active'); + }; + + const toggleOff = function() { + dom.cl.remove('#showpopup', 'active'); + dom.off(document, 'tabIdChanged', onTabIdChanged); + dom.cl.remove('#inspectors', 'popupOn'); + dom.off(popup, 'load', onLoad); + popupObserver.disconnect(); + popupObserver = null; + dom.attr(popup, 'src', ''); + + realTabId = 0; + }; + + const api = { + get tabId() { return realTabId || 0; }, + toggleOff: function() { + if ( realTabId !== 0 ) { + toggleOff(); + } + } + }; + + dom.on('#showpopup', 'click', ( ) => { + void (realTabId === 0 ? toggleOn() : toggleOff()); + }); + + return api; +})(); + +/******************************************************************************/ + +// Filter hit stats' MVP ("minimum viable product") +// +const loggerStats = (( ) => { + const enabled = false; + const filterHits = new Map(); + let dialog; + let timer; + const makeRow = function() { + const div = document.createElement('div'); + div.appendChild(document.createElement('span')); + div.appendChild(document.createElement('span')); + return div; + }; + + const fillRow = function(div, entry) { + div.children[0].textContent = entry[1].toLocaleString(); + div.children[1].textContent = entry[0]; + }; + + const updateList = function() { + const sortedHits = Array.from(filterHits).sort((a, b) => { + return b[1] - a[1]; + }); + + const doc = document; + const parent = qs$(dialog, '.sortedEntries'); + let i = 0; + + // Reuse existing rows + for ( let iRow = 0; iRow < parent.childElementCount; iRow++ ) { + if ( i === sortedHits.length ) { break; } + fillRow(parent.children[iRow], sortedHits[i]); + i += 1; + } + + // Append new rows + if ( i < sortedHits.length ) { + const list = doc.createDocumentFragment(); + for ( ; i < sortedHits.length; i++ ) { + const div = makeRow(); + fillRow(div, sortedHits[i]); + list.appendChild(div); + } + parent.appendChild(list); + } + + // Remove extraneous rows + // [Should never happen at this point in this current + // bare-bone implementation] + }; + + const toggleOn = function() { + dialog = modalDialog.create( + '#loggerStatsDialog', + ( ) => { + dialog = undefined; + if ( timer !== undefined ) { + self.cancelIdleCallback(timer); + timer = undefined; + } + } + ); + updateList(); + modalDialog.show(); + }; + + dom.on('#loggerStats', 'click', toggleOn); + + return { + processFilter: function(filter) { + if ( enabled !== true ) { return; } + if ( filter.source !== 'static' && filter.source !== 'cosmetic' ) { + return; + } + filterHits.set(filter.raw, (filterHits.get(filter.raw) || 0) + 1); + if ( dialog === undefined || timer !== undefined ) { return; } + timer = self.requestIdleCallback( + ( ) => { + timer = undefined; + updateList(); + }, + { timeout: 2001 } + ); + } + }; +})(); + +/******************************************************************************/ + +(( ) => { + const lines = []; + const options = { + format: 'list', + encoding: 'markdown', + time: 'anonymous', + }; + let dialog; + + const collectLines = function() { + lines.length = 0; + let t0 = filteredLoggerEntries.length !== 0 + ? filteredLoggerEntries[filteredLoggerEntries.length - 1].tstamp + : 0; + for ( const entry of filteredLoggerEntries ) { + const text = entry.textContent; + const fields = []; + let i = 0; + let beg = text.indexOf('\t'); + if ( beg === 0 ) { continue; } + let timeField = text.slice(0, beg); + if ( options.time === 'anonymous' ) { + timeField = '+' + Math.round((entry.tstamp - t0) / 1000).toString(); + } + fields.push(timeField); + beg += 1; + while ( beg < text.length ) { + let end = text.indexOf('\t', beg); + if ( end === -1 ) { end = text.length; } + fields.push(text.slice(beg, end)); + beg = end + 1; + i += 1; + } + lines.push(fields); + } + }; + + const formatAsPlainTextTable = function() { + const outputAll = []; + for ( const fields of lines ) { + outputAll.push(fields.join('\t')); + } + outputAll.push(''); + return outputAll.join('\n'); + }; + + const formatAsMarkdownTable = function() { + const outputAll = []; + let fieldCount = 0; + for ( const fields of lines ) { + if ( fields.length <= 2 ) { continue; } + if ( fields.length > fieldCount ) { + fieldCount = fields.length; + } + const outputOne = []; + for ( let i = 0; i < fields.length; i++ ) { + const field = fields[i]; + let code = /\b(?:www\.|https?:\/\/)/.test(field) ? '`' : ''; + outputOne.push(` ${code}${field.replace(/\|/g, '\\|')}${code} `); + } + outputAll.push(outputOne.join('|')); + } + if ( fieldCount !== 0 ) { + outputAll.unshift( + `${' |'.repeat(fieldCount-1)} `, + `${':--- |'.repeat(fieldCount-1)}:--- ` + ); + } + return `

Logger output\n\n|${outputAll.join('|\n|')}|\n
\n`; + }; + + const formatAsTable = function() { + if ( options.encoding === 'plain' ) { + return formatAsPlainTextTable(); + } + return formatAsMarkdownTable(); + }; + + const formatAsList = function() { + const outputAll = []; + for ( const fields of lines ) { + const outputOne = []; + for ( let i = 0; i < fields.length; i++ ) { + let str = fields[i]; + if ( str.length === 0 ) { continue; } + outputOne.push(str); + } + outputAll.push(outputOne.join('\n')); + } + let before, between, after; + if ( options.encoding === 'markdown' ) { + const code = '```'; + before = `
Logger output\n\n${code}\n`; + between = `\n${code}\n${code}\n`; + after = `\n${code}\n
\n`; + } else { + before = ''; + between = '\n\n'; + after = '\n'; + } + return `${before}${outputAll.join(between)}${after}`; + }; + + const format = function() { + const output = qs$(dialog, '.output'); + if ( options.format === 'list' ) { + output.textContent = formatAsList(); + } else { + output.textContent = formatAsTable(); + } + }; + + const setRadioButton = function(group, value) { + if ( options.hasOwnProperty(group) === false ) { return; } + const groupEl = qs$(dialog, `[data-radio="${group}"]`); + const buttonEls = qsa$(groupEl, '[data-radio-item]'); + for ( const buttonEl of buttonEls ) { + dom.cl.toggle( + buttonEl, + 'on', + dom.attr(buttonEl, 'data-radio-item') === value + ); + } + options[group] = value; + }; + + const onOption = function(ev) { + const target = ev.target.closest('span[data-i18n]'); + if ( target === null ) { return; } + + // Copy to clipboard + if ( target.matches('.pushbutton') ) { + const textarea = qs$(dialog, 'textarea'); + textarea.focus(); + if ( textarea.selectionEnd === textarea.selectionStart ) { + textarea.select(); + } + document.execCommand('copy'); + ev.stopPropagation(); + return; + } + + // Radio buttons + const group = target.closest('[data-radio]'); + if ( group === null ) { return; } + if ( target.matches('span.on') ) { return; } + const item = target.closest('[data-radio-item]'); + if ( item === null ) { return; } + setRadioButton( + dom.attr(group, 'data-radio'), + dom.attr(item, 'data-radio-item') + ); + format(); + ev.stopPropagation(); + }; + + const toggleOn = function() { + dialog = modalDialog.create( + '#loggerExportDialog', + ( ) => { + dialog = undefined; + lines.length = 0; + } + ); + + setRadioButton('format', options.format); + setRadioButton('encoding', options.encoding); + + collectLines(); + format(); + + dom.on(qs$(dialog, '.options'), 'click', onOption, { capture: true }); + + modalDialog.show(); + }; + + dom.on('#loggerExport', 'click', toggleOn); +})(); + +/******************************************************************************/ + +// TODO: +// - Give some thoughts to: +// - an option to discard immediately filtered out new entries +// - max entry count _per load_ +// +const loggerSettings = (( ) => { + const settings = { + discard: { + maxAge: 240, // global + maxEntryCount: 2000, // per-tab + maxLoadCount: 20, // per-tab + }, + columns: [ true, true, true, true, true, true, true, true, true ], + linesPerEntry: 4, + }; + + vAPI.localStorage.getItemAsync('loggerSettings').then(value => { + try { + const stored = JSON.parse(value); + if ( typeof stored.discard.maxAge === 'number' ) { + settings.discard.maxAge = stored.discard.maxAge; + } + if ( typeof stored.discard.maxEntryCount === 'number' ) { + settings.discard.maxEntryCount = stored.discard.maxEntryCount; + } + if ( typeof stored.discard.maxLoadCount === 'number' ) { + settings.discard.maxLoadCount = stored.discard.maxLoadCount; + } + if ( typeof stored.linesPerEntry === 'number' ) { + settings.linesPerEntry = stored.linesPerEntry; + } + if ( Array.isArray(stored.columns) ) { + settings.columns = stored.columns; + } + } catch(ex) { + } + }); + + const valueFromInput = function(input, def) { + let value = parseInt(input.value, 10); + if ( isNaN(value) ) { value = def; } + const min = parseInt(dom.attr(input, 'min'), 10); + if ( isNaN(min) === false ) { + value = Math.max(value, min); + } + const max = parseInt(dom.attr(input, 'max'), 10); + if ( isNaN(max) === false ) { + value = Math.min(value, max); + } + return value; + }; + + const toggleOn = function() { + const dialog = modalDialog.create( + '#loggerSettingsDialog', + dialog => { + toggleOff(dialog); + } + ); + + // Number inputs + let inputs = qsa$(dialog, 'input[type="number"]'); + inputs[0].value = settings.discard.maxAge; + inputs[1].value = settings.discard.maxLoadCount; + inputs[2].value = settings.discard.maxEntryCount; + inputs[3].value = settings.linesPerEntry; + dom.on(inputs[3], 'input', ev => { + settings.linesPerEntry = valueFromInput(ev.target, 4); + viewPort.updateLayout(); + }); + + // Column checkboxs + const onColumnChanged = ev => { + const input = ev.target; + const i = parseInt(dom.attr(input, 'data-column'), 10); + settings.columns[i] = input.checked !== true; + viewPort.updateLayout(); + }; + inputs = qsa$(dialog, 'input[type="checkbox"][data-column]'); + for ( const input of inputs ) { + const i = parseInt(dom.attr(input, 'data-column'), 10); + input.checked = settings.columns[i] === false; + dom.on(input, 'change', onColumnChanged); + } + + modalDialog.show(); + }; + + const toggleOff = function(dialog) { + // Number inputs + let inputs = qsa$(dialog, 'input[type="number"]'); + settings.discard.maxAge = valueFromInput(inputs[0], 240); + settings.discard.maxLoadCount = valueFromInput(inputs[1], 25); + settings.discard.maxEntryCount = valueFromInput(inputs[2], 2000); + settings.linesPerEntry = valueFromInput(inputs[3], 4); + + // Column checkboxs + inputs = qsa$(dialog, 'input[type="checkbox"][data-column]'); + for ( const input of inputs ) { + const i = parseInt(dom.attr(input, 'data-column'), 10); + settings.columns[i] = input.checked !== true; + } + + vAPI.localStorage.setItem( + 'loggerSettings', + JSON.stringify(settings) + ); + + viewPort.updateLayout(); + }; + + dom.on('#loggerSettings', 'click', toggleOn); + + return settings; +})(); + +/******************************************************************************/ + +logger.resize = (function() { + let timer; + + const resize = function() { + const vrect = dom.body.getBoundingClientRect(); + for ( const elem of qsa$('.vscrollable') ) { + const crect = elem.getBoundingClientRect(); + const dh = crect.bottom - vrect.bottom; + if ( dh === 0 ) { continue; } + elem.style.height = Math.ceil(crect.height - dh) + 'px'; + } + }; + + const resizeAsync = function() { + if ( timer !== undefined ) { return; } + timer = self.requestAnimationFrame(( ) => { + timer = undefined; + resize(); + }); + }; + + resizeAsync(); + + dom.on(window, 'resize', resizeAsync, { passive: true }); + + return resizeAsync; +})(); + +/******************************************************************************/ + +const grabView = function() { + if ( logger.ownerId === undefined ) { + logger.ownerId = Date.now(); + } + readLogBuffer(); +}; + +const releaseView = function() { + if ( logger.ownerId === undefined ) { return; } + vAPI.messaging.send('loggerUI', { + what: 'releaseView', + ownerId: logger.ownerId, + }); + logger.ownerId = undefined; +}; + +dom.on(window, 'pagehide', releaseView); +dom.on(window, 'pageshow', grabView); +// https://bugzilla.mozilla.org/show_bug.cgi?id=1398625 +dom.on(window, 'beforeunload', releaseView); + +/******************************************************************************/ + +dom.on('#pageSelector', 'change', pageSelectorChanged); +dom.on('#netInspector .vCompactToggler', 'click', toggleVCompactView); +dom.on('#pause', 'click', pauseNetInspector); + +// https://github.com/gorhill/uBlock/issues/507 +// Ensure tab selector is in sync with URL hash +pageSelectorFromURLHash(); +dom.on(window, 'hashchange', pageSelectorFromURLHash); + +// Start to watch the current window geometry 2 seconds after the document +// is loaded, to be sure no spurious geometry changes will be triggered due +// to the window geometry pontentially not settling fast enough. +if ( self.location.search.includes('popup=1') ) { + dom.on(window, 'load', ( ) => { + vAPI.defer.once(2000).then(( ) => { + popupLoggerBox = { + x: self.screenX, + y: self.screenY, + w: self.outerWidth, + h: self.outerHeight, + }; + }); + }, { once: true }); +} + +/******************************************************************************/ diff --git a/src/js/logger.js b/src/js/logger.js new file mode 100644 index 0000000..5d1114f --- /dev/null +++ b/src/js/logger.js @@ -0,0 +1,88 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import { broadcastToAll } from './broadcast.js'; + +/******************************************************************************/ + +let buffer = null; +let lastReadTime = 0; +let writePtr = 0; + +// After 30 seconds without being read, the logger buffer will be considered +// unused, and thus disabled. +const logBufferObsoleteAfter = 30 * 1000; + +const janitorTimer = vAPI.defer.create(( ) => { + if ( buffer === null ) { return; } + if ( lastReadTime >= (Date.now() - logBufferObsoleteAfter) ) { + return janitorTimer.on(logBufferObsoleteAfter); + } + logger.enabled = false; + buffer = null; + writePtr = 0; + logger.ownerId = undefined; + broadcastToAll({ what: 'loggerDisabled' }); +}); + +const boxEntry = function(details) { + if ( details.tstamp === undefined ) { + details.tstamp = Date.now(); + } + return JSON.stringify(details); +}; + +const logger = { + enabled: false, + ownerId: undefined, + writeOne: function(details) { + if ( buffer === null ) { return; } + const box = boxEntry(details); + if ( writePtr === buffer.length ) { + buffer.push(box); + } else { + buffer[writePtr] = box; + } + writePtr += 1; + }, + readAll: function(ownerId) { + this.ownerId = ownerId; + if ( buffer === null ) { + this.enabled = true; + buffer = []; + janitorTimer.on(logBufferObsoleteAfter); + } + const out = buffer.slice(0, writePtr); + writePtr = 0; + lastReadTime = Date.now(); + return out; + }, +}; + +/******************************************************************************/ + +export default logger; + +/******************************************************************************/ diff --git a/src/js/lz4.js b/src/js/lz4.js new file mode 100644 index 0000000..608cdd8 --- /dev/null +++ b/src/js/lz4.js @@ -0,0 +1,190 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2018-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 +*/ + +/* global lz4BlockCodec */ + +'use strict'; + +/******************************************************************************/ + +import µb from './background.js'; + +/******************************************************************************* + + Experimental support for storage compression. + + For background information on the topic, see: + https://github.com/uBlockOrigin/uBlock-issues/issues/141#issuecomment-407737186 + +**/ + +/******************************************************************************/ + +let promisedInstance; +let textEncoder, textDecoder; +let ttlCount = 0; +let ttlDelay = 60000; + +const init = function() { + ttlDelay = µb.hiddenSettings.autoUpdateAssetFetchPeriod * 2 * 1000; + if ( promisedInstance === undefined ) { + let flavor; + if ( µb.hiddenSettings.disableWebAssembly === true ) { + flavor = 'js'; + } + promisedInstance = lz4BlockCodec.createInstance(flavor); + } + return promisedInstance; +}; + +// We can't shrink memory usage of lz4 codec instances, and in the +// current case memory usage can grow to a significant amount given +// that a single contiguous memory buffer is required to accommodate +// both input and output data. Thus a time-to-live implementation +// which will cause the wasm instance to be forgotten after enough +// time elapse without the instance being used. + +const destroy = function() { + //if ( lz4CodecInstance !== undefined ) { + // console.info( + // 'uBO: freeing lz4-block-codec instance (%s KB)', + // lz4CodecInstance.bytesInUse() >>> 10 + // ); + //} + promisedInstance = undefined; + textEncoder = textDecoder = undefined; + ttlCount = 0; +}; + +const ttlTimer = vAPI.defer.create(destroy); + +const ttlManage = function(count) { + ttlTimer.off(); + ttlCount += count; + if ( ttlCount > 0 ) { return; } + ttlTimer.on(ttlDelay); +}; + +const encodeValue = function(lz4CodecInstance, dataIn) { + if ( !lz4CodecInstance ) { return; } + //let t0 = window.performance.now(); + if ( textEncoder === undefined ) { + textEncoder = new TextEncoder(); + } + const inputArray = textEncoder.encode(dataIn); + const inputSize = inputArray.byteLength; + const outputArray = lz4CodecInstance.encodeBlock(inputArray, 8); + if ( outputArray instanceof Uint8Array === false ) { return; } + outputArray[0] = 0x18; + outputArray[1] = 0x4D; + outputArray[2] = 0x22; + outputArray[3] = 0x04; + outputArray[4] = (inputSize >>> 0) & 0xFF; + outputArray[5] = (inputSize >>> 8) & 0xFF; + outputArray[6] = (inputSize >>> 16) & 0xFF; + outputArray[7] = (inputSize >>> 24) & 0xFF; + //console.info( + // 'uBO: [%s] compressed %d KB => %d KB (%s%%) in %s ms', + // inputArray.byteLength >> 10, + // outputArray.byteLength >> 10, + // (outputArray.byteLength / inputArray.byteLength * 100).toFixed(0), + // (window.performance.now() - t0).toFixed(1) + //); + return outputArray; +}; + +const decodeValue = function(lz4CodecInstance, inputArray) { + if ( !lz4CodecInstance ) { return; } + //let t0 = window.performance.now(); + if ( + inputArray[0] !== 0x18 || inputArray[1] !== 0x4D || + inputArray[2] !== 0x22 || inputArray[3] !== 0x04 + ) { + console.error('decodeValue: invalid input array'); + return; + } + const outputSize = + (inputArray[4] << 0) | (inputArray[5] << 8) | + (inputArray[6] << 16) | (inputArray[7] << 24); + const outputArray = lz4CodecInstance.decodeBlock(inputArray, 8, outputSize); + if ( outputArray instanceof Uint8Array === false ) { return; } + if ( textDecoder === undefined ) { + textDecoder = new TextDecoder(); + } + const s = textDecoder.decode(outputArray); + //console.info( + // 'uBO: [%s] decompressed %d KB => %d KB (%s%%) in %s ms', + // inputArray.byteLength >>> 10, + // outputSize >>> 10, + // (inputArray.byteLength / outputSize * 100).toFixed(0), + // (window.performance.now() - t0).toFixed(1) + //); + return s; +}; + +const lz4Codec = { + // Arguments: + // dataIn: must be a string + // Returns: + // A Uint8Array, or the input string as is if compression is not + // possible. + encode: async function(dataIn, serialize = undefined) { + if ( typeof dataIn !== 'string' || dataIn.length < 4096 ) { + return dataIn; + } + ttlManage(1); + const lz4CodecInstance = await init(); + let dataOut = encodeValue(lz4CodecInstance, dataIn); + ttlManage(-1); + if ( serialize instanceof Function ) { + dataOut = await serialize(dataOut); + } + return dataOut || dataIn; + }, + // Arguments: + // dataIn: must be a Uint8Array + // Returns: + // A string, or the input argument as is if decompression is not + // possible. + decode: async function(dataIn, deserialize = undefined) { + if ( deserialize instanceof Function ) { + dataIn = await deserialize(dataIn); + } + if ( dataIn instanceof Uint8Array === false ) { + return dataIn; + } + ttlManage(1); + const lz4CodecInstance = await init(); + const dataOut = decodeValue(lz4CodecInstance, dataIn); + ttlManage(-1); + return dataOut || dataIn; + }, + relinquish: function() { + ttlDelay = 1; + ttlManage(0); + }, +}; + +/******************************************************************************/ + +export default lz4Codec; + +/******************************************************************************/ diff --git a/src/js/messaging.js b/src/js/messaging.js new file mode 100644 index 0000000..52242b3 --- /dev/null +++ b/src/js/messaging.js @@ -0,0 +1,2195 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ + +import publicSuffixList from '../lib/publicsuffixlist/publicsuffixlist.js'; +import punycode from '../lib/punycode.js'; + +import { filteringBehaviorChanged } from './broadcast.js'; +import cacheStorage from './cachestorage.js'; +import cosmeticFilteringEngine from './cosmetic-filtering.js'; +import htmlFilteringEngine from './html-filtering.js'; +import logger from './logger.js'; +import lz4Codec from './lz4.js'; +import io from './assets.js'; +import scriptletFilteringEngine from './scriptlet-filtering.js'; +import staticFilteringReverseLookup from './reverselookup.js'; +import staticNetFilteringEngine from './static-net-filtering.js'; +import µb from './background.js'; +import webRequest from './traffic.js'; +import { denseBase64 } from './base64-custom.js'; +import { dnrRulesetFromRawLists } from './static-dnr-filtering.js'; +import { i18n$ } from './i18n.js'; +import { redirectEngine } from './redirect-engine.js'; +import * as sfp from './static-filtering-parser.js'; + +import { + permanentFirewall, + sessionFirewall, + permanentSwitches, + sessionSwitches, + permanentURLFiltering, + sessionURLFiltering, +} from './filtering-engines.js'; + +import { + domainFromHostname, + domainFromURI, + entityFromDomain, + hostnameFromURI, + isNetworkURI, +} from './uri-utils.js'; + +import './benchmarks.js'; + +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/710 +// Listeners have a name and a "privileged" status. +// The nameless default handler is always deemed "privileged". +// Messages from privileged ports must never relayed to listeners +// which are not privileged. + +/******************************************************************************/ +/******************************************************************************/ + +// Default handler +// privileged + +{ +// >>>>> start of local scope + +const clickToLoad = function(request, sender) { + const { tabId, frameId } = sender; + if ( tabId === undefined || frameId === undefined ) { return false; } + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore === null ) { return false; } + pageStore.clickToLoad(frameId, request.frameURL); + return true; +}; + +const getDomainNames = function(targets) { + return targets.map(target => { + if ( typeof target !== 'string' ) { return ''; } + return target.indexOf('/') !== -1 + ? domainFromURI(target) || '' + : domainFromHostname(target) || target; + }); +}; + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'getAssetContent': + // https://github.com/chrisaljoudi/uBlock/issues/417 + io.get(request.url, { + dontCache: true, + needSourceURL: true, + }).then(result => { + result.trustedSource = µb.isTrustedList(result.assetKey); + callback(result); + }); + return; + + case 'listsFromNetFilter': + staticFilteringReverseLookup.fromNetFilter( + request.rawFilter + ).then(response => { + callback(response); + }); + return; + + case 'listsFromCosmeticFilter': + staticFilteringReverseLookup.fromExtendedFilter( + request + ).then(response => { + callback(response); + }); + return; + + case 'reloadAllFilters': + µb.loadFilterLists().then(( ) => { callback(); }); + return; + + case 'scriptlet': + vAPI.tabs.executeScript(request.tabId, { + file: `/js/scriptlets/${request.scriptlet}.js` + }).then(result => { + callback(result); + }); + return; + + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'applyFilterListSelection': + response = µb.applyFilterListSelection(request); + break; + + case 'clickToLoad': + response = clickToLoad(request, sender); + break; + + case 'createUserFilter': + µb.createUserFilters(request); + break; + + case 'getAppData': + response = { + name: browser.runtime.getManifest().name, + version: vAPI.app.version, + canBenchmark: µb.hiddenSettings.benchmarkDatasetURL !== 'unset', + }; + break; + + case 'getDomainNames': + response = getDomainNames(request.targets); + break; + + case 'getTrustedScriptletTokens': + response = redirectEngine.getTrustedScriptletTokens(); + break; + + case 'getWhitelist': + response = { + whitelist: µb.arrayFromWhitelist(µb.netWhitelist), + whitelistDefault: µb.netWhitelistDefault, + reBadHostname: µb.reWhitelistBadHostname.source, + reHostnameExtractor: µb.reWhitelistHostnameExtractor.source + }; + break; + + case 'launchElementPicker': + // Launched from some auxiliary pages, clear context menu coords. + µb.epickerArgs.mouse = false; + µb.elementPickerExec(request.tabId, 0, request.targetURL, request.zap); + break; + + case 'loggerDisabled': + µb.clearInMemoryFilters(); + break; + + case 'gotoURL': + µb.openNewTab(request.details); + break; + + case 'readyToFilter': + response = µb.readyToFilter; + break; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1954 + // In case of document-blocked page, navigate to blocked URL instead + // of forcing a reload. + case 'reloadTab': { + if ( vAPI.isBehindTheSceneTabId(request.tabId) ) { break; } + const { tabId, bypassCache, url, select } = request; + vAPI.tabs.get(tabId).then(tab => { + if ( url && tab && url !== tab.url ) { + vAPI.tabs.replace(tabId, url); + } else { + vAPI.tabs.reload(tabId, bypassCache === true); + } + }); + if ( select && vAPI.tabs.select ) { + vAPI.tabs.select(tabId); + } + break; + } + case 'setWhitelist': + µb.netWhitelist = µb.whitelistFromString(request.whitelist); + µb.saveWhitelist(); + filteringBehaviorChanged(); + break; + + case 'toggleHostnameSwitch': + µb.toggleHostnameSwitch(request); + break; + + case 'uiAccentStylesheet': + µb.uiAccentStylesheet = request.stylesheet; + break; + + case 'uiStyles': + response = { + uiAccentCustom: µb.userSettings.uiAccentCustom, + uiAccentCustom0: µb.userSettings.uiAccentCustom0, + uiAccentStylesheet: µb.uiAccentStylesheet, + uiStyles: µb.hiddenSettings.uiStyles, + uiTheme: µb.userSettings.uiTheme, + }; + break; + + case 'userSettings': + response = µb.changeUserSettings(request.name, request.value); + if ( response instanceof Object ) { + if ( vAPI.net.canUncloakCnames !== true ) { + response.cnameUncloakEnabled = undefined; + } + response.canLeakLocalIPAddresses = + vAPI.browserSettings.canLeakLocalIPAddresses === true; + } + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.setup(onMessage); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// popupPanel +// privileged + +{ +// >>>>> start of local scope + +const createCounts = ( ) => { + return { + blocked: { any: 0, frame: 0, script: 0 }, + allowed: { any: 0, frame: 0, script: 0 }, + }; +}; + +const getHostnameDict = function(hostnameDetailsMap, out) { + const hnDict = Object.create(null); + const cnMap = []; + + const createDictEntry = (domain, hostname, details) => { + const cname = vAPI.net.canonicalNameFromHostname(hostname); + if ( cname !== undefined ) { + cnMap.push([ cname, hostname ]); + } + hnDict[hostname] = { domain, counts: details.counts }; + }; + + for ( const hnDetails of hostnameDetailsMap.values() ) { + const hostname = hnDetails.hostname; + if ( hnDict[hostname] !== undefined ) { continue; } + const domain = domainFromHostname(hostname) || hostname; + const dnDetails = + hostnameDetailsMap.get(domain) || { counts: createCounts() }; + if ( hnDict[domain] === undefined ) { + createDictEntry(domain, domain, dnDetails); + } + if ( hostname === domain ) { continue; } + createDictEntry(domain, hostname, hnDetails); + } + + out.hostnameDict = hnDict; + out.cnameMap = cnMap; +}; + +const firewallRuleTypes = [ + '*', + 'image', + '3p', + 'inline-script', + '1p-script', + '3p-script', + '3p-frame', +]; + +const getFirewallRules = function(src, out) { + const ruleset = out.firewallRules = {}; + const df = sessionFirewall; + + for ( const type of firewallRuleTypes ) { + const r = df.lookupRuleData('*', '*', type); + if ( r === undefined ) { continue; } + ruleset[`/ * ${type}`] = r; + } + if ( typeof src !== 'string' ) { return; } + + for ( const type of firewallRuleTypes ) { + const r = df.lookupRuleData(src, '*', type); + if ( r === undefined ) { continue; } + ruleset[`. * ${type}`] = r; + } + + const { hostnameDict } = out; + for ( const des in hostnameDict ) { + let r = df.lookupRuleData('*', des, '*'); + if ( r !== undefined ) { ruleset[`/ ${des} *`] = r; } + r = df.lookupRuleData(src, des, '*'); + if ( r !== undefined ) { ruleset[`. ${des} *`] = r; } + } +}; + +const popupDataFromTabId = function(tabId, tabTitle) { + const tabContext = µb.tabContextManager.mustLookup(tabId); + const rootHostname = tabContext.rootHostname; + const µbus = µb.userSettings; + const µbhs = µb.hiddenSettings; + const r = { + advancedUserEnabled: µbus.advancedUserEnabled, + appName: vAPI.app.name, + appVersion: vAPI.app.version, + colorBlindFriendly: µbus.colorBlindFriendly, + cosmeticFilteringSwitch: false, + firewallPaneMinimized: µbus.firewallPaneMinimized, + globalAllowedRequestCount: µb.localSettings.allowedRequestCount, + globalBlockedRequestCount: µb.localSettings.blockedRequestCount, + fontSize: µbhs.popupFontSize, + godMode: µbhs.filterAuthorMode, + netFilteringSwitch: false, + rawURL: tabContext.rawURL, + pageURL: tabContext.normalURL, + pageHostname: rootHostname, + pageDomain: tabContext.rootDomain, + popupBlockedCount: 0, + popupPanelSections: µbus.popupPanelSections, + popupPanelDisabledSections: µbhs.popupPanelDisabledSections, + popupPanelLockedSections: µbhs.popupPanelLockedSections, + popupPanelHeightMode: µbhs.popupPanelHeightMode, + tabId, + tabTitle, + tooltipsDisabled: µbus.tooltipsDisabled, + hasUnprocessedRequest: vAPI.net && vAPI.net.hasUnprocessedRequest(tabId), + }; + + if ( µbhs.uiPopupConfig !== 'unset' ) { + r.uiPopupConfig = µbhs.uiPopupConfig; + } + + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore ) { + r.pageCounts = pageStore.counts; + r.netFilteringSwitch = pageStore.getNetFilteringSwitch(); + getHostnameDict(pageStore.getAllHostnameDetails(), r); + r.contentLastModified = pageStore.contentLastModified; + getFirewallRules(rootHostname, r); + r.canElementPicker = isNetworkURI(r.rawURL); + r.noPopups = sessionSwitches.evaluateZ( + 'no-popups', + rootHostname + ); + r.popupBlockedCount = pageStore.popupBlockedCount; + r.noCosmeticFiltering = sessionSwitches.evaluateZ( + 'no-cosmetic-filtering', + rootHostname + ); + r.noLargeMedia = sessionSwitches.evaluateZ( + 'no-large-media', + rootHostname + ); + r.largeMediaCount = pageStore.largeMediaCount; + r.noRemoteFonts = sessionSwitches.evaluateZ( + 'no-remote-fonts', + rootHostname + ); + r.remoteFontCount = pageStore.remoteFontCount; + r.noScripting = sessionSwitches.evaluateZ( + 'no-scripting', + rootHostname + ); + } else { + r.hostnameDict = {}; + getFirewallRules(undefined, r); + } + + r.matrixIsDirty = sessionFirewall.hasSameRules( + permanentFirewall, + rootHostname, + r.hostnameDict + ) === false; + if ( r.matrixIsDirty === false ) { + r.matrixIsDirty = sessionSwitches.hasSameRules( + permanentSwitches, + rootHostname + ) === false; + } + return r; +}; + +const popupDataFromRequest = async function(request) { + if ( request.tabId ) { + return popupDataFromTabId(request.tabId, ''); + } + + // Still no target tab id? Use currently selected tab. + const tab = await vAPI.tabs.getCurrent(); + let tabId = ''; + let tabTitle = ''; + if ( tab instanceof Object ) { + tabId = tab.id; + tabTitle = tab.title || ''; + } + return popupDataFromTabId(tabId, tabTitle); +}; + +const getElementCount = async function(tabId, what) { + const results = await vAPI.tabs.executeScript(tabId, { + allFrames: true, + file: `/js/scriptlets/dom-survey-${what}.js`, + runAt: 'document_end', + }); + + let total = 0; + for ( const count of results ) { + if ( typeof count !== 'number' ) { continue; } + if ( count === -1 ) { return -1; } + total += count; + } + + return total; +}; + +const launchReporter = async function(request) { + const pageStore = µb.pageStoreFromTabId(request.tabId); + if ( pageStore === null ) { return; } + if ( pageStore.hasUnprocessedRequest ) { + request.popupPanel.hasUnprocessedRequest = true; + } + + const entries = await io.getUpdateAges({ + filters: µb.selectedFilterLists.slice() + }); + const shouldUpdateLists = []; + for ( const entry of entries ) { + if ( entry.age < (2 * 60 * 60 * 1000) ) { continue; } + shouldUpdateLists.push(entry.assetKey); + } + + // https://github.com/gorhill/uBlock/commit/6efd8eb#commitcomment-107523558 + // Important: for whatever reason, not using `document_start` causes the + // Promise returned by `tabs.executeScript()` to resolve only when the + // associated tab is closed. + const cosmeticSurveyResults = await vAPI.tabs.executeScript(request.tabId, { + allFrames: true, + file: '/js/scriptlets/cosmetic-report.js', + matchAboutBlank: true, + runAt: 'document_start', + }); + + const filters = cosmeticSurveyResults.reduce((a, v) => { + if ( Array.isArray(v) ) { a.push(...v); } + return a; + }, []); + // Remove duplicate, truncate too long filters. + if ( filters.length !== 0 ) { + request.popupPanel.extended = Array.from( + new Set(filters.map(s => s.length <= 64 ? s : `${s.slice(0, 64)}…`)) + ); + } + + const supportURL = new URL(vAPI.getURL('support.html')); + supportURL.searchParams.set('pageURL', request.pageURL); + supportURL.searchParams.set('popupPanel', JSON.stringify(request.popupPanel)); + if ( shouldUpdateLists.length ) { + supportURL.searchParams.set('shouldUpdateLists', JSON.stringify(shouldUpdateLists)); + } + return supportURL.href; +}; + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'getHiddenElementCount': + getElementCount(request.tabId, 'elements').then(count => { + callback(count); + }); + return; + + case 'getScriptCount': + getElementCount(request.tabId, 'scripts').then(count => { + callback(count); + }); + return; + + case 'getPopupData': + popupDataFromRequest(request).then(popupData => { + callback(popupData); + }); + return; + + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'dismissUnprocessedRequest': + vAPI.net.removeUnprocessedRequest(request.tabId); + µb.updateToolbarIcon(request.tabId, 0b110); + break; + + case 'hasPopupContentChanged': { + const pageStore = µb.pageStoreFromTabId(request.tabId); + const lastModified = pageStore ? pageStore.contentLastModified : 0; + response = lastModified !== request.contentLastModified; + break; + } + + case 'launchReporter': { + launchReporter(request).then(url => { + if ( typeof url !== 'string' ) { return; } + µb.openNewTab({ url, select: true, index: -1 }); + }); + break; + } + + case 'revertFirewallRules': + // TODO: use Set() to message around sets of hostnames + sessionFirewall.copyRules( + permanentFirewall, + request.srcHostname, + Object.assign(Object.create(null), request.desHostnames) + ); + sessionSwitches.copyRules( + permanentSwitches, + request.srcHostname + ); + // https://github.com/gorhill/uBlock/issues/188 + cosmeticFilteringEngine.removeFromSelectorCache( + request.srcHostname, + 'net' + ); + µb.updateToolbarIcon(request.tabId, 0b100); + response = popupDataFromTabId(request.tabId); + break; + + case 'saveFirewallRules': + // TODO: use Set() to message around sets of hostnames + if ( + permanentFirewall.copyRules( + sessionFirewall, + request.srcHostname, + Object.assign(Object.create(null), request.desHostnames) + ) + ) { + µb.savePermanentFirewallRules(); + } + if ( + permanentSwitches.copyRules( + sessionSwitches, + request.srcHostname + ) + ) { + µb.saveHostnameSwitches(); + } + break; + + case 'toggleHostnameSwitch': + µb.toggleHostnameSwitch(request); + response = popupDataFromTabId(request.tabId); + break; + + case 'toggleFirewallRule': + µb.toggleFirewallRule(request); + response = popupDataFromTabId(request.tabId); + break; + + case 'toggleNetFiltering': { + const pageStore = µb.pageStoreFromTabId(request.tabId); + if ( pageStore ) { + pageStore.toggleNetFilteringSwitch( + request.url, + request.scope, + request.state + ); + µb.updateToolbarIcon(request.tabId, 0b111); + } + break; + } + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'popupPanel', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// contentscript +// unprivileged + +{ +// >>>>> start of local scope + +const retrieveContentScriptParameters = async function(sender, request) { + if ( µb.readyToFilter !== true ) { return; } + const { tabId, frameId } = sender; + if ( tabId === undefined || frameId === undefined ) { return; } + + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore === null || pageStore.getNetFilteringSwitch() === false ) { + return; + } + + // A content script may not always be able to successfully look up the + // effective context, hence in such case we try again to look up here + // using cached information about embedded frames. + if ( frameId !== 0 && request.url.startsWith('about:') ) { + request.url = pageStore.getEffectiveFrameURL(sender); + } + + const noSpecificCosmeticFiltering = + pageStore.shouldApplySpecificCosmeticFilters(frameId) === false; + const noGenericCosmeticFiltering = + pageStore.shouldApplyGenericCosmeticFilters(frameId) === false; + + const response = { + collapseBlocked: µb.userSettings.collapseBlocked, + noGenericCosmeticFiltering, + noSpecificCosmeticFiltering, + }; + + request.tabId = tabId; + request.frameId = frameId; + request.hostname = hostnameFromURI(request.url); + request.domain = domainFromHostname(request.hostname); + request.entity = entityFromDomain(request.domain); + + const scf = response.specificCosmeticFilters = + cosmeticFilteringEngine.retrieveSpecificSelectors(request, response); + + // The procedural filterer's code is loaded only when needed and must be + // present before returning response to caller. + if ( + scf.proceduralFilters.length !== 0 || ( + logger.enabled && ( + scf.convertedProceduralFilters.length !== 0 || + scf.exceptedFilters.length !== 0 + ) + ) + ) { + await vAPI.tabs.executeScript(tabId, { + allFrames: false, + file: '/js/contentscript-extra.js', + frameId, + matchAboutBlank: true, + runAt: 'document_start', + }); + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/688#issuecomment-748179731 + // For non-network URIs, scriptlet injection is deferred to here. The + // effective URL is available here in `request.url`. + if ( logger.enabled || request.needScriptlets ) { + const scriptletDetails = scriptletFilteringEngine.injectNow(request); + if ( scriptletDetails !== undefined ) { + scriptletFilteringEngine.toLogger(request, scriptletDetails); + if ( request.needScriptlets ) { + response.scriptletDetails = scriptletDetails; + } + } + } + + // https://github.com/NanoMeow/QuickReports/issues/6#issuecomment-414516623 + // Inject as early as possible to make the cosmetic logger code less + // sensitive to the removal of DOM nodes which may match injected + // cosmetic filters. + if ( logger.enabled ) { + if ( + noSpecificCosmeticFiltering === false || + noGenericCosmeticFiltering === false + ) { + vAPI.tabs.executeScript(tabId, { + allFrames: false, + file: '/js/scriptlets/cosmetic-logger.js', + frameId, + matchAboutBlank: true, + runAt: 'document_start', + }); + } + } + + return response; +}; + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'retrieveContentScriptParameters': + return retrieveContentScriptParameters( + sender, + request + ).then(response => { + callback(response); + }); + default: + break; + } + + const pageStore = µb.pageStoreFromTabId(sender.tabId); + + // Sync + let response; + + switch ( request.what ) { + case 'cosmeticFiltersInjected': + cosmeticFilteringEngine.addToSelectorCache(request); + break; + + case 'disableGenericCosmeticFilteringSurveyor': + cosmeticFilteringEngine.disableSurveyor(request); + break; + + case 'getCollapsibleBlockedRequests': + response = { + id: request.id, + hash: request.hash, + netSelectorCacheCountMax: + cosmeticFilteringEngine.netSelectorCacheCountMax, + }; + if ( + µb.userSettings.collapseBlocked && + pageStore && pageStore.getNetFilteringSwitch() + ) { + pageStore.getBlockedResources(request, response); + } + break; + + case 'maybeGoodPopup': + µb.maybeGoodPopup.tabId = sender.tabId; + µb.maybeGoodPopup.url = request.url; + break; + + case 'shouldRenderNoscriptTags': + if ( pageStore === null ) { break; } + const fctxt = µb.filteringContext.fromTabId(sender.tabId); + if ( pageStore.filterScripting(fctxt, undefined) ) { + vAPI.tabs.executeScript(sender.tabId, { + file: '/js/scriptlets/noscript-spoof.js', + frameId: sender.frameId, + runAt: 'document_end', + }); + } + break; + + case 'retrieveGenericCosmeticSelectors': + request.tabId = sender.tabId; + request.frameId = sender.frameId; + response = { + result: cosmeticFilteringEngine.retrieveGenericSelectors(request), + }; + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'contentscript', + listener: onMessage, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// elementPicker +// unprivileged + +{ +// >>>>> start of local scope + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + // The procedural filterer must be present in case the user wants to + // type-in custom filters. + case 'elementPickerArguments': + return vAPI.tabs.executeScript(sender.tabId, { + allFrames: false, + file: '/js/contentscript-extra.js', + frameId: sender.frameId, + matchAboutBlank: true, + runAt: 'document_start', + }).then(( ) => { + callback({ + target: µb.epickerArgs.target, + mouse: µb.epickerArgs.mouse, + zap: µb.epickerArgs.zap, + eprom: µb.epickerArgs.eprom, + pickerURL: vAPI.getURL( + `/web_accessible_resources/epicker-ui.html?secret=${vAPI.warSecret.short()}` + ), + }); + µb.epickerArgs.target = ''; + }); + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'elementPickerEprom': + µb.epickerArgs.eprom = request; + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'elementPicker', + listener: onMessage, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// cloudWidget +// privileged + +{ +// >>>>> start of local scope + +const fromBase64 = function(encoded) { + if ( typeof encoded !== 'string' ) { + return Promise.resolve(encoded); + } + let u8array; + try { + u8array = denseBase64.decode(encoded); + } catch(ex) { + } + return Promise.resolve(u8array !== undefined ? u8array : encoded); +}; + +const toBase64 = function(data) { + const value = data instanceof Uint8Array + ? denseBase64.encode(data) + : data; + return Promise.resolve(value); +}; + +const compress = function(json) { + return lz4Codec.encode(json, toBase64); +}; + +const decompress = function(encoded) { + return lz4Codec.decode(encoded, fromBase64); +}; + +const onMessage = function(request, sender, callback) { + // Cloud storage support is optional. + if ( µb.cloudStorageSupported !== true ) { + callback(); + return; + } + + // Async + switch ( request.what ) { + case 'cloudGetOptions': + vAPI.cloud.getOptions(function(options) { + options.enabled = µb.userSettings.cloudStorageEnabled === true; + callback(options); + }); + return; + + case 'cloudSetOptions': + vAPI.cloud.setOptions(request.options, callback); + return; + + case 'cloudPull': + request.decode = decompress; + return vAPI.cloud.pull(request).then(result => { + callback(result); + }); + + case 'cloudPush': + if ( µb.hiddenSettings.cloudStorageCompression ) { + request.encode = compress; + } + return vAPI.cloud.push(request).then(result => { + callback(result); + }); + + case 'cloudUsed': + return vAPI.cloud.used(request.datakey).then(result => { + callback(result); + }); + + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + // For when cloud storage is disabled. + case 'cloudPull': + // fallthrough + case 'cloudPush': + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'cloudWidget', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// dashboard +// privileged + +{ +// >>>>> start of local scope + +// Settings +const getLocalData = async function() { + const data = Object.assign({}, µb.restoreBackupSettings); + data.storageUsed = await µb.getBytesInUse(); + data.cloudStorageSupported = µb.cloudStorageSupported; + data.privacySettingsSupported = µb.privacySettingsSupported; + return data; +}; + +const backupUserData = async function() { + const userFilters = await µb.loadUserFilters(); + + const userData = { + timeStamp: Date.now(), + version: vAPI.app.version, + userSettings: + µb.getModifiedSettings(µb.userSettings, µb.userSettingsDefault), + selectedFilterLists: µb.selectedFilterLists, + hiddenSettings: + µb.getModifiedSettings(µb.hiddenSettings, µb.hiddenSettingsDefault), + whitelist: µb.arrayFromWhitelist(µb.netWhitelist), + dynamicFilteringString: permanentFirewall.toString(), + urlFilteringString: permanentURLFiltering.toString(), + hostnameSwitchesString: permanentSwitches.toString(), + userFilters: userFilters.content, + }; + + const filename = i18n$('aboutBackupFilename') + .replace('{{datetime}}', µb.dateNowToSensibleString()) + .replace(/ +/g, '_'); + µb.restoreBackupSettings.lastBackupFile = filename; + µb.restoreBackupSettings.lastBackupTime = Date.now(); + vAPI.storage.set(µb.restoreBackupSettings); + + const localData = await getLocalData(); + + return { localData, userData }; +}; + +const restoreUserData = async function(request) { + const userData = request.userData; + + // https://github.com/LiCybora/NanoDefenderFirefox/issues/196 + // Backup data could be from Chromium platform or from an older + // Firefox version. + if ( + vAPI.webextFlavor.soup.has('firefox') && + vAPI.app.intFromVersion(userData.version) <= 1031003011 + ) { + userData.hostnameSwitchesString += '\nno-csp-reports: * true'; + } + + // List of external lists is meant to be a string. + if ( Array.isArray(userData.externalLists) ) { + userData.externalLists = userData.externalLists.join('\n'); + } + + // https://github.com/chrisaljoudi/uBlock/issues/1102 + // Ensure all currently cached assets are flushed from storage AND memory. + io.rmrf(); + + // If we are going to restore all, might as well wipe out clean local + // storages + await Promise.all([ + cacheStorage.clear(), + vAPI.storage.clear(), + ]); + + // Restore block stats + µb.saveLocalSettings(); + + // Restore user data + vAPI.storage.set(userData.userSettings); + + // Restore advanced settings. + let hiddenSettings = userData.hiddenSettings; + if ( hiddenSettings instanceof Object === false ) { + hiddenSettings = µb.hiddenSettingsFromString( + userData.hiddenSettingsString || '' + ); + } + // Discard unknown setting or setting with default value. + for ( const key in hiddenSettings ) { + if ( + µb.hiddenSettingsDefault.hasOwnProperty(key) === false || + hiddenSettings[key] === µb.hiddenSettingsDefault[key] + ) { + delete hiddenSettings[key]; + } + } + + // Whitelist directives can be represented as an array or as a + // (eventually to be deprecated) string. + let whitelist = userData.whitelist; + if ( + Array.isArray(whitelist) === false && + typeof userData.netWhitelist === 'string' && + userData.netWhitelist !== '' + ) { + whitelist = userData.netWhitelist.split('\n'); + } + vAPI.storage.set({ + hiddenSettings, + netWhitelist: whitelist || [], + dynamicFilteringString: userData.dynamicFilteringString || '', + urlFilteringString: userData.urlFilteringString || '', + hostnameSwitchesString: userData.hostnameSwitchesString || '', + lastRestoreFile: request.file || '', + lastRestoreTime: Date.now(), + lastBackupFile: '', + lastBackupTime: 0 + }); + µb.saveUserFilters(userData.userFilters); + if ( Array.isArray(userData.selectedFilterLists) ) { + await µb.saveSelectedFilterLists(userData.selectedFilterLists); + } + + vAPI.app.restart(); +}; + +// Remove all stored data but keep global counts, people can become +// quite attached to numbers +const resetUserData = async function() { + await Promise.all([ + cacheStorage.clear(), + vAPI.storage.clear(), + ]); + + await µb.saveLocalSettings(); + + vAPI.app.restart(); +}; + +// Filter lists +const prepListEntries = function(entries) { + for ( const k in entries ) { + if ( entries.hasOwnProperty(k) === false ) { continue; } + const entry = entries[k]; + if ( typeof entry.supportURL === 'string' && entry.supportURL !== '' ) { + entry.supportName = hostnameFromURI(entry.supportURL); + } else if ( typeof entry.homeURL === 'string' && entry.homeURL !== '' ) { + const hn = hostnameFromURI(entry.homeURL); + entry.supportURL = `http://${hn}/`; + entry.supportName = domainFromHostname(hn); + } + } +}; + +const getLists = async function(callback) { + const r = { + autoUpdate: µb.userSettings.autoUpdate, + available: null, + cache: null, + cosmeticFilterCount: cosmeticFilteringEngine.getFilterCount(), + current: µb.availableFilterLists, + ignoreGenericCosmeticFilters: µb.userSettings.ignoreGenericCosmeticFilters, + isUpdating: io.isUpdating(), + netFilterCount: staticNetFilteringEngine.getFilterCount(), + parseCosmeticFilters: µb.userSettings.parseAllABPHideFilters, + suspendUntilListsAreLoaded: µb.userSettings.suspendUntilListsAreLoaded, + userFiltersPath: µb.userFiltersPath + }; + const [ lists, metadata ] = await Promise.all([ + µb.getAvailableLists(), + io.metadata(), + ]); + r.available = lists; + prepListEntries(r.available); + r.cache = metadata; + prepListEntries(r.cache); + callback(r); +}; + +// My filters + +// TODO: also return origin of embedded frames? +const getOriginHints = function() { + const out = new Set(); + for ( const tabId of µb.pageStores.keys() ) { + if ( tabId === -1 ) { continue; } + const tabContext = µb.tabContextManager.lookup(tabId); + if ( tabContext === null ) { continue; } + let { rootDomain, rootHostname } = tabContext; + if ( rootDomain.endsWith('-scheme') ) { continue; } + const isPunycode = rootHostname.includes('xn--'); + out.add(isPunycode ? punycode.toUnicode(rootDomain) : rootDomain); + if ( rootHostname === rootDomain ) { continue; } + out.add(isPunycode ? punycode.toUnicode(rootHostname) : rootHostname); + } + return Array.from(out); +}; + +// My rules +const getRules = function() { + return { + permanentRules: + permanentFirewall.toArray().concat( + permanentSwitches.toArray(), + permanentURLFiltering.toArray() + ), + sessionRules: + sessionFirewall.toArray().concat( + sessionSwitches.toArray(), + sessionURLFiltering.toArray() + ), + pslSelfie: publicSuffixList.toSelfie(), + }; +}; + +const modifyRuleset = function(details) { + let swRuleset, hnRuleset, urlRuleset; + if ( details.permanent ) { + swRuleset = permanentSwitches; + hnRuleset = permanentFirewall; + urlRuleset = permanentURLFiltering; + } else { + swRuleset = sessionSwitches; + hnRuleset = sessionFirewall; + urlRuleset = sessionURLFiltering; + } + let toRemove = new Set(details.toRemove.trim().split(/\s*[\n\r]+\s*/)); + for ( let rule of toRemove ) { + if ( rule === '' ) { continue; } + let parts = rule.split(/\s+/); + if ( hnRuleset.removeFromRuleParts(parts) === false ) { + if ( swRuleset.removeFromRuleParts(parts) === false ) { + urlRuleset.removeFromRuleParts(parts); + } + } + } + let toAdd = new Set(details.toAdd.trim().split(/\s*[\n\r]+\s*/)); + for ( let rule of toAdd ) { + if ( rule === '' ) { continue; } + let parts = rule.split(/\s+/); + if ( hnRuleset.addFromRuleParts(parts) === false ) { + if ( swRuleset.addFromRuleParts(parts) === false ) { + urlRuleset.addFromRuleParts(parts); + } + } + } + if ( details.permanent ) { + if ( swRuleset.changed ) { + µb.saveHostnameSwitches(); + swRuleset.changed = false; + } + if ( hnRuleset.changed ) { + µb.savePermanentFirewallRules(); + hnRuleset.changed = false; + } + if ( urlRuleset.changed ) { + µb.savePermanentURLFilteringRules(); + urlRuleset.changed = false; + } + } +}; + +// Support +const getSupportData = async function() { + const diffArrays = function(modified, original) { + const modifiedSet = new Set(modified); + const originalSet = new Set(original); + let added = []; + let removed = []; + for ( const item of modifiedSet ) { + if ( originalSet.has(item) ) { continue; } + added.push(item); + } + for ( const item of originalSet ) { + if ( modifiedSet.has(item) ) { continue; } + removed.push(item); + } + if ( added.length === 0 ) { + added = undefined; + } + if ( removed.length === 0 ) { + removed = undefined; + } + if ( added !== undefined || removed !== undefined ) { + return { added, removed }; + } + }; + + const modifiedUserSettings = µb.getModifiedSettings( + µb.userSettings, + µb.userSettingsDefault + ); + + const modifiedHiddenSettings = µb.getModifiedSettings( + µb.hiddenSettings, + µb.hiddenSettingsDefault + ); + + let filterset = []; + const userFilters = await µb.loadUserFilters(); + for ( const line of userFilters.content.split(/\s*\n+\s*/) ) { + if ( /^($|![^#])/.test(line) ) { continue; } + filterset.push(line); + } + + const now = Date.now(); + + const formatDelayFromNow = list => { + const time = list.writeTime; + if ( typeof time !== 'number' || time === 0 ) { return 'never'; } + if ( (time || 0) === 0 ) { return '?'; } + const delayInSec = (now - time) / 1000; + const days = (delayInSec / 86400) | 0; + const hours = (delayInSec % 86400) / 3600 | 0; + const minutes = (delayInSec % 3600) / 60 | 0; + const parts = []; + if ( days > 0 ) { parts.push(`${days}d`); } + if ( hours > 0 ) { parts.push(`${hours}h`); } + if ( minutes > 0 ) { parts.push(`${minutes}m`); } + if ( parts.length === 0 ) { parts.push('now'); } + const out = parts.join('.'); + if ( list.diffUpdated ) { return `${out} Δ`; } + return out; + }; + + const lists = µb.availableFilterLists; + let defaultListset = {}; + let addedListset = {}; + let removedListset = {}; + for ( const listKey in lists ) { + if ( lists.hasOwnProperty(listKey) === false ) { continue; } + const list = lists[listKey]; + if ( list.content !== 'filters' ) { continue; } + const used = µb.selectedFilterLists.includes(listKey); + const listDetails = []; + if ( used ) { + if ( typeof list.entryCount === 'number' ) { + listDetails.push(`${list.entryCount}-${list.entryCount-list.entryUsedCount}`); + } + listDetails.push(formatDelayFromNow(list)); + } + if ( list.isDefault || listKey === µb.userFiltersPath ) { + if ( used ) { + defaultListset[listKey] = listDetails.join(', '); + } else { + removedListset[listKey] = null; + } + } else if ( used ) { + addedListset[listKey] = listDetails.join(', '); + } + } + if ( Object.keys(defaultListset).length === 0 ) { + defaultListset = undefined; + } + if ( Object.keys(addedListset).length === 0 ) { + addedListset = undefined; + } else { + const added = Object.keys(addedListset); + const truncated = added.slice(12); + for ( const key of truncated ) { + delete addedListset[key]; + } + if ( truncated.length !== 0 ) { + addedListset[`[${truncated.length} lists not shown]`] = '[too many]'; + } + } + if ( Object.keys(removedListset).length === 0 ) { + removedListset = undefined; + } + + let browserFamily = (( ) => { + if ( vAPI.webextFlavor.soup.has('firefox') ) { return 'Firefox'; } + if ( vAPI.webextFlavor.soup.has('chromium') ) { return 'Chromium'; } + return 'Unknown'; + })(); + if ( vAPI.webextFlavor.soup.has('mobile') ) { + browserFamily += ' Mobile'; + } + + return { + [`${vAPI.app.name}`]: `${vAPI.app.version}`, + [`${browserFamily}`]: `${vAPI.webextFlavor.major}`, + 'filterset (summary)': { + network: staticNetFilteringEngine.getFilterCount(), + cosmetic: cosmeticFilteringEngine.getFilterCount(), + scriptlet: scriptletFilteringEngine.getFilterCount(), + html: htmlFilteringEngine.getFilterCount(), + }, + 'listset (total-discarded, last-updated)': { + removed: removedListset, + added: addedListset, + default: defaultListset, + }, + 'filterset (user)': filterset, + trustedset: diffArrays( + µb.arrayFromWhitelist(µb.netWhitelist), + µb.netWhitelistDefault + ), + switchRuleset: diffArrays( + sessionSwitches.toArray(), + µb.hostnameSwitchesDefault + ), + hostRuleset: diffArrays( + sessionFirewall.toArray(), + µb.dynamicFilteringDefault + ), + urlRuleset: diffArrays( + sessionURLFiltering.toArray(), + [] + ), + 'userSettings': modifiedUserSettings, + 'hiddenSettings': modifiedHiddenSettings, + supportStats: µb.supportStats, + }; +}; + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'backupUserData': + return backupUserData().then(data => { + callback(data); + }); + + case 'getLists': + return µb.isReadyPromise.then(( ) => { + getLists(callback); + }); + + case 'getLocalData': + return getLocalData().then(localData => { + callback(localData); + }); + + case 'getSupportData': { + getSupportData().then(response => { + callback(response); + }); + return; + } + + case 'readUserFilters': + return µb.loadUserFilters().then(result => { + result.trustedSource = µb.isTrustedList(µb.userFiltersPath); + callback(result); + }); + + case 'writeUserFilters': + return µb.saveUserFilters(request.content).then(result => { + callback(result); + }); + + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'dashboardConfig': + response = { + noDashboard: µb.noDashboard, + }; + break; + + case 'getAutoCompleteDetails': + response = {}; + if ( (request.hintUpdateToken || 0) === 0 ) { + response.redirectResources = redirectEngine.getResourceDetails(); + response.preparseDirectiveEnv = vAPI.webextFlavor.env.slice(); + response.preparseDirectiveHints = sfp.utils.preparser.getHints(); + } + if ( request.hintUpdateToken !== µb.pageStoresToken ) { + response.originHints = getOriginHints(); + response.hintUpdateToken = µb.pageStoresToken; + } + break; + + case 'getRules': + response = getRules(); + break; + + case 'modifyRuleset': + // https://github.com/chrisaljoudi/uBlock/issues/772 + cosmeticFilteringEngine.removeFromSelectorCache('*'); + modifyRuleset(request); + response = getRules(); + break; + + case 'supportUpdateNow': { + const { assetKeys } = request; + if ( assetKeys.length === 0 ) { return; } + for ( const assetKey of assetKeys ) { + io.purge(assetKey); + } + µb.scheduleAssetUpdater({ now: true, fetchDelay: 100 }); + break; + } + + case 'listsUpdateNow': { + const { assetKeys, preferOrigin = false } = request; + if ( assetKeys.length === 0 ) { return; } + for ( const assetKey of assetKeys ) { + io.purge(assetKey); + } + µb.scheduleAssetUpdater({ now: true, fetchDelay: 100, auto: preferOrigin !== true }); + break; + } + + case 'readHiddenSettings': + response = { + 'default': µb.hiddenSettingsDefault, + 'admin': µb.hiddenSettingsAdmin, + 'current': µb.hiddenSettings, + }; + break; + + case 'restoreUserData': + restoreUserData(request); + break; + + case 'resetUserData': + resetUserData(); + break; + + case 'updateNow': + µb.scheduleAssetUpdater({ now: true, fetchDelay: 100, auto: true }); + break; + + case 'writeHiddenSettings': + µb.changeHiddenSettings(µb.hiddenSettingsFromString(request.content)); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'dashboard', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// loggerUI +// privileged + +{ +// >>>>> start of local scope + +const extensionOriginURL = vAPI.getURL(''); +const documentBlockedURL = vAPI.getURL('document-blocked.html'); + +const getLoggerData = async function(details, activeTabId, callback) { + const response = { + activeTabId, + colorBlind: µb.userSettings.colorBlindFriendly, + entries: logger.readAll(details.ownerId), + tabIdsToken: µb.pageStoresToken, + tooltips: µb.userSettings.tooltipsDisabled === false + }; + if ( µb.pageStoresToken !== details.tabIdsToken ) { + response.tabIds = []; + for ( const [ tabId, pageStore ] of µb.pageStores ) { + const { rawURL, title } = pageStore; + if ( rawURL.startsWith(extensionOriginURL) ) { + if ( rawURL.startsWith(documentBlockedURL) === false ) { continue; } + } + response.tabIds.push([ tabId, title ]); + } + } + if ( activeTabId ) { + const pageStore = µb.pageStoreFromTabId(activeTabId); + const rawURL = pageStore && pageStore.rawURL; + if ( + rawURL === null || + rawURL.startsWith(extensionOriginURL) && + rawURL.startsWith(documentBlockedURL) === false + ) { + response.activeTabId = undefined; + } + } + if ( details.popupLoggerBoxChanged && vAPI.windows instanceof Object ) { + const tabs = await vAPI.tabs.query({ + url: vAPI.getURL('/logger-ui.html?popup=1') + }); + if ( tabs.length !== 0 ) { + const win = await vAPI.windows.get(tabs[0].windowId); + if ( win === null ) { return; } + vAPI.localStorage.setItem('popupLoggerBox', JSON.stringify({ + left: win.left, + top: win.top, + width: win.width, + height: win.height, + })); + } + } + callback(response); +}; + +const getURLFilteringData = function(details) { + const colors = {}; + const response = { + dirty: false, + colors: colors + }; + const suf = sessionURLFiltering; + const puf = permanentURLFiltering; + const urls = details.urls; + const context = details.context; + const type = details.type; + for ( const url of urls ) { + const colorEntry = colors[url] = { r: 0, own: false }; + if ( suf.evaluateZ(context, url, type).r !== 0 ) { + colorEntry.r = suf.r; + colorEntry.own = suf.r !== 0 && + suf.context === context && + suf.url === url && + suf.type === type; + } + if ( response.dirty ) { continue; } + puf.evaluateZ(context, url, type); + const pown = ( + puf.r !== 0 && + puf.context === context && + puf.url === url && + puf.type === type + ); + response.dirty = colorEntry.own !== pown || colorEntry.r !== puf.r; + } + return response; +}; + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'readAll': + if ( logger.ownerId !== undefined && logger.ownerId !== request.ownerId ) { + return callback({ unavailable: true }); + } + vAPI.tabs.getCurrent().then(tab => { + getLoggerData(request, tab && tab.id, callback); + }); + return; + + case 'toggleInMemoryFilter': { + const promise = µb.hasInMemoryFilter(request.filter) + ? µb.removeInMemoryFilter(request.filter) + : µb.addInMemoryFilter(request.filter); + promise.then(status => { callback(status); }); + return; + } + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'hasInMemoryFilter': + response = µb.hasInMemoryFilter(request.filter); + break; + + case 'releaseView': + if ( request.ownerId !== logger.ownerId ) { break; } + logger.ownerId = undefined; + µb.clearInMemoryFilters(); + break; + + case 'saveURLFilteringRules': + response = permanentURLFiltering.copyRules( + sessionURLFiltering, + request.context, + request.urls, + request.type + ); + if ( response ) { + µb.savePermanentURLFilteringRules(); + } + break; + + case 'setURLFilteringRule': + µb.toggleURLFilteringRule(request); + break; + + case 'getURLFilteringData': + response = getURLFilteringData(request); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'loggerUI', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// domInspectorContent +// unprivileged + +{ +// >>>>> start of local scope + +const onMessage = (request, sender, callback) => { + // Async + switch ( request.what ) { + default: + break; + } + // Sync + let response; + switch ( request.what ) { + case 'getInspectorArgs': + const bc = new globalThis.BroadcastChannel('contentInspectorChannel'); + bc.postMessage({ + what: 'contentInspectorChannel', + tabId: sender.tabId || 0, + frameId: sender.frameId || 0, + }); + response = { + inspectorURL: vAPI.getURL( + `/web_accessible_resources/dom-inspector.html?secret=${vAPI.warSecret.short()}` + ), + }; + break; + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'domInspectorContent', + listener: onMessage, + privileged: false, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// documentBlocked +// privileged + +{ +// >>>>> start of local scope + +const onMessage = function(request, sender, callback) { + const tabId = sender.tabId || 0; + + // Async + switch ( request.what ) { + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'closeThisTab': + vAPI.tabs.remove(tabId); + break; + + case 'temporarilyWhitelistDocument': + webRequest.strictBlockBypass(request.hostname); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'documentBlocked', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// devTools +// privileged + +{ +// >>>>> start of local scope + +const onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + case 'purgeAllCaches': + µb.getBytesInUse().then(bytesInUseBefore => + io.remove(/./).then(( ) => + µb.getBytesInUse().then(bytesInUseAfter => { + callback([ + `Storage used before: ${µb.formatCount(bytesInUseBefore)}B`, + `Storage used after: ${µb.formatCount(bytesInUseAfter)}B`, + ].join('\n')); + }) + ) + ); + return; + + case 'snfeBenchmark': + µb.benchmarkStaticNetFiltering({ redirectEngine }).then(result => { + callback(result); + }); + return; + + case 'snfeToDNR': { + const listPromises = []; + const listNames = []; + for ( const assetKey of µb.selectedFilterLists ) { + listPromises.push( + io.get(assetKey, { dontCache: true }).then(details => { + listNames.push(assetKey); + return { name: assetKey, text: details.content }; + }) + ); + } + const options = { + extensionPaths: redirectEngine.getResourceDetails().filter(e => + typeof e[1].extensionPath === 'string' && e[1].extensionPath !== '' + ).map(e => + [ e[0], e[1].extensionPath ] + ), + env: vAPI.webextFlavor.env, + }; + const t0 = Date.now(); + dnrRulesetFromRawLists(listPromises, options).then(result => { + const { network } = result; + const replacer = (k, v) => { + if ( k.startsWith('__') ) { return; } + if ( Array.isArray(v) ) { + return v.sort(); + } + if ( v instanceof Object ) { + const sorted = {}; + for ( const kk of Object.keys(v).sort() ) { + sorted[kk] = v[kk]; + } + return sorted; + } + return v; + }; + const isUnsupported = rule => + rule._error !== undefined; + const isRegex = rule => + rule.condition !== undefined && + rule.condition.regexFilter !== undefined; + const isRedirect = rule => + rule.action !== undefined && + rule.action.type === 'redirect' && + rule.action.redirect.extensionPath !== undefined; + const isCsp = rule => + rule.action !== undefined && + rule.action.type === 'modifyHeaders'; + const isRemoveparam = rule => + rule.action !== undefined && + rule.action.type === 'redirect' && + rule.action.redirect.transform !== undefined; + const runtime = Date.now() - t0; + const { ruleset } = network; + const good = ruleset.filter(rule => + isUnsupported(rule) === false && + isRegex(rule) === false && + isRedirect(rule) === false && + isCsp(rule) === false && + isRemoveparam(rule) === false + ); + const unsupported = ruleset.filter(rule => + isUnsupported(rule) + ); + const regexes = ruleset.filter(rule => + isUnsupported(rule) === false && + isRegex(rule) && + isRedirect(rule) === false && + isCsp(rule) === false && + isRemoveparam(rule) === false + ); + const redirects = ruleset.filter(rule => + isUnsupported(rule) === false && + isRedirect(rule) + ); + const headers = ruleset.filter(rule => + isUnsupported(rule) === false && + isCsp(rule) + ); + const removeparams = ruleset.filter(rule => + isUnsupported(rule) === false && + isRemoveparam(rule) + ); + const out = [ + `dnrRulesetFromRawLists(${JSON.stringify(listNames, null, 2)})`, + `Run time: ${runtime} ms`, + `Filters count: ${network.filterCount}`, + `Accepted filter count: ${network.acceptedFilterCount}`, + `Rejected filter count: ${network.rejectedFilterCount}`, + `Un-DNR-able filter count: ${unsupported.length}`, + `Resulting DNR rule count: ${ruleset.length}`, + ]; + out.push(`+ Good filters (${good.length}): ${JSON.stringify(good, replacer, 2)}`); + out.push(`+ Regex-based filters (${regexes.length}): ${JSON.stringify(regexes, replacer, 2)}`); + out.push(`+ 'redirect=' filters (${redirects.length}): ${JSON.stringify(redirects, replacer, 2)}`); + out.push(`+ 'csp=' filters (${headers.length}): ${JSON.stringify(headers, replacer, 2)}`); + out.push(`+ 'removeparam=' filters (${removeparams.length}): ${JSON.stringify(removeparams, replacer, 2)}`); + out.push(`+ Unsupported filters (${unsupported.length}): ${JSON.stringify(unsupported, replacer, 2)}`); + out.push(`+ generichide exclusions (${network.generichideExclusions.length}): ${JSON.stringify(network.generichideExclusions, replacer, 2)}`); + if ( result.specificCosmetic ) { + out.push(`+ Cosmetic filters: ${result.specificCosmetic.size}`); + for ( const details of result.specificCosmetic ) { + out.push(` ${JSON.stringify(details)}`); + } + } else { + out.push(' Cosmetic filters: 0'); + } + callback(out.join('\n')); + }); + return; + } + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'snfeDump': + response = staticNetFilteringEngine.dump(); + break; + + case 'cfeDump': + response = cosmeticFilteringEngine.dump(); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'devTools', + listener: onMessage, + privileged: true, +}); + +// <<<<< end of local scope +} + +/******************************************************************************/ +/******************************************************************************/ + +// Channel: +// scriptlets +// unprivileged + +{ +// >>>>> start of local scope + +const logCosmeticFilters = function(tabId, details) { + if ( logger.enabled === false ) { return; } + + const filter = { source: 'cosmetic', raw: '' }; + const fctxt = µb.filteringContext.duplicate(); + fctxt.fromTabId(tabId) + .setRealm('cosmetic') + .setType('dom') + .setURL(details.frameURL) + .setDocOriginFromURL(details.frameURL) + .setFilter(filter); + for ( const selector of details.matchedSelectors.sort() ) { + filter.raw = selector; + fctxt.toLogger(); + } +}; + +const logCSPViolations = function(pageStore, request) { + if ( logger.enabled === false || pageStore === null ) { + return false; + } + if ( request.violations.length === 0 ) { + return true; + } + + const fctxt = µb.filteringContext.duplicate(); + fctxt.fromTabId(pageStore.tabId) + .setRealm('network') + .setDocOriginFromURL(request.docURL) + .setURL(request.docURL); + + let cspData = pageStore.extraData.get('cspData'); + if ( cspData === undefined ) { + cspData = new Map(); + + const staticDirectives = + staticNetFilteringEngine.matchAndFetchModifiers(fctxt, 'csp'); + if ( staticDirectives !== undefined ) { + for ( const directive of staticDirectives ) { + if ( directive.result !== 1 ) { continue; } + cspData.set(directive.value, directive.logData()); + } + } + + fctxt.type = 'inline-script'; + fctxt.filter = undefined; + if ( pageStore.filterRequest(fctxt) === 1 ) { + cspData.set(µb.cspNoInlineScript, fctxt.filter); + } + + fctxt.type = 'script'; + fctxt.filter = undefined; + if ( pageStore.filterScripting(fctxt, true) === 1 ) { + cspData.set(µb.cspNoScripting, fctxt.filter); + } + + fctxt.type = 'inline-font'; + fctxt.filter = undefined; + if ( pageStore.filterRequest(fctxt) === 1 ) { + cspData.set(µb.cspNoInlineFont, fctxt.filter); + } + + if ( cspData.size === 0 ) { return false; } + + pageStore.extraData.set('cspData', cspData); + } + + const typeMap = logCSPViolations.policyDirectiveToTypeMap; + for ( const json of request.violations ) { + const violation = JSON.parse(json); + let type = typeMap.get(violation.directive); + if ( type === undefined ) { continue; } + const logData = cspData.get(violation.policy); + if ( logData === undefined ) { continue; } + if ( /^[\w.+-]+:\/\//.test(violation.url) === false ) { + violation.url = request.docURL; + if ( type === 'script' ) { type = 'inline-script'; } + else if ( type === 'font' ) { type = 'inline-font'; } + } + // The resource was blocked as a result of applying a CSP directive + // elsewhere rather than to the resource itself. + logData.modifier = undefined; + fctxt.setURL(violation.url) + .setType(type) + .setFilter(logData) + .toLogger(); + } + + return true; +}; + +logCSPViolations.policyDirectiveToTypeMap = new Map([ + [ 'img-src', 'image' ], + [ 'connect-src', 'xmlhttprequest' ], + [ 'font-src', 'font' ], + [ 'frame-src', 'sub_frame' ], + [ 'media-src', 'media' ], + [ 'object-src', 'object' ], + [ 'script-src', 'script' ], + [ 'script-src-attr', 'script' ], + [ 'script-src-elem', 'script' ], + [ 'style-src', 'stylesheet' ], + [ 'style-src-attr', 'stylesheet' ], + [ 'style-src-elem', 'stylesheet' ], +]); + +const onMessage = function(request, sender, callback) { + const tabId = sender.tabId || 0; + const pageStore = µb.pageStoreFromTabId(tabId); + + // Async + switch ( request.what ) { + default: + break; + } + + // Sync + let response; + + switch ( request.what ) { + case 'inlinescriptFound': + if ( logger.enabled && pageStore !== null ) { + const fctxt = µb.filteringContext.duplicate(); + fctxt.fromTabId(tabId) + .setType('inline-script') + .setURL(request.docURL) + .setDocOriginFromURL(request.docURL); + if ( pageStore.filterRequest(fctxt) === 0 ) { + fctxt.setRealm('network').toLogger(); + } + } + break; + + case 'logCosmeticFilteringData': + logCosmeticFilters(tabId, request); + break; + + case 'securityPolicyViolation': + response = logCSPViolations(pageStore, request); + break; + + case 'temporarilyAllowLargeMediaElement': + if ( pageStore !== null ) { + pageStore.allowLargeMediaElementsUntil = Date.now() + 5000; + } + break; + + case 'subscribeTo': + // https://github.com/uBlockOrigin/uBlock-issues/issues/1797 + if ( /^(file|https?):\/\//.test(request.location) === false ) { break; } + const url = encodeURIComponent(request.location); + const title = encodeURIComponent(request.title); + const hash = µb.selectedFilterLists.indexOf(request.location) !== -1 + ? '#subscribed' + : ''; + vAPI.tabs.open({ + url: `/asset-viewer.html?url=${url}&title=${title}&subscribe=1${hash}`, + select: true, + }); + break; + + case 'updateLists': + const listkeys = request.listkeys.split(',').filter(s => s !== ''); + if ( listkeys.length === 0 ) { return; } + if ( listkeys.includes('all') ) { + io.purge(/./, 'public_suffix_list.dat'); + } else { + for ( const listkey of listkeys ) { + io.purge(listkey); + } + } + µb.openNewTab({ + url: 'dashboard.html#3p-filters.html', + select: true, + }); + µb.scheduleAssetUpdater({ now: true, fetchDelay: 100, auto: request.auto }); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen({ + name: 'scriptlets', + listener: onMessage, +}); + +// <<<<< end of local scope +} + + +/******************************************************************************/ +/******************************************************************************/ diff --git a/src/js/mrucache.js b/src/js/mrucache.js new file mode 100644 index 0000000..9a16047 --- /dev/null +++ b/src/js/mrucache.js @@ -0,0 +1,58 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +export class MRUCache { + constructor(maxSize) { + this.maxSize = maxSize; + this.array = []; + this.map = new Map(); + this.resetTime = Date.now(); + } + add(key, value) { + const found = this.map.has(key); + this.map.set(key, value); + if ( found ) { return; } + if ( this.array.length === this.maxSize ) { + this.map.delete(this.array.pop()); + } + this.array.unshift(key); + } + remove(key) { + if ( this.map.delete(key) === false ) { return; } + this.array.splice(this.array.indexOf(key), 1); + } + lookup(key) { + const value = this.map.get(key); + if ( value === undefined ) { return; } + if ( this.array[0] === key ) { return value; } + const i = this.array.indexOf(key); + this.array.copyWithin(1, 0, i); + this.array[0] = key; + return value; + } + reset() { + this.array = []; + this.map.clear(); + this.resetTime = Date.now(); + } +} diff --git a/src/js/pagestore.js b/src/js/pagestore.js new file mode 100644 index 0000000..907e747 --- /dev/null +++ b/src/js/pagestore.js @@ -0,0 +1,1140 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +/******************************************************************************/ + +import contextMenu from './contextmenu.js'; +import logger from './logger.js'; +import staticNetFilteringEngine from './static-net-filtering.js'; +import µb from './background.js'; +import webext from './webext.js'; +import { orphanizeString } from './text-utils.js'; +import { redirectEngine } from './redirect-engine.js'; + +import { + sessionFirewall, + sessionSwitches, + sessionURLFiltering, +} from './filtering-engines.js'; + +import { + domainFromHostname, + hostnameFromURI, + isNetworkURI, +} from './uri-utils.js'; + +/******************************************************************************* + +A PageRequestStore object is used to store net requests in two ways: + +To record distinct net requests +To create a log of net requests + +**/ + +/******************************************************************************/ + +const NetFilteringResultCache = class { + constructor() { + this.pruneTimer = vAPI.defer.create(( ) => { + this.prune(); + }); + this.init(); + } + + init() { + this.blocked = new Map(); + this.results = new Map(); + this.hash = 0; + return this; + } + + // https://github.com/gorhill/uBlock/issues/3619 + // Don't collapse redirected resources + rememberResult(fctxt, result) { + if ( fctxt.tabId <= 0 ) { return; } + if ( this.results.size === 0 ) { + this.pruneAsync(); + } + const key = `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`; + this.results.set(key, { + result, + redirectURL: fctxt.redirectURL, + logData: fctxt.filter, + tstamp: Date.now() + }); + if ( result !== 1 || fctxt.redirectURL !== undefined ) { return; } + const now = Date.now(); + this.blocked.set(key, now); + this.hash = now; + } + + rememberBlock(fctxt) { + if ( fctxt.tabId <= 0 ) { return; } + if ( this.blocked.size === 0 ) { + this.pruneAsync(); + } + if ( fctxt.redirectURL !== undefined ) { return; } + const now = Date.now(); + this.blocked.set( + `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`, + now + ); + this.hash = now; + } + + forgetResult(docHostname, type, url) { + const key = `${docHostname} ${type} ${url}`; + this.results.delete(key); + this.blocked.delete(key); + } + + empty() { + this.blocked.clear(); + this.results.clear(); + this.hash = 0; + this.pruneTimer.off(); + } + + prune() { + const obsolete = Date.now() - this.shelfLife; + for ( const entry of this.blocked ) { + if ( entry[1] <= obsolete ) { + this.results.delete(entry[0]); + this.blocked.delete(entry[0]); + } + } + for ( const entry of this.results ) { + if ( entry[1].tstamp <= obsolete ) { + this.results.delete(entry[0]); + } + } + if ( this.blocked.size !== 0 || this.results.size !== 0 ) { + this.pruneAsync(); + } + } + + pruneAsync() { + this.pruneTimer.on(this.shelfLife); + } + + lookupResult(fctxt) { + const entry = this.results.get( + fctxt.getDocHostname() + ' ' + + fctxt.type + ' ' + + fctxt.url + ); + if ( entry === undefined ) { return; } + // We need to use a new WAR secret if one is present since WAR secrets + // can only be used once. + if ( + entry.redirectURL !== undefined && + entry.redirectURL.startsWith(this.extensionOriginURL) + ) { + const redirectURL = new URL(entry.redirectURL); + redirectURL.searchParams.set('secret', vAPI.warSecret.short()); + entry.redirectURL = redirectURL.href; + } + return entry; + } + + lookupAllBlocked(hostname) { + const result = []; + for ( const entry of this.blocked ) { + const pos = entry[0].indexOf(' '); + if ( entry[0].slice(0, pos) === hostname ) { + result[result.length] = entry[0].slice(pos + 1); + } + } + return result; + } + + static factory() { + return new NetFilteringResultCache(); + } +}; + +NetFilteringResultCache.prototype.shelfLife = 15000; +NetFilteringResultCache.prototype.extensionOriginURL = vAPI.getURL('/'); + +/******************************************************************************/ + +// Frame stores are used solely to associate a URL with a frame id. + +const FrameStore = class { + constructor(frameURL, parentId) { + this.init(frameURL, parentId); + } + + init(frameURL, parentId) { + this.t0 = Date.now(); + this.parentId = parentId; + this.exceptCname = undefined; + this.clickToLoad = false; + this.rawURL = frameURL; + if ( frameURL !== undefined ) { + this.hostname = hostnameFromURI(frameURL); + this.domain = domainFromHostname(this.hostname) || this.hostname; + } + // Evaluated on-demand + // - 0b01: specific cosmetic filtering + // - 0b10: generic cosmetic filtering + this._cosmeticFilteringBits = undefined; + return this; + } + + dispose() { + this.rawURL = this.hostname = this.domain = ''; + if ( FrameStore.junkyard.length < FrameStore.junkyardMax ) { + FrameStore.junkyard.push(this); + } + return null; + } + + updateURL(url) { + if ( typeof url !== 'string' ) { return; } + this.rawURL = url; + this.hostname = hostnameFromURI(url); + this.domain = domainFromHostname(this.hostname) || this.hostname; + this._cosmeticFilteringBits = undefined; + } + + getCosmeticFilteringBits(tabId) { + if ( this._cosmeticFilteringBits !== undefined ) { + return this._cosmeticFilteringBits; + } + this._cosmeticFilteringBits = 0b11; + { + const result = staticNetFilteringEngine.matchRequestReverse( + 'specifichide', + this.rawURL + ); + if ( result !== 0 && logger.enabled ) { + µb.filteringContext + .duplicate() + .fromTabId(tabId) + .setURL(this.rawURL) + .setDocOriginFromURL(this.rawURL) + .setRealm('network') + .setType('specifichide') + .setFilter(staticNetFilteringEngine.toLogData()) + .toLogger(); + } + if ( result === 2 ) { + this._cosmeticFilteringBits &= ~0b01; + } + } + { + const result = staticNetFilteringEngine.matchRequestReverse( + 'generichide', + this.rawURL + ); + if ( result !== 0 && logger.enabled ) { + µb.filteringContext + .duplicate() + .fromTabId(tabId) + .setURL(this.rawURL) + .setDocOriginFromURL(this.rawURL) + .setRealm('network') + .setType('generichide') + .setFilter(staticNetFilteringEngine.toLogData()) + .toLogger(); + } + if ( result === 2 ) { + this._cosmeticFilteringBits &= ~0b10; + } + } + return this._cosmeticFilteringBits; + } + + shouldApplySpecificCosmeticFilters(tabId) { + return (this.getCosmeticFilteringBits(tabId) & 0b01) !== 0; + } + + shouldApplyGenericCosmeticFilters(tabId) { + return (this.getCosmeticFilteringBits(tabId) & 0b10) !== 0; + } + + static factory(frameURL, parentId = -1) { + const entry = FrameStore.junkyard.pop(); + if ( entry === undefined ) { + return new FrameStore(frameURL, parentId); + } + return entry.init(frameURL, parentId); + } +}; + +// To mitigate memory churning +FrameStore.junkyard = []; +FrameStore.junkyardMax = 50; + +/******************************************************************************/ + +const CountDetails = class { + constructor() { + this.allowed = { any: 0, frame: 0, script: 0 }; + this.blocked = { any: 0, frame: 0, script: 0 }; + } + reset() { + const { allowed, blocked } = this; + blocked.any = blocked.frame = blocked.script = + allowed.any = allowed.frame = allowed.script = 0; + } + inc(blocked, type = undefined) { + const stat = blocked ? this.blocked : this.allowed; + if ( type !== undefined ) { stat[type] += 1; } + stat.any += 1; + } +}; + +const HostnameDetails = class { + constructor(hostname) { + this.counts = new CountDetails(); + this.init(hostname); + } + init(hostname) { + this.hostname = hostname; + this.counts.reset(); + } + dispose() { + this.hostname = ''; + if ( HostnameDetails.junkyard.length < HostnameDetails.junkyardMax ) { + HostnameDetails.junkyard.push(this); + } + } +}; + +HostnameDetails.junkyard = []; +HostnameDetails.junkyardMax = 100; + +const HostnameDetailsMap = class extends Map { + reset() { + this.clear(); + } + dispose() { + for ( const item of this.values() ) { + item.dispose(); + } + this.reset(); + } +}; + +/******************************************************************************/ + +const PageStore = class { + constructor(tabId, details) { + this.extraData = new Map(); + this.journal = []; + this.journalLastCommitted = this.journalLastUncommitted = -1; + this.journalLastUncommittedOrigin = undefined; + this.netFilteringCache = NetFilteringResultCache.factory(); + this.hostnameDetailsMap = new HostnameDetailsMap(); + this.counts = new CountDetails(); + this.journalTimer = vAPI.defer.create(( ) => { + this.journalProcess(); + }); + this.largeMediaTimer = vAPI.defer.create(( ) => { + this.injectLargeMediaElementScriptlet(); + }); + this.init(tabId, details); + } + + static factory(tabId, details) { + let entry = PageStore.junkyard.pop(); + if ( entry === undefined ) { + entry = new PageStore(tabId, details); + } else { + entry.init(tabId, details); + } + return entry; + } + + // https://github.com/gorhill/uBlock/issues/3201 + // The context is used to determine whether we report behavior change + // to the logger. + + init(tabId, details) { + const tabContext = µb.tabContextManager.mustLookup(tabId); + this.tabId = tabId; + + // If we are navigating from-to same site, remember whether large + // media elements were temporarily allowed. + if ( + typeof this.allowLargeMediaElementsUntil !== 'number' || + tabContext.rootHostname !== this.tabHostname + ) { + this.allowLargeMediaElementsUntil = Date.now(); + } + + this.tabHostname = tabContext.rootHostname; + this.rawURL = tabContext.rawURL; + this.hostnameDetailsMap.reset(); + this.contentLastModified = 0; + this.logData = undefined; + this.counts.reset(); + this.remoteFontCount = 0; + this.popupBlockedCount = 0; + this.largeMediaCount = 0; + this.allowLargeMediaElementsRegex = undefined; + this.extraData.clear(); + + this.frameAddCount = 0; + this.frames = new Map(); + this.setFrameURL({ url: tabContext.rawURL }); + + if ( this.titleFromDetails(details) === false ) { + this.title = tabContext.rawURL; + } + + // Evaluated on-demand + this._noCosmeticFiltering = undefined; + + // Remember if the webpage was potentially improperly filtered, for + // reporting purpose. + this.hasUnprocessedRequest = vAPI.net.hasUnprocessedRequest(tabId); + + return this; + } + + reuse(context, details) { + // When force refreshing a page, the page store data needs to be reset. + + // If the hostname changes, we can't merely just update the context. + const tabContext = µb.tabContextManager.mustLookup(this.tabId); + if ( tabContext.rootHostname !== this.tabHostname ) { + context = ''; + } + + // If URL changes without a page reload (more and more common), then + // we need to keep all that we collected for reuse. In particular, + // not doing so was causing a problem in `videos.foxnews.com`: + // clicking a video thumbnail would not work, because the frame + // hierarchy structure was flushed from memory, while not really being + // flushed on the page. + if ( context === 'tabUpdated' ) { + // As part of https://github.com/chrisaljoudi/uBlock/issues/405 + // URL changed, force a re-evaluation of filtering switch + this.rawURL = tabContext.rawURL; + this.setFrameURL({ url: this.rawURL }); + this.titleFromDetails(details); + return this; + } + + // A new page is completely reloaded from scratch, reset all. + this.largeMediaTimer.off(); + this.disposeFrameStores(); + this.init(this.tabId, details); + return this; + } + + dispose() { + this.tabHostname = ''; + this.title = ''; + this.rawURL = ''; + this.hostnameDetailsMap.dispose(); + this.netFilteringCache.empty(); + this.allowLargeMediaElementsUntil = Date.now(); + this.allowLargeMediaElementsRegex = undefined; + this.largeMediaTimer.off(); + this.disposeFrameStores(); + this.journalTimer.off(); + this.journal = []; + this.journalLastUncommittedOrigin = undefined; + this.journalLastCommitted = this.journalLastUncommitted = -1; + if ( PageStore.junkyard.length < PageStore.junkyardMax ) { + PageStore.junkyard.push(this); + } + return null; + } + + titleFromDetails(details) { + if ( + details instanceof Object === false || + details.title === undefined + ) { + return false; + } + this.title = orphanizeString(details.title.slice(0, 128)); + return true; + } + + disposeFrameStores() { + for ( const frameStore of this.frames.values() ) { + frameStore.dispose(); + } + this.frames.clear(); + } + + getFrameStore(frameId) { + return this.frames.get(frameId) || null; + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1858 + // Mind that setFrameURL() can be called from navigation event handlers. + setFrameURL(details) { + let { frameId, url, parentFrameId } = details; + if ( frameId === undefined ) { frameId = 0; } + if ( parentFrameId === undefined ) { parentFrameId = -1; } + let frameStore = this.frames.get(frameId); + if ( frameStore !== undefined ) { + if ( url === frameStore.rawURL ) { + frameStore.parentId = parentFrameId; + } else { + frameStore.init(url, parentFrameId); + } + return frameStore; + } + frameStore = FrameStore.factory(url, parentFrameId); + this.frames.set(frameId, frameStore); + this.frameAddCount += 1; + if ( url.startsWith('about:') ) { + frameStore.updateURL(this.getEffectiveFrameURL({ frameId })); + } + if ( (this.frameAddCount & 0b111111) === 0 ) { + this.pruneFrames(); + } + return frameStore; + } + + getEffectiveFrameURL(sender) { + let { frameId } = sender; + for (;;) { + const frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { break; } + if ( frameStore.rawURL.startsWith('about:') === false ) { + return frameStore.rawURL; + } + frameId = frameStore.parentId; + if ( frameId === -1 ) { break; } + } + return sender.frameURL; + } + + // There is no event to tell us a specific subframe has been removed from + // the main document. The code below will remove subframes which are no + // longer present in the root document. Removing obsolete subframes is + // not a critical task, so this is executed just once on a while, to avoid + // bloated dictionary of subframes. + // A TTL is used to avoid race conditions when new iframes are added + // through the webRequest API but still not yet visible through the + // webNavigation API. + async pruneFrames() { + let entries; + try { + entries = await webext.webNavigation.getAllFrames({ + tabId: this.tabId + }); + } catch(ex) { + } + if ( Array.isArray(entries) === false ) { return; } + const toKeep = new Set(); + for ( const { frameId } of entries ) { + toKeep.add(frameId); + } + const obsolete = Date.now() - 60000; + for ( const [ frameId, { t0 } ] of this.frames ) { + if ( toKeep.has(frameId) || t0 >= obsolete ) { continue; } + this.frames.delete(frameId); + } + } + + getNetFilteringSwitch() { + return µb.tabContextManager + .mustLookup(this.tabId) + .getNetFilteringSwitch(); + } + + toggleNetFilteringSwitch(url, scope, state) { + µb.toggleNetFilteringSwitch(url, scope, state); + this.netFilteringCache.empty(); + } + + shouldApplyCosmeticFilters(frameId = 0) { + if ( this._noCosmeticFiltering === undefined ) { + this._noCosmeticFiltering = this.getNetFilteringSwitch() === false; + if ( this._noCosmeticFiltering === false ) { + this._noCosmeticFiltering = sessionSwitches.evaluateZ( + 'no-cosmetic-filtering', + this.tabHostname + ) === true; + if ( this._noCosmeticFiltering && logger.enabled ) { + µb.filteringContext + .duplicate() + .fromTabId(this.tabId) + .setURL(this.rawURL) + .setRealm('cosmetic') + .setType('dom') + .setFilter(sessionSwitches.toLogData()) + .toLogger(); + } + } + } + if ( this._noCosmeticFiltering ) { return false; } + if ( frameId === -1 ) { return true; } + // Cosmetic filtering can be effectively disabled when both specific + // and generic cosmetic filters are disabled. + return this.shouldApplySpecificCosmeticFilters(frameId) || + this.shouldApplyGenericCosmeticFilters(frameId); + } + + shouldApplySpecificCosmeticFilters(frameId) { + if ( this.shouldApplyCosmeticFilters(-1) === false ) { return false; } + const frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { return false; } + return frameStore.shouldApplySpecificCosmeticFilters(this.tabId); + } + + shouldApplyGenericCosmeticFilters(frameId) { + if ( this.shouldApplyCosmeticFilters(-1) === false ) { return false; } + const frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { return false; } + return frameStore.shouldApplyGenericCosmeticFilters(this.tabId); + } + + // https://github.com/gorhill/uBlock/issues/2105 + // Be sure to always include the current page's hostname -- it might not + // be present when the page itself is pulled from the browser's + // short-term memory cache. + getAllHostnameDetails() { + if ( + this.hostnameDetailsMap.has(this.tabHostname) === false && + isNetworkURI(this.rawURL) + ) { + this.hostnameDetailsMap.set( + this.tabHostname, + new HostnameDetails(this.tabHostname) + ); + } + return this.hostnameDetailsMap; + } + + injectLargeMediaElementScriptlet() { + vAPI.tabs.executeScript(this.tabId, { + file: '/js/scriptlets/load-large-media-interactive.js', + allFrames: true, + runAt: 'document_idle', + }); + contextMenu.update(this.tabId); + } + + temporarilyAllowLargeMediaElements(state) { + this.largeMediaCount = 0; + contextMenu.update(this.tabId); + if ( state ) { + this.allowLargeMediaElementsUntil = 0; + this.allowLargeMediaElementsRegex = undefined; + } else { + this.allowLargeMediaElementsUntil = Date.now(); + } + vAPI.tabs.executeScript(this.tabId, { + file: '/js/scriptlets/load-large-media-all.js', + allFrames: true, + }); + } + + // https://github.com/gorhill/uBlock/issues/2053 + // There is no way around using journaling to ensure we deal properly with + // potentially out of order navigation events vs. network request events. + journalAddRequest(fctxt, result) { + const hostname = fctxt.getHostname(); + if ( hostname === '' ) { return; } + this.journal.push(hostname, result, fctxt.itype); + this.journalTimer.on(µb.hiddenSettings.requestJournalProcessPeriod); + } + + journalAddRootFrame(type, url) { + if ( type === 'committed' ) { + this.journalLastCommitted = this.journal.length; + if ( + this.journalLastUncommitted !== -1 && + this.journalLastUncommitted < this.journalLastCommitted && + this.journalLastUncommittedOrigin === hostnameFromURI(url) + ) { + this.journalLastCommitted = this.journalLastUncommitted; + } + } else if ( type === 'uncommitted' ) { + const newOrigin = hostnameFromURI(url); + if ( + this.journalLastUncommitted === -1 || + this.journalLastUncommittedOrigin !== newOrigin + ) { + this.journalLastUncommitted = this.journal.length; + this.journalLastUncommittedOrigin = newOrigin; + } + } + this.journalTimer.offon(µb.hiddenSettings.requestJournalProcessPeriod); + } + + journalProcess() { + this.journalTimer.off(); + + const journal = this.journal; + const pivot = Math.max(0, this.journalLastCommitted); + const now = Date.now(); + const { SCRIPT, SUB_FRAME, OBJECT } = µb.FilteringContext; + let aggregateAllowed = 0; + let aggregateBlocked = 0; + + // Everything after pivot originates from current page. + for ( let i = pivot; i < journal.length; i += 3 ) { + const hostname = journal[i+0]; + let hnDetails = this.hostnameDetailsMap.get(hostname); + if ( hnDetails === undefined ) { + hnDetails = new HostnameDetails(hostname); + this.hostnameDetailsMap.set(hostname, hnDetails); + this.contentLastModified = now; + } + const blocked = journal[i+1] === 1; + const itype = journal[i+2]; + if ( itype === SCRIPT ) { + hnDetails.counts.inc(blocked, 'script'); + this.counts.inc(blocked, 'script'); + } else if ( itype === SUB_FRAME || itype === OBJECT ) { + hnDetails.counts.inc(blocked, 'frame'); + this.counts.inc(blocked, 'frame'); + } else { + hnDetails.counts.inc(blocked); + this.counts.inc(blocked); + } + if ( blocked ) { + aggregateBlocked += 1; + } else { + aggregateAllowed += 1; + } + } + this.journalLastUncommitted = this.journalLastCommitted = -1; + + // https://github.com/chrisaljoudi/uBlock/issues/905#issuecomment-76543649 + // No point updating the badge if it's not being displayed. + if ( aggregateBlocked !== 0 && µb.userSettings.showIconBadge ) { + µb.updateToolbarIcon(this.tabId, 0x02); + } + + // Everything before pivot does not originate from current page -- we + // still need to bump global blocked/allowed counts. + for ( let i = 0; i < pivot; i += 3 ) { + if ( journal[i+1] === 1 ) { + aggregateBlocked += 1; + } else { + aggregateAllowed += 1; + } + } + if ( aggregateAllowed !== 0 || aggregateBlocked !== 0 ) { + µb.localSettings.blockedRequestCount += aggregateBlocked; + µb.localSettings.allowedRequestCount += aggregateAllowed; + µb.localSettingsLastModified = now; + } + journal.length = 0; + } + + filterRequest(fctxt) { + fctxt.filter = undefined; + fctxt.redirectURL = undefined; + + if ( this.getNetFilteringSwitch(fctxt) === false ) { + return 0; + } + + if ( + fctxt.itype === fctxt.CSP_REPORT && + this.filterCSPReport(fctxt) === 1 + ) { + return 1; + } + + if ( + (fctxt.itype & fctxt.FONT_ANY) !== 0 && + this.filterFont(fctxt) === 1 ) + { + return 1; + } + + if ( + fctxt.itype === fctxt.SCRIPT && + this.filterScripting(fctxt, true) === 1 + ) { + return 1; + } + + const cacheableResult = + this.cacheableResults.has(fctxt.itype) && + fctxt.aliasURL === undefined; + + if ( cacheableResult ) { + const entry = this.netFilteringCache.lookupResult(fctxt); + if ( entry !== undefined ) { + fctxt.redirectURL = entry.redirectURL; + fctxt.filter = entry.logData; + return entry.result; + } + } + + const requestType = fctxt.type; + const loggerEnabled = logger.enabled; + + // Dynamic URL filtering. + let result = sessionURLFiltering.evaluateZ( + fctxt.getTabHostname(), + fctxt.url, + requestType + ); + if ( result !== 0 && loggerEnabled ) { + fctxt.filter = sessionURLFiltering.toLogData(); + } + + // Dynamic hostname/type filtering. + if ( result === 0 && µb.userSettings.advancedUserEnabled ) { + result = sessionFirewall.evaluateCellZY( + fctxt.getTabHostname(), + fctxt.getHostname(), + requestType + ); + if ( result !== 0 && result !== 3 && loggerEnabled ) { + fctxt.filter = sessionFirewall.toLogData(); + } + } + + // Static filtering has lowest precedence. + const snfe = staticNetFilteringEngine; + if ( result === 0 || result === 3 ) { + result = snfe.matchRequest(fctxt); + if ( result !== 0 ) { + if ( loggerEnabled ) { + fctxt.setFilter(snfe.toLogData()); + } + // https://github.com/uBlockOrigin/uBlock-issues/issues/943 + // Blanket-except blocked aliased canonical hostnames? + if ( + result === 1 && + fctxt.aliasURL !== undefined && + snfe.isBlockImportant() === false && + this.shouldExceptCname(fctxt) + ) { + return 2; + } + } + } + + // Click-to-load? + // When frameId is not -1, the resource is always sub_frame. + if ( result === 1 && fctxt.frameId !== -1 ) { + const frameStore = this.getFrameStore(fctxt.frameId); + if ( frameStore !== null && frameStore.clickToLoad ) { + result = 2; + if ( loggerEnabled ) { + fctxt.pushFilter({ + result, + source: 'network', + raw: 'click-to-load', + }); + } + } + } + + // Modifier(s)? + // A modifier is an action which transform the original network request. + // https://github.com/gorhill/uBlock/issues/949 + // Redirect blocked request? + // https://github.com/uBlockOrigin/uBlock-issues/issues/760 + // Redirect non-blocked request? + if ( (fctxt.itype & fctxt.INLINE_ANY) === 0 ) { + if ( result === 1 ) { + this.redirectBlockedRequest(fctxt); + } else { + this.redirectNonBlockedRequest(fctxt); + } + } + + if ( cacheableResult ) { + this.netFilteringCache.rememberResult(fctxt, result); + } else if ( result === 1 && this.collapsibleResources.has(fctxt.itype) ) { + this.netFilteringCache.rememberBlock(fctxt); + } + + return result; + } + + filterOnHeaders(fctxt, headers) { + fctxt.filter = undefined; + + if ( this.getNetFilteringSwitch(fctxt) === false ) { return 0; } + + let result = staticNetFilteringEngine.matchHeaders(fctxt, headers); + if ( result === 0 ) { return 0; } + + const loggerEnabled = logger.enabled; + if ( loggerEnabled ) { + fctxt.filter = staticNetFilteringEngine.toLogData(); + } + + // Dynamic filtering allow rules + // URL filtering + if ( + result === 1 && + sessionURLFiltering.evaluateZ( + fctxt.getTabHostname(), + fctxt.url, + fctxt.type + ) === 2 + ) { + result = 2; + if ( loggerEnabled ) { + fctxt.filter = sessionURLFiltering.toLogData(); + } + } + // Hostname filtering + if ( + result === 1 && + µb.userSettings.advancedUserEnabled && + sessionFirewall.evaluateCellZY( + fctxt.getTabHostname(), + fctxt.getHostname(), + fctxt.type + ) === 2 + ) { + result = 2; + if ( loggerEnabled ) { + fctxt.filter = sessionFirewall.toLogData(); + } + } + + return result; + } + + redirectBlockedRequest(fctxt) { + const directives = staticNetFilteringEngine.redirectRequest(redirectEngine, fctxt); + if ( directives === undefined ) { return; } + if ( logger.enabled !== true ) { return; } + fctxt.pushFilters(directives.map(a => a.logData())); + if ( fctxt.redirectURL === undefined ) { return; } + fctxt.pushFilter({ + source: 'redirect', + raw: directives[directives.length-1].value + }); + } + + redirectNonBlockedRequest(fctxt) { + const transformDirectives = staticNetFilteringEngine.transformRequest(fctxt); + const pruneDirectives = fctxt.redirectURL === undefined && + staticNetFilteringEngine.hasQuery(fctxt) && + staticNetFilteringEngine.filterQuery(fctxt) || + undefined; + if ( transformDirectives === undefined && pruneDirectives === undefined ) { return; } + if ( logger.enabled !== true ) { return; } + if ( transformDirectives !== undefined ) { + fctxt.pushFilters(transformDirectives.map(a => a.logData())); + } + if ( pruneDirectives !== undefined ) { + fctxt.pushFilters(pruneDirectives.map(a => a.logData())); + } + if ( fctxt.redirectURL === undefined ) { return; } + fctxt.pushFilter({ + source: 'redirect', + raw: fctxt.redirectURL + }); + } + + filterCSPReport(fctxt) { + if ( + sessionSwitches.evaluateZ( + 'no-csp-reports', + fctxt.getHostname() + ) + ) { + if ( logger.enabled ) { + fctxt.filter = sessionSwitches.toLogData(); + } + return 1; + } + return 0; + } + + filterFont(fctxt) { + if ( fctxt.itype === fctxt.FONT ) { + this.remoteFontCount += 1; + } + if ( + sessionSwitches.evaluateZ( + 'no-remote-fonts', + fctxt.getTabHostname() + ) !== false + ) { + if ( logger.enabled ) { + fctxt.filter = sessionSwitches.toLogData(); + } + return 1; + } + return 0; + } + + filterScripting(fctxt, netFiltering) { + fctxt.filter = undefined; + if ( netFiltering === undefined ) { + netFiltering = this.getNetFilteringSwitch(fctxt); + } + if ( + netFiltering === false || + sessionSwitches.evaluateZ( + 'no-scripting', + fctxt.getTabHostname() + ) === false + ) { + return 0; + } + if ( logger.enabled ) { + fctxt.filter = sessionSwitches.toLogData(); + } + return 1; + } + + // The caller is responsible to check whether filtering is enabled or not. + filterLargeMediaElement(fctxt, size) { + fctxt.filter = undefined; + + if ( this.allowLargeMediaElementsUntil === 0 ) { + return 0; + } + // Disregard large media elements previously allowed: for example, to + // seek inside a previously allowed audio/video. + if ( + this.allowLargeMediaElementsRegex instanceof RegExp && + this.allowLargeMediaElementsRegex.test(fctxt.url) + ) { + return 0; + } + if ( Date.now() < this.allowLargeMediaElementsUntil ) { + const sources = this.allowLargeMediaElementsRegex instanceof RegExp + ? [ this.allowLargeMediaElementsRegex.source ] + : []; + sources.push('^' + µb.escapeRegex(fctxt.url)); + this.allowLargeMediaElementsRegex = new RegExp(sources.join('|')); + return 0; + } + if ( + sessionSwitches.evaluateZ( + 'no-large-media', + fctxt.getTabHostname() + ) !== true + ) { + this.allowLargeMediaElementsUntil = 0; + return 0; + } + if ( (size >>> 10) < µb.userSettings.largeMediaSize ) { + return 0; + } + + this.largeMediaCount += 1; + this.largeMediaTimer.on(500); + + if ( logger.enabled ) { + fctxt.filter = sessionSwitches.toLogData(); + } + + return 1; + } + + clickToLoad(frameId, frameURL) { + let frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { + frameStore = this.setFrameURL({ frameId, url: frameURL }); + } + this.netFilteringCache.forgetResult( + this.tabHostname, + 'sub_frame', + frameURL + ); + frameStore.clickToLoad = true; + } + + shouldExceptCname(fctxt) { + let exceptCname; + let frameStore; + if ( fctxt.docId !== undefined ) { + frameStore = this.getFrameStore(fctxt.docId); + if ( frameStore instanceof Object ) { + exceptCname = frameStore.exceptCname; + } + } + if ( exceptCname === undefined ) { + const result = staticNetFilteringEngine.matchRequestReverse( + 'cname', + frameStore instanceof Object + ? frameStore.rawURL + : fctxt.getDocOrigin() + ); + exceptCname = result === 2 + ? staticNetFilteringEngine.toLogData() + : false; + if ( frameStore instanceof Object ) { + frameStore.exceptCname = exceptCname; + } + } + if ( exceptCname === false ) { return false; } + if ( exceptCname instanceof Object ) { + fctxt.setFilter(exceptCname); + } + return true; + } + + getBlockedResources(request, response) { + const normalURL = µb.normalizeTabURL(this.tabId, request.frameURL); + const resources = request.resources; + const fctxt = µb.filteringContext; + fctxt.fromTabId(this.tabId) + .setDocOriginFromURL(normalURL); + // Force some resources to go through the filtering engine in order to + // populate the blocked-resources cache. This is required because for + // some resources it's not possible to detect whether they were blocked + // content script-side (i.e. `iframes` -- unlike `img`). + if ( Array.isArray(resources) && resources.length !== 0 ) { + for ( const resource of resources ) { + this.filterRequest( + fctxt.setType(resource.type).setURL(resource.url) + ); + } + } + if ( this.netFilteringCache.hash === response.hash ) { return; } + response.hash = this.netFilteringCache.hash; + response.blockedResources = + this.netFilteringCache.lookupAllBlocked(fctxt.getDocHostname()); + } +}; + +PageStore.prototype.cacheableResults = new Set([ + µb.FilteringContext.SUB_FRAME, +]); + +PageStore.prototype.collapsibleResources = new Set([ + µb.FilteringContext.IMAGE, + µb.FilteringContext.MEDIA, + µb.FilteringContext.OBJECT, + µb.FilteringContext.SUB_FRAME, +]); + +// To mitigate memory churning +PageStore.junkyard = []; +PageStore.junkyardMax = 10; + +/******************************************************************************/ + +export { PageStore }; diff --git a/src/js/popup-fenix.js b/src/js/popup-fenix.js new file mode 100644 index 0000000..b44b923 --- /dev/null +++ b/src/js/popup-fenix.js @@ -0,0 +1,1530 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +'use strict'; + +import punycode from '../lib/punycode.js'; +import { i18n$ } from './i18n.js'; +import { dom, qs$, qsa$ } from './dom.js'; + +/******************************************************************************/ + +let popupFontSize = 'unset'; +vAPI.localStorage.getItemAsync('popupFontSize').then(value => { + if ( typeof value !== 'string' || value === 'unset' ) { return; } + document.body.style.setProperty('--font-size', value); + popupFontSize = value; +}); + +// https://github.com/chrisaljoudi/uBlock/issues/996 +// Experimental: mitigate glitchy popup UI: immediately set the firewall +// pane visibility to its last known state. By default the pane is hidden. +vAPI.localStorage.getItemAsync('popupPanelSections').then(bits => { + if ( typeof bits !== 'number' ) { return; } + setSections(bits); +}); + +/******************************************************************************/ + +const messaging = vAPI.messaging; +const scopeToSrcHostnameMap = { + '/': '*', + '.': '' +}; +const hostnameToSortableTokenMap = new Map(); +const statsStr = i18n$('popupBlockedStats'); +const domainsHitStr = i18n$('popupHitDomainCount'); + +let popupData = {}; +let dfPaneBuilt = false; +let dfHotspots = null; +const allHostnameRows = []; +let cachedPopupHash = ''; + +// https://github.com/gorhill/uBlock/issues/2550 +// Solution inspired from +// - https://bugs.chromium.org/p/chromium/issues/detail?id=683314 +// - https://bugzilla.mozilla.org/show_bug.cgi?id=1332714#c17 +// Confusable character set from: +// - http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%D0%B0%D1%81%D4%81%D0%B5%D2%BB%D1%96%D1%98%D3%8F%D0%BE%D1%80%D4%9B%D1%95%D4%9D%D1%85%D1%83%D1%8A%D0%AC%D2%BD%D0%BF%D0%B3%D1%B5%D1%A1%5D&g=gc&i= +// Linked from: +// - https://www.chromium.org/developers/design-documents/idn-in-google-chrome +const reCyrillicNonAmbiguous = /[\u0400-\u042b\u042d-\u042f\u0431\u0432\u0434\u0436-\u043d\u0442\u0444\u0446-\u0449\u044b-\u0454\u0457\u0459-\u0460\u0462-\u0474\u0476-\u04ba\u04bc\u04be-\u04ce\u04d0-\u0500\u0502-\u051a\u051c\u051e-\u052f]/; +const reCyrillicAmbiguous = /[\u042c\u0430\u0433\u0435\u043e\u043f\u0440\u0441\u0443\u0445\u044a\u0455\u0456\u0458\u0461\u0475\u04bb\u04bd\u04cf\u0501\u051b\u051d]/; + +/******************************************************************************/ + +const cachePopupData = function(data) { + popupData = {}; + scopeToSrcHostnameMap['.'] = ''; + hostnameToSortableTokenMap.clear(); + + if ( typeof data !== 'object' ) { + return popupData; + } + popupData = data; + popupData.cnameMap = new Map(popupData.cnameMap); + scopeToSrcHostnameMap['.'] = popupData.pageHostname || ''; + const hostnameDict = popupData.hostnameDict; + if ( typeof hostnameDict !== 'object' ) { + return popupData; + } + for ( const hostname in hostnameDict ) { + if ( hostnameDict.hasOwnProperty(hostname) === false ) { continue; } + let domain = hostnameDict[hostname].domain; + let prefix = hostname.slice(0, 0 - domain.length - 1); + // Prefix with space char for 1st-party hostnames: this ensure these + // will come first in list. + if ( domain === popupData.pageDomain ) { + domain = '\u0020'; + } + hostnameToSortableTokenMap.set( + hostname, + domain + ' ' + prefix.split('.').reverse().join('.') + ); + } + return popupData; +}; + +/******************************************************************************/ + +const hashFromPopupData = function(reset = false) { + // It makes no sense to offer to refresh the behind-the-scene scope + if ( popupData.pageHostname === 'behind-the-scene' ) { + dom.cl.remove(dom.body, 'needReload'); + return; + } + + const hasher = []; + const rules = popupData.firewallRules; + for ( const key in rules ) { + const rule = rules[key]; + if ( rule === undefined ) { continue; } + hasher.push(rule); + } + hasher.sort(); + hasher.push( + dom.cl.has('body', 'off'), + dom.cl.has('#no-large-media', 'on'), + dom.cl.has('#no-cosmetic-filtering', 'on'), + dom.cl.has('#no-remote-fonts', 'on'), + dom.cl.has('#no-scripting', 'on') + ); + + const hash = hasher.join(''); + if ( reset ) { + cachedPopupHash = hash; + } + dom.cl.toggle(dom.body, 'needReload', + hash !== cachedPopupHash || popupData.hasUnprocessedRequest === true + ); +}; + +/******************************************************************************/ + +// greater-than-zero test + +const gtz = n => typeof n === 'number' && n > 0; + +/******************************************************************************/ + +const formatNumber = function(count) { + if ( typeof count !== 'number' ) { return ''; } + if ( count < 1e6 ) { return count.toLocaleString(); } + + if ( + intlNumberFormat === undefined && + Intl.NumberFormat instanceof Function + ) { + const intl = new Intl.NumberFormat(undefined, { + notation: 'compact', + maximumSignificantDigits: 4 + }); + if ( + intl.resolvedOptions instanceof Function && + intl.resolvedOptions().hasOwnProperty('notation') + ) { + intlNumberFormat = intl; + } + } + + if ( intlNumberFormat ) { + return intlNumberFormat.format(count); + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1027#issuecomment-629696676 + // For platforms which do not support proper number formatting, use + // a poor's man compact form, which unfortunately is not i18n-friendly. + count /= 1000000; + if ( count >= 100 ) { + count = Math.floor(count * 10) / 10; + } else if ( count > 10 ) { + count = Math.floor(count * 100) / 100; + } else { + count = Math.floor(count * 1000) / 1000; + } + return (count).toLocaleString(undefined) + '\u2009M'; +}; + +let intlNumberFormat; + +/******************************************************************************/ + +const safePunycodeToUnicode = function(hn) { + const pretty = punycode.toUnicode(hn); + return pretty === hn || + reCyrillicAmbiguous.test(pretty) === false || + reCyrillicNonAmbiguous.test(pretty) + ? pretty + : hn; +}; + +/******************************************************************************/ + +const updateFirewallCellCount = function(cells, allowed, blocked) { + for ( const cell of cells ) { + if ( gtz(allowed) ) { + dom.attr(cell, 'data-acount', + Math.min(Math.ceil(Math.log(allowed + 1) / Math.LN10), 3) + ); + } else { + dom.attr(cell, 'data-acount', '0'); + } + if ( gtz(blocked) ) { + dom.attr(cell, 'data-bcount', + Math.min(Math.ceil(Math.log(blocked + 1) / Math.LN10), 3) + ); + } else { + dom.attr(cell, 'data-bcount', '0'); + } + } +}; + +/******************************************************************************/ + +const updateFirewallCellRule = function(cells, scope, des, type, rule) { + const ruleParts = rule !== undefined ? rule.split(' ') : undefined; + + for ( const cell of cells ) { + if ( ruleParts === undefined ) { + dom.attr(cell, 'class', null); + continue; + } + + const action = updateFirewallCellRule.actionNames[ruleParts[3]]; + dom.attr(cell, 'class', `${action}Rule`); + + // Use dark shade visual cue if the rule is specific to the cell. + if ( + (ruleParts[1] !== '*' || ruleParts[2] === type) && + (ruleParts[1] === des) && + (ruleParts[0] === scopeToSrcHostnameMap[scope]) + + ) { + dom.cl.add(cell, 'ownRule'); + } + } +}; + +updateFirewallCellRule.actionNames = { '1': 'block', '2': 'allow', '3': 'noop' }; + +/******************************************************************************/ + +const updateAllFirewallCells = function(doRules = true, doCounts = true) { + const { pageDomain } = popupData; + const rowContainer = qs$('#firewall'); + const rows = qsa$(rowContainer, '#firewall > [data-des][data-type]'); + + let a1pScript = 0, b1pScript = 0; + let a3pScript = 0, b3pScript = 0; + let a3pFrame = 0, b3pFrame = 0; + + for ( const row of rows ) { + const des = dom.attr(row, 'data-des'); + const type = dom.attr(row, 'data-type'); + if ( doRules ) { + updateFirewallCellRule( + qsa$(row, ':scope > span[data-src="/"]'), + '/', + des, + type, + popupData.firewallRules[`/ ${des} ${type}`] + ); + } + const cells = qsa$(row, ':scope > span[data-src="."]'); + if ( doRules ) { + updateFirewallCellRule( + cells, + '.', + des, + type, + popupData.firewallRules[`. ${des} ${type}`] + ); + } + if ( des === '*' || type !== '*' ) { continue; } + if ( doCounts === false ) { continue; } + const hnDetails = popupData.hostnameDict[des]; + if ( hnDetails === undefined ) { + updateFirewallCellCount(cells); + continue; + } + const { allowed, blocked } = hnDetails.counts; + updateFirewallCellCount([ cells[0] ], allowed.any, blocked.any); + const { totals } = hnDetails; + if ( totals !== undefined ) { + updateFirewallCellCount([ cells[1] ], totals.allowed.any, totals.blocked.any); + } + if ( hnDetails.domain === pageDomain ) { + a1pScript += allowed.script; b1pScript += blocked.script; + } else { + a3pScript += allowed.script; b3pScript += blocked.script; + a3pFrame += allowed.frame; b3pFrame += blocked.frame; + } + } + + if ( doCounts ) { + const fromType = type => + qsa$(`#firewall > [data-des="*"][data-type="${type}"] > [data-src="."]`); + updateFirewallCellCount(fromType('1p-script'), a1pScript, b1pScript); + updateFirewallCellCount(fromType('3p-script'), a3pScript, b3pScript); + dom.cl.toggle(rowContainer, 'has3pScript', a3pScript !== 0 || b3pScript !== 0); + updateFirewallCellCount(fromType('3p-frame'), a3pFrame, b3pFrame); + dom.cl.toggle(rowContainer, 'has3pFrame', a3pFrame !== 0 || b3pFrame !== 0); + } + + dom.cl.toggle(dom.body, 'needSave', popupData.matrixIsDirty === true); +}; + +/******************************************************************************/ + +// Compute statistics useful only to firewall entries -- we need to call +// this only when overview pane needs to be rendered. + +const expandHostnameStats = ( ) => { + let dnDetails; + for ( const des of allHostnameRows ) { + const hnDetails = popupData.hostnameDict[des]; + const { domain, counts } = hnDetails; + const isDomain = des === domain; + const { allowed: hnAllowed, blocked: hnBlocked } = counts; + if ( isDomain ) { + dnDetails = hnDetails; + dnDetails.totals = JSON.parse(JSON.stringify(dnDetails.counts)); + } else { + const { allowed: dnAllowed, blocked: dnBlocked } = dnDetails.totals; + dnAllowed.any += hnAllowed.any; + dnBlocked.any += hnBlocked.any; + } + hnDetails.hasScript = hnAllowed.script !== 0 || hnBlocked.script !== 0; + dnDetails.hasScript = dnDetails.hasScript || hnDetails.hasScript; + hnDetails.hasFrame = hnAllowed.frame !== 0 || hnBlocked.frame !== 0; + dnDetails.hasFrame = dnDetails.hasFrame || hnDetails.hasFrame; + } +}; + +/******************************************************************************/ + +const buildAllFirewallRows = function() { + // Do this before removing the rows + if ( dfHotspots === null ) { + dfHotspots = qs$('#actionSelector'); + dom.on(dfHotspots, 'click', setFirewallRuleHandler); + } + dfHotspots.remove(); + + // This must be called before we create the rows. + expandHostnameStats(); + + // Update incrementally: reuse existing rows if possible. + const rowContainer = qs$('#firewall'); + const toAppend = document.createDocumentFragment(); + const rowTemplate = qs$('#templates > div[data-des=""][data-type="*"]'); + const { cnameMap, hostnameDict, pageDomain, pageHostname } = popupData; + + let row = qs$(rowContainer, 'div[data-des="*"][data-type="3p-frame"] + div'); + + for ( const des of allHostnameRows ) { + if ( row === null ) { + row = dom.clone(rowTemplate); + toAppend.appendChild(row); + } + dom.attr(row, 'data-des', des); + + const hnDetails = hostnameDict[des] || {}; + const isDomain = des === hnDetails.domain; + const prettyDomainName = des.includes('xn--') + ? punycode.toUnicode(des) + : des; + const isPunycoded = prettyDomainName !== des; + + if ( isDomain && row.childElementCount < 4 ) { + row.append(dom.clone(row.children[2])); + } else if ( isDomain === false && row.childElementCount === 4 ) { + row.children[3].remove(); + } + + const span = qs$(row, 'span:first-of-type'); + dom.text(qs$(span, ':scope > span > span'), prettyDomainName); + + const classList = row.classList; + + let desExtra = ''; + if ( classList.toggle('isCname', cnameMap.has(des)) ) { + desExtra = punycode.toUnicode(cnameMap.get(des)); + } else if ( + isDomain && isPunycoded && + reCyrillicAmbiguous.test(prettyDomainName) && + reCyrillicNonAmbiguous.test(prettyDomainName) === false + ) { + desExtra = des; + } + dom.text(qs$(span, 'sub'), desExtra); + + classList.toggle('isRootContext', des === pageHostname); + classList.toggle('is3p', hnDetails.domain !== pageDomain); + classList.toggle('isDomain', isDomain); + classList.toggle('hasSubdomains', isDomain && hnDetails.hasSubdomains); + classList.toggle('isSubdomain', !isDomain); + const { counts } = hnDetails; + classList.toggle('allowed', gtz(counts.allowed.any)); + classList.toggle('blocked', gtz(counts.blocked.any)); + const { totals } = hnDetails; + classList.toggle('totalAllowed', gtz(totals && totals.allowed.any)); + classList.toggle('totalBlocked', gtz(totals && totals.blocked.any)); + classList.toggle('hasScript', hnDetails.hasScript === true); + classList.toggle('hasFrame', hnDetails.hasFrame === true); + classList.toggle('expandException', expandExceptions.has(hnDetails.domain)); + + row = row.nextElementSibling; + } + + // Remove unused trailing rows + if ( row !== null ) { + while ( row.nextElementSibling !== null ) { + row.nextElementSibling.remove(); + } + row.remove(); + } + + // Add new rows all at once + if ( toAppend.childElementCount !== 0 ) { + rowContainer.append(toAppend); + } + + if ( dfPaneBuilt !== true && popupData.advancedUserEnabled ) { + dom.on('#firewall', 'click', 'span[data-src]', unsetFirewallRuleHandler); + dom.on('#firewall', 'mouseenter', 'span[data-src]', mouseenterCellHandler); + dom.on('#firewall', 'mouseleave', 'span[data-src]', mouseleaveCellHandler); + dfPaneBuilt = true; + } + + updateAllFirewallCells(); +}; + +/******************************************************************************/ + +const hostnameCompare = function(a, b) { + let ha = a; + if ( !reIP.test(ha) ) { + ha = hostnameToSortableTokenMap.get(ha) || ' '; + } + let hb = b; + if ( !reIP.test(hb) ) { + hb = hostnameToSortableTokenMap.get(hb) || ' '; + } + const ca = ha.charCodeAt(0); + const cb = hb.charCodeAt(0); + return ca !== cb ? ca - cb : ha.localeCompare(hb); +}; + +const reIP = /(\d|\])$/; + +/******************************************************************************/ + +function filterFirewallRows() { + const firewallElem = qs$('#firewall'); + const elems = qsa$('#firewall .filterExpressions span[data-expr]'); + let not = false; + for ( const elem of elems ) { + const on = dom.cl.has(elem, 'on'); + switch ( elem.dataset.expr ) { + case 'not': + not = on; + break; + case 'blocked': + dom.cl.toggle(firewallElem, 'showBlocked', !not && on); + dom.cl.toggle(firewallElem, 'hideBlocked', not && on); + break; + case 'allowed': + dom.cl.toggle(firewallElem, 'showAllowed', !not && on); + dom.cl.toggle(firewallElem, 'hideAllowed', not && on); + break; + case 'script': + dom.cl.toggle(firewallElem, 'show3pScript', !not && on); + dom.cl.toggle(firewallElem, 'hide3pScript', not && on); + break; + case 'frame': + dom.cl.toggle(firewallElem, 'show3pFrame', !not && on); + dom.cl.toggle(firewallElem, 'hide3pFrame', not && on); + break; + default: + break; + } + } +} + +dom.on('#firewall .filterExpressions', 'click', 'span[data-expr]', ev => { + const target = ev.target; + dom.cl.toggle(target, 'on'); + switch ( target.dataset.expr ) { + case 'blocked': + if ( dom.cl.has(target, 'on') === false ) { break; } + dom.cl.remove('#firewall .filterExpressions span[data-expr="allowed"]', 'on'); + break; + case 'allowed': + if ( dom.cl.has(target, 'on') === false ) { break; } + dom.cl.remove('#firewall .filterExpressions span[data-expr="blocked"]', 'on'); + break; + } + filterFirewallRows(); + const elems = qsa$('#firewall .filterExpressions span[data-expr]'); + const filters = Array.from(elems) .map(el => dom.cl.has(el, 'on') ? '1' : '0'); + filters.unshift('00'); + vAPI.localStorage.setItem('firewallFilters', filters.join(' ')); +}); + +{ + vAPI.localStorage.getItemAsync('firewallFilters').then(v => { + if ( v === null ) { return; } + const filters = v.split(' '); + if ( filters.shift() !== '00' ) { return; } + if ( filters.every(v => v === '0') ) { return; } + const elems = qsa$('#firewall .filterExpressions span[data-expr]'); + for ( let i = 0; i < elems.length; i++ ) { + if ( filters[i] === '0' ) { continue; } + dom.cl.add(elems[i], 'on'); + } + filterFirewallRows(); + }); +} + +/******************************************************************************/ + +const renderPrivacyExposure = function() { + const allDomains = {}; + let allDomainCount = 0; + let touchedDomainCount = 0; + + allHostnameRows.length = 0; + + // Sort hostnames. First-party hostnames must always appear at the top + // of the list. + const { hostnameDict } = popupData; + const desHostnameDone = new Set(); + const keys = Object.keys(hostnameDict).sort(hostnameCompare); + for ( const des of keys ) { + // Specific-type rules -- these are built-in + if ( des === '*' || desHostnameDone.has(des) ) { continue; } + const hnDetails = hostnameDict[des]; + const { domain, counts } = hnDetails; + if ( allDomains.hasOwnProperty(domain) === false ) { + allDomains[domain] = false; + allDomainCount += 1; + } + if ( gtz(counts.allowed.any) ) { + if ( allDomains[domain] === false ) { + allDomains[domain] = true; + touchedDomainCount += 1; + } + } + const dnDetails = hostnameDict[domain]; + if ( dnDetails !== undefined ) { + if ( des !== domain ) { + dnDetails.hasSubdomains = true; + } else if ( dnDetails.hasSubdomains === undefined ) { + dnDetails.hasSubdomains = false; + } + } + allHostnameRows.push(des); + desHostnameDone.add(des); + } + + const summary = domainsHitStr + .replace('{{count}}', touchedDomainCount.toLocaleString()) + .replace('{{total}}', allDomainCount.toLocaleString()); + dom.text('[data-i18n^="popupDomainsConnected"] + span', summary); +}; + +/******************************************************************************/ + +const updateHnSwitches = function() { + dom.cl.toggle('#no-popups', 'on', popupData.noPopups === true); + dom.cl.toggle('#no-large-media', 'on', popupData.noLargeMedia === true); + dom.cl.toggle('#no-cosmetic-filtering', 'on',popupData.noCosmeticFiltering === true); + dom.cl.toggle('#no-remote-fonts', 'on', popupData.noRemoteFonts === true); + dom.cl.toggle('#no-scripting', 'on', popupData.noScripting === true); +}; + +/******************************************************************************/ + +// Assume everything has to be done incrementally. + +const renderPopup = function() { + if ( popupData.tabTitle ) { + document.title = popupData.appName + ' - ' + popupData.tabTitle; + } + + const isFiltering = popupData.netFilteringSwitch; + + dom.cl.toggle(dom.body, 'advancedUser', popupData.advancedUserEnabled === true); + dom.cl.toggle(dom.body, 'off', popupData.pageURL === '' || isFiltering !== true); + dom.cl.toggle(dom.body, 'needSave', popupData.matrixIsDirty === true); + + // The hostname information below the power switch + { + const [ elemHn, elemDn ] = qs$('#hostname').children; + const { pageDomain, pageHostname } = popupData; + if ( pageDomain !== '' ) { + dom.text(elemDn, safePunycodeToUnicode(pageDomain)); + dom.text(elemHn, pageHostname !== pageDomain + ? safePunycodeToUnicode(pageHostname.slice(0, -pageDomain.length - 1)) + '.' + : '' + ); + } else { + dom.text(elemDn, ''); + dom.text(elemHn, ''); + } + } + + dom.cl.toggle( + '#basicTools', + 'canPick', + popupData.canElementPicker === true && isFiltering + ); + + let blocked, total; + if ( popupData.pageCounts !== undefined ) { + const counts = popupData.pageCounts; + blocked = counts.blocked.any; + total = blocked + counts.allowed.any; + } else { + blocked = 0; + total = 0; + } + let text; + if ( total === 0 ) { + text = formatNumber(0); + } else { + text = statsStr.replace('{{count}}', formatNumber(blocked)) + .replace('{{percent}}', formatNumber(Math.floor(blocked * 100 / total))); + } + dom.text('[data-i18n^="popupBlockedOnThisPage"] + span', text); + + blocked = popupData.globalBlockedRequestCount; + total = popupData.globalAllowedRequestCount + blocked; + if ( total === 0 ) { + text = formatNumber(0); + } else { + text = statsStr.replace('{{count}}', formatNumber(blocked)) + .replace('{{percent}}', formatNumber(Math.floor(blocked * 100 / total))); + } + dom.text('[data-i18n^="popupBlockedSinceInstall"] + span', text); + + // This will collate all domains, touched or not + renderPrivacyExposure(); + + // Extra tools + updateHnSwitches(); + + // Report popup count on badge + total = popupData.popupBlockedCount; + dom.text( + '#no-popups .fa-icon-badge', + total ? Math.min(total, 99).toLocaleString() : '' + ); + + // Report large media count on badge + total = popupData.largeMediaCount; + dom.text( + '#no-large-media .fa-icon-badge', + total ? Math.min(total, 99).toLocaleString() : '' + ); + + // Report remote font count on badge + total = popupData.remoteFontCount; + dom.text( + '#no-remote-fonts .fa-icon-badge', + total ? Math.min(total, 99).toLocaleString() : '' + ); + + // Unprocesseed request(s) warning + dom.cl.toggle(dom.root, 'warn', popupData.hasUnprocessedRequest === true); + + dom.cl.toggle(dom.html, 'colorBlind', popupData.colorBlindFriendly === true); + + setGlobalExpand(popupData.firewallPaneMinimized === false, true); + + // Build dynamic filtering pane only if in use + if ( (computedSections() & sectionFirewallBit) !== 0 ) { + buildAllFirewallRows(); + } + + renderTooltips(); +}; + +/******************************************************************************/ + +dom.on('.dismiss', 'click', ( ) => { + messaging.send('popupPanel', { + what: 'dismissUnprocessedRequest', + tabId: popupData.tabId, + }).then(( ) => { + popupData.hasUnprocessedRequest = false; + dom.cl.remove(dom.root, 'warn'); + }); +}); + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/2889 +// Use tooltip for ARIA purpose. + +const renderTooltips = function(selector) { + for ( const [ key, details ] of tooltipTargetSelectors ) { + if ( selector !== undefined && key !== selector ) { continue; } + const elem = qs$(key); + if ( elem.hasAttribute('title') === false ) { continue; } + const text = i18n$( + details.i18n + + (qs$(details.state) === null ? '1' : '2') + ); + dom.attr(elem, 'aria-label', text); + dom.attr(elem, 'title', text); + } +}; + +const tooltipTargetSelectors = new Map([ + [ + '#switch', + { + state: 'body.off', + i18n: 'popupPowerSwitchInfo', + } + ], + [ + '#no-popups', + { + state: '#no-popups.on', + i18n: 'popupTipNoPopups' + } + ], + [ + '#no-large-media', + { + state: '#no-large-media.on', + i18n: 'popupTipNoLargeMedia' + } + ], + [ + '#no-cosmetic-filtering', + { + state: '#no-cosmetic-filtering.on', + i18n: 'popupTipNoCosmeticFiltering' + } + ], + [ + '#no-remote-fonts', + { + state: '#no-remote-fonts.on', + i18n: 'popupTipNoRemoteFonts' + } + ], + [ + '#no-scripting', + { + state: '#no-scripting.on', + i18n: 'popupTipNoScripting' + } + ], +]); + +/******************************************************************************/ + +// All rendering code which need to be executed only once. + +let renderOnce = function() { + renderOnce = function(){}; + + if ( popupData.fontSize !== popupFontSize ) { + popupFontSize = popupData.fontSize; + if ( popupFontSize !== 'unset' ) { + dom.body.style.setProperty('--font-size', popupFontSize); + vAPI.localStorage.setItem('popupFontSize', popupFontSize); + } else { + dom.body.style.removeProperty('--font-size'); + vAPI.localStorage.removeItem('popupFontSize'); + } + } + + dom.text('#version', popupData.appVersion); + + setSections(computedSections()); + + if ( popupData.uiPopupConfig !== undefined ) { + dom.attr(dom.body, 'data-ui', popupData.uiPopupConfig); + } + + dom.cl.toggle(dom.body, 'no-tooltips', popupData.tooltipsDisabled === true); + if ( popupData.tooltipsDisabled === true ) { + dom.attr('[title]', 'title', null); + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/22 + if ( popupData.advancedUserEnabled !== true ) { + dom.attr('#firewall [title][data-src]', 'title', null); + } + + // This must be done the firewall is populated + if ( popupData.popupPanelHeightMode === 1 ) { + dom.cl.add(dom.body, 'vMin'); + } + + // Prevent non-advanced user opting into advanced user mode from harming + // themselves by disabling by default features generally suitable to + // filter list maintainers and actual advanced users. + if ( popupData.godMode ) { + dom.cl.add(dom.body, 'godMode'); + } +}; + +/******************************************************************************/ + +const renderPopupLazy = (( ) => { + let mustRenderCosmeticFilteringBadge = true; + + // https://github.com/uBlockOrigin/uBlock-issues/issues/756 + // Launch potentially expensive hidden elements-counting scriptlet on + // demand only. + { + const sw = qs$('#no-cosmetic-filtering'); + const badge = qs$(sw, ':scope .fa-icon-badge'); + dom.text(badge, '\u22EF'); + + const render = ( ) => { + if ( mustRenderCosmeticFilteringBadge === false ) { return; } + mustRenderCosmeticFilteringBadge = false; + if ( dom.cl.has(sw, 'hnSwitchBusy') ) { return; } + dom.cl.add(sw, 'hnSwitchBusy'); + messaging.send('popupPanel', { + what: 'getHiddenElementCount', + tabId: popupData.tabId, + }).then(count => { + let text; + if ( (count || 0) === 0 ) { + text = ''; + } else if ( count === -1 ) { + text = '?'; + } else { + text = Math.min(count, 99).toLocaleString(); + } + dom.text(badge, text); + dom.cl.remove(sw, 'hnSwitchBusy'); + }); + }; + + dom.on(sw, 'mouseenter', render, { passive: true }); + } + + return async function() { + const count = await messaging.send('popupPanel', { + what: 'getScriptCount', + tabId: popupData.tabId, + }); + dom.text( + '#no-scripting .fa-icon-badge', + (count || 0) !== 0 ? Math.min(count, 99).toLocaleString() : '' + ); + mustRenderCosmeticFilteringBadge = true; + }; +})(); + +/******************************************************************************/ + +const toggleNetFilteringSwitch = function(ev) { + if ( !popupData || !popupData.pageURL ) { return; } + messaging.send('popupPanel', { + what: 'toggleNetFiltering', + url: popupData.pageURL, + scope: ev.ctrlKey || ev.metaKey ? 'page' : '', + state: dom.cl.toggle(dom.body, 'off') === false, + tabId: popupData.tabId, + }); + renderTooltips('#switch'); + hashFromPopupData(); +}; + +/******************************************************************************/ + +const gotoZap = function() { + messaging.send('popupPanel', { + what: 'launchElementPicker', + tabId: popupData.tabId, + zap: true, + }); + + vAPI.closePopup(); +}; + +/******************************************************************************/ + +const gotoPick = function() { + messaging.send('popupPanel', { + what: 'launchElementPicker', + tabId: popupData.tabId, + }); + + vAPI.closePopup(); +}; + +/******************************************************************************/ + +const gotoReport = function() { + const popupPanel = { + blocked: popupData.pageCounts.blocked.any, + }; + const reportedStates = [ + { name: 'enabled', prop: 'netFilteringSwitch', expected: true }, + { name: 'no-cosmetic-filtering', prop: 'noCosmeticFiltering', expected: false }, + { name: 'no-large-media', prop: 'noLargeMedia', expected: false }, + { name: 'no-popups', prop: 'noPopups', expected: false }, + { name: 'no-remote-fonts', prop: 'noRemoteFonts', expected: false }, + { name: 'no-scripting', prop: 'noScripting', expected: false }, + { name: 'can-element-picker', prop: 'canElementPicker', expected: true }, + ]; + for ( const { name, prop, expected } of reportedStates ) { + if ( popupData[prop] === expected ) { continue; } + popupPanel[name] = !expected; + } + if ( hostnameToSortableTokenMap.size !== 0 ) { + const network = {}; + const hostnames = + Array.from(hostnameToSortableTokenMap.keys()).sort(hostnameCompare); + for ( const hostname of hostnames ) { + const entry = popupData.hostnameDict[hostname]; + const count = entry.counts.blocked.any; + if ( count === 0 ) { continue; } + const domain = entry.domain; + if ( network[domain] === undefined ) { + network[domain] = 0; + } + network[domain] += count; + } + if ( Object.keys(network).length !== 0 ) { + popupPanel.network = network; + } + } + messaging.send('popupPanel', { + what: 'launchReporter', + tabId: popupData.tabId, + pageURL: popupData.rawURL, + popupPanel, + }); + + vAPI.closePopup(); +}; + +/******************************************************************************/ + +const gotoURL = function(ev) { + if ( this.hasAttribute('href') === false ) { return; } + + ev.preventDefault(); + + let url = dom.attr(ev.target, 'href'); + if ( + url === 'logger-ui.html#_' && + typeof popupData.tabId === 'number' + ) { + url += '+' + popupData.tabId; + } + + messaging.send('popupPanel', { + what: 'gotoURL', + details: { + url: url, + select: true, + index: -1, + shiftKey: ev.shiftKey + }, + }); + + vAPI.closePopup(); +}; + +/******************************************************************************/ + +// The popup panel is made of sections. Visibility of sections can +// be toggled on/off. + +const maxNumberOfSections = 6; +const sectionFirewallBit = 0b10000; + +const computedSections = ( ) => + popupData.popupPanelSections & + ~popupData.popupPanelDisabledSections | + popupData.popupPanelLockedSections; + +const sectionBitsFromAttribute = function() { + const attr = document.body.dataset.more; + if ( attr === '' ) { return 0; } + let bits = 0; + for ( const c of attr ) { + bits |= 1 << (c.charCodeAt(0) - 97); + } + return bits; +}; + +const sectionBitsToAttribute = function(bits) { + const attr = []; + for ( let i = 0; i < maxNumberOfSections; i++ ) { + const bit = 1 << i; + if ( (bits & bit) === 0 ) { continue; } + attr.push(String.fromCharCode(97 + i)); + } + return attr.join(''); +}; + +const setSections = function(bits) { + const value = sectionBitsToAttribute(bits); + const min = sectionBitsToAttribute(popupData.popupPanelLockedSections); + const max = sectionBitsToAttribute( + (1 << maxNumberOfSections) - 1 & ~popupData.popupPanelDisabledSections + ); + document.body.dataset.more = value; + dom.cl.toggle('#lessButton', 'disabled', value === min); + dom.cl.toggle('#moreButton', 'disabled', value === max); +}; + +const toggleSections = function(more) { + const offbits = ~popupData.popupPanelDisabledSections; + const onbits = popupData.popupPanelLockedSections; + let currentBits = sectionBitsFromAttribute(); + let newBits = currentBits; + for ( let i = 0; i < maxNumberOfSections; i++ ) { + const bit = 1 << (more ? i : maxNumberOfSections - i - 1); + if ( more ) { + newBits |= bit; + } else { + newBits &= ~bit; + } + newBits = newBits & offbits | onbits; + if ( newBits !== currentBits ) { break; } + } + if ( newBits === currentBits ) { return; } + + setSections(newBits); + + popupData.popupPanelSections = newBits; + messaging.send('popupPanel', { + what: 'userSettings', + name: 'popupPanelSections', + value: newBits, + }); + + // https://github.com/chrisaljoudi/uBlock/issues/996 + // Remember the last state of the firewall pane. This allows to + // configure the popup size early next time it is opened, which means a + // less glitchy popup at open time. + vAPI.localStorage.setItem('popupPanelSections', newBits); + + // Dynamic filtering pane may not have been built yet + if ( (newBits & sectionFirewallBit) !== 0 && dfPaneBuilt === false ) { + buildAllFirewallRows(); + } +}; + +dom.on('#moreButton', 'click', ( ) => { toggleSections(true); }); +dom.on('#lessButton', 'click', ( ) => { toggleSections(false); }); + +/******************************************************************************/ + +const mouseenterCellHandler = function(ev) { + const target = ev.target; + if ( dom.cl.has(target, 'ownRule') ) { return; } + target.appendChild(dfHotspots); +}; + +const mouseleaveCellHandler = function() { + dfHotspots.remove(); +}; + +/******************************************************************************/ + +const setFirewallRule = async function(src, des, type, action, persist) { + // This can happen on pages where uBlock does not work + if ( + typeof popupData.pageHostname !== 'string' || + popupData.pageHostname === '' + ) { + return; + } + + const response = await messaging.send('popupPanel', { + what: 'toggleFirewallRule', + tabId: popupData.tabId, + pageHostname: popupData.pageHostname, + srcHostname: src, + desHostname: des, + requestType: type, + action: action, + persist: persist, + }); + + // Remove action widget if an own rule has been set, this allows to click + // again immediately to remove the rule. + if ( action !== 0 ) { + dfHotspots.remove(); + } + + cachePopupData(response); + updateAllFirewallCells(true, false); + hashFromPopupData(); +}; + +/******************************************************************************/ + +const unsetFirewallRuleHandler = function(ev) { + const cell = ev.target; + const row = cell.closest('[data-des]'); + setFirewallRule( + dom.attr(cell, 'data-src') === '/' ? '*' : popupData.pageHostname, + dom.attr(row, 'data-des'), + dom.attr(row, 'data-type'), + 0, + ev.ctrlKey || ev.metaKey + ); + cell.appendChild(dfHotspots); +}; + +/******************************************************************************/ + +const setFirewallRuleHandler = function(ev) { + const hotspot = ev.target; + const cell = hotspot.closest('[data-src]'); + if ( cell === null ) { return; } + const row = cell.closest('[data-des]'); + let action = 0; + if ( hotspot.id === 'dynaAllow' ) { + action = 2; + } else if ( hotspot.id === 'dynaNoop' ) { + action = 3; + } else { + action = 1; + } + setFirewallRule( + dom.attr(cell, 'data-src') === '/' ? '*' : popupData.pageHostname, + dom.attr(row, 'data-des'), + dom.attr(row, 'data-type'), + action, + ev.ctrlKey || ev.metaKey + ); + dfHotspots.remove(); +}; + +/******************************************************************************/ + +const reloadTab = function(bypassCache = false) { + // Preemptively clear the unprocessed-requests status since we know for sure + // the page is being reloaded in this code path. + if ( popupData.hasUnprocessedRequest === true ) { + messaging.send('popupPanel', { + what: 'dismissUnprocessedRequest', + tabId: popupData.tabId, + }).then(( ) => { + popupData.hasUnprocessedRequest = false; + dom.cl.remove(dom.root, 'warn'); + }); + } + + messaging.send('popupPanel', { + what: 'reloadTab', + tabId: popupData.tabId, + url: popupData.rawURL, + select: vAPI.webextFlavor.soup.has('mobile'), + bypassCache, + }); + + // Polling will take care of refreshing the popup content + // https://github.com/chrisaljoudi/uBlock/issues/748 + // User forces a reload, assume the popup has to be updated regardless + // if there were changes or not. + popupData.contentLastModified = -1; + + // Reset popup state hash to current state. + hashFromPopupData(true); +}; + +dom.on('#refresh', 'click', ev => { + reloadTab(ev.ctrlKey || ev.metaKey || ev.shiftKey); +}); + +// https://github.com/uBlockOrigin/uBlock-issues/issues/672 +dom.on(document, 'keydown', ev => { + if ( ev.isComposing ) { return; } + let bypassCache = false; + switch ( ev.key ) { + case 'F5': + bypassCache = ev.ctrlKey || ev.metaKey || ev.shiftKey; + break; + case 'r': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + break; + case 'R': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + bypassCache = true; + break; + default: + return; + } + reloadTab(bypassCache); + ev.preventDefault(); + ev.stopPropagation(); +}, { capture: true }); + +/******************************************************************************/ + +const expandExceptions = new Set(); + +vAPI.localStorage.getItemAsync('popupExpandExceptions').then(exceptions => { + try { + if ( Array.isArray(exceptions) === false ) { return; } + for ( const exception of exceptions ) { + expandExceptions.add(exception); + } + } + catch(ex) { + } +}); + +const saveExpandExceptions = function() { + vAPI.localStorage.setItem( + 'popupExpandExceptions', + Array.from(expandExceptions) + ); +}; + +const setGlobalExpand = function(state, internal = false) { + dom.cl.remove('.expandException', 'expandException'); + if ( state ) { + dom.cl.add('#firewall', 'expanded'); + } else { + dom.cl.remove('#firewall', 'expanded'); + } + if ( internal ) { return; } + popupData.firewallPaneMinimized = !state; + expandExceptions.clear(); + saveExpandExceptions(); + messaging.send('popupPanel', { + what: 'userSettings', + name: 'firewallPaneMinimized', + value: popupData.firewallPaneMinimized, + }); +}; + +const setSpecificExpand = function(domain, state, internal = false) { + const elems = qsa$(`[data-des="${domain}"],[data-des$=".${domain}"]`); + if ( state ) { + dom.cl.add(elems, 'expandException'); + } else { + dom.cl.remove(elems, 'expandException'); + } + if ( internal ) { return; } + if ( state ) { + expandExceptions.add(domain); + } else { + expandExceptions.delete(domain); + } + saveExpandExceptions(); +}; + +dom.on('[data-i18n="popupAnyRulePrompt"]', 'click', ev => { + // Special display mode: in its own tab/window, with no vertical restraint. + // Useful to take snapshots of the whole list of domains -- example: + // https://github.com/gorhill/uBlock/issues/736#issuecomment-178879944 + if ( ev.shiftKey && ev.ctrlKey ) { + messaging.send('popupPanel', { + what: 'gotoURL', + details: { + url: `popup-fenix.html?tabId=${popupData.tabId}&intab=1`, + select: true, + index: -1, + }, + }); + vAPI.closePopup(); + return; + } + + setGlobalExpand(dom.cl.has('#firewall', 'expanded') === false); +}); + +dom.on('#firewall', 'click', '.isDomain[data-type="*"] > span:first-of-type', ev => { + const div = ev.target.closest('[data-des]'); + if ( div === null ) { return; } + setSpecificExpand( + dom.attr(div, 'data-des'), + dom.cl.has(div, 'expandException') === false + ); +}); + +/******************************************************************************/ + +const saveFirewallRules = function() { + messaging.send('popupPanel', { + what: 'saveFirewallRules', + srcHostname: popupData.pageHostname, + desHostnames: popupData.hostnameDict, + }); + dom.cl.remove(dom.body, 'needSave'); +}; + +/******************************************************************************/ + +const revertFirewallRules = async function() { + dom.cl.remove(dom.body, 'needSave'); + const response = await messaging.send('popupPanel', { + what: 'revertFirewallRules', + srcHostname: popupData.pageHostname, + desHostnames: popupData.hostnameDict, + tabId: popupData.tabId, + }); + cachePopupData(response); + updateAllFirewallCells(true, false); + updateHnSwitches(); + hashFromPopupData(); +}; + +/******************************************************************************/ + +const toggleHostnameSwitch = async function(ev) { + const target = ev.currentTarget; + const switchName = dom.attr(target, 'id'); + if ( !switchName ) { return; } + // For touch displays, process click only if the switch is not "busy". + if ( + vAPI.webextFlavor.soup.has('mobile') && + dom.cl.has(target, 'hnSwitchBusy') + ) { + return; + } + dom.cl.toggle(target, 'on'); + renderTooltips(`#${switchName}`); + + const response = await messaging.send('popupPanel', { + what: 'toggleHostnameSwitch', + name: switchName, + hostname: popupData.pageHostname, + state: dom.cl.has(target, 'on'), + tabId: popupData.tabId, + persist: ev.ctrlKey || ev.metaKey, + }); + + cachePopupData(response); + hashFromPopupData(); + + dom.cl.toggle(dom.body, 'needSave', popupData.matrixIsDirty === true); +}; + +/******************************************************************************* + + Double tap ctrl key: toggle god mode + +*/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/2145 +// Ignore events from auto-repeating keys + +{ + let eventCount = 0; + let eventTime = 0; + + dom.on(document, 'keydown', ev => { + if ( ev.key !== 'Control' ) { + eventCount = 0; + return; + } + if ( ev.repeat ) { return; } + const now = Date.now(); + if ( (now - eventTime) >= 500 ) { + eventCount = 0; + } + eventCount += 1; + eventTime = now; + if ( eventCount < 2 ) { return; } + eventCount = 0; + dom.cl.toggle(dom.body, 'godMode'); + }); +} + + +/******************************************************************************/ + +// Poll for changes. +// +// I couldn't find a better way to be notified of changes which can affect +// popup content, as the messaging API doesn't support firing events accurately +// from the main extension process to a specific auxiliary extension process: +// +// - broadcasting() is not an option given there could be a lot of tabs opened, +// and maybe even many frames within these tabs, i.e. unacceptable overhead +// regardless of whether the popup is opened or not. +// +// - Modifying the messaging API is not an option, as this would require +// revisiting all platform-specific code to support targeted broadcasting, +// which who knows could be not so trivial for some platforms. +// +// A well done polling is a better anyways IMO, I prefer that data is pulled +// on demand rather than forcing the main process to assume a client may need +// it and thus having to push it all the time unconditionally. + +const pollForContentChange = (( ) => { + const pollCallback = async function() { + const response = await messaging.send('popupPanel', { + what: 'hasPopupContentChanged', + tabId: popupData.tabId, + contentLastModified: popupData.contentLastModified, + }); + if ( response ) { + await getPopupData(popupData.tabId); + return; + } + poll(); + }; + + const pollTimer = vAPI.defer.create(pollCallback); + + const poll = function() { + pollTimer.on(1500); + }; + + return poll; +})(); + +/******************************************************************************/ + +const getPopupData = async function(tabId, first = false) { + const response = await messaging.send('popupPanel', { + what: 'getPopupData', + tabId, + }); + + cachePopupData(response); + renderOnce(); + renderPopup(); + renderPopupLazy(); // low priority rendering + hashFromPopupData(first); + pollForContentChange(); +}; + +/******************************************************************************/ + +// Popup DOM is assumed to be loaded at this point -- because this script +// is loaded after everything else. + +{ + // Extract the tab id of the page for this popup. If there's no tab id + // specified in the query string, it will default to current tab. + const selfURL = new URL(self.location.href); + const tabId = parseInt(selfURL.searchParams.get('tabId'), 10) || null; + + const nextFrames = async n => { + for ( let i = 0; i < n; i++ ) { + await new Promise(resolve => { + self.requestAnimationFrame(( ) => { resolve(); }); + }); + } + }; + + // The purpose of the following code is to reset to a vertical layout + // should the viewport not be enough wide to accommodate the horizontal + // layout. + // To avoid querying a spurious viewport width -- it happens sometimes, + // somehow -- we delay layout-changing operations to the next paint + // frames. + // Force a layout recalculation by querying the body width. To be + // honest, I have no clue if this makes a difference in the end. + // https://gist.github.com/paulirish/5d52fb081b3570c81e3a + // Use a tolerance proportional to the sum of the width of the panes + // when testing against viewport width. + const checkViewport = async function() { + if ( + dom.cl.has(dom.root, 'mobile') || + selfURL.searchParams.get('portrait') + ) { + dom.cl.add(dom.root, 'portrait'); + dom.cl.remove(dom.root, 'desktop'); + } else if ( dom.cl.has(dom.root, 'desktop') ) { + await nextFrames(8); + const main = qs$('#main'); + const firewall = qs$('#firewall'); + const minWidth = (main.offsetWidth + firewall.offsetWidth) / 1.1; + if ( + selfURL.searchParams.get('portrait') || + window.innerWidth < minWidth + ) { + dom.cl.add(dom.root, 'portrait'); + } + } + if ( dom.cl.has(dom.root, 'portrait') ) { + const panes = qs$('#panes'); + const sticky = qs$('#sticky'); + const stickyParent = sticky.parentElement; + if ( stickyParent !== panes ) { + panes.prepend(sticky); + } + } + if ( selfURL.searchParams.get('intab') !== null ) { + dom.cl.add(dom.root, 'intab'); + } + await nextFrames(1); + dom.cl.remove(dom.body, 'loading'); + }; + + getPopupData(tabId, true).then(( ) => { + if ( document.readyState !== 'complete' ) { + dom.on(self, 'load', ( ) => { checkViewport(); }, { once: true }); + } else { + checkViewport(); + } + }); +} + +/******************************************************************************/ + +dom.on('#switch', 'click', toggleNetFilteringSwitch); +dom.on('#gotoZap', 'click', gotoZap); +dom.on('#gotoPick', 'click', gotoPick); +dom.on('#gotoReport', 'click', gotoReport); +dom.on('.hnSwitch', 'click', ev => { toggleHostnameSwitch(ev); }); +dom.on('#saveRules', 'click', saveFirewallRules); +dom.on('#revertRules', 'click', ( ) => { revertFirewallRules(); }); +dom.on('a[href]', 'click', gotoURL); + +/******************************************************************************/ diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js new file mode 100644 index 0000000..2f58066 --- /dev/null +++ b/src/js/redirect-engine.js @@ -0,0 +1,494 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import redirectableResources from './redirect-resources.js'; + +import { + LineIterator, + orphanizeString, +} from './text-utils.js'; + +/******************************************************************************/ + +const extToMimeMap = new Map([ + [ 'css', 'text/css' ], + [ 'fn', 'fn/javascript' ], // invented mime type for internal use + [ 'gif', 'image/gif' ], + [ 'html', 'text/html' ], + [ 'js', 'text/javascript' ], + [ 'json', 'application/json' ], + [ 'mp3', 'audio/mp3' ], + [ 'mp4', 'video/mp4' ], + [ 'png', 'image/png' ], + [ 'txt', 'text/plain' ], + [ 'xml', 'text/xml' ], +]); + +const typeToMimeMap = new Map([ + [ 'main_frame', 'text/html' ], + [ 'other', 'text/plain' ], + [ 'script', 'text/javascript' ], + [ 'stylesheet', 'text/css' ], + [ 'sub_frame', 'text/html' ], + [ 'xmlhttprequest', 'text/plain' ], +]); + +const validMimes = new Set(extToMimeMap.values()); + +const mimeFromName = name => { + const match = /\.([^.]+)$/.exec(name); + if ( match === null ) { return ''; } + return extToMimeMap.get(match[1]); +}; + +const removeTopCommentBlock = text => { + return text.replace(/^\/\*[\S\s]+?\n\*\/\s*/, ''); +}; + +// vAPI.warSecret is optional, it could be absent in some environments, +// i.e. nodejs for example. Probably the best approach is to have the +// "web_accessible_resources secret" added outside by the client of this +// module, but for now I just want to remove an obstacle to modularization. +const warSecret = typeof vAPI === 'object' && vAPI !== null + ? vAPI.warSecret.short + : ( ) => ''; + +const RESOURCES_SELFIE_VERSION = 7; +const RESOURCES_SELFIE_NAME = 'compiled/redirectEngine/resources'; + +/******************************************************************************/ +/******************************************************************************/ + +class RedirectEntry { + constructor() { + this.mime = ''; + this.data = ''; + this.warURL = undefined; + this.params = undefined; + this.requiresTrust = false; + this.world = 'MAIN'; + this.dependencies = []; + } + + // Prevent redirection to web accessible resources when the request is + // of type 'xmlhttprequest', because XMLHttpRequest.responseURL would + // cause leakage of extension id. See: + // - https://stackoverflow.com/a/8056313 + // - https://bugzilla.mozilla.org/show_bug.cgi?id=998076 + // https://www.reddit.com/r/uBlockOrigin/comments/cpxm1v/ + // User-supplied resources may already be base64 encoded. + + toURL(fctxt, asDataURI = false) { + if ( + this.warURL !== undefined && + asDataURI !== true && + fctxt instanceof Object && + fctxt.type !== 'xmlhttprequest' + ) { + const params = []; + const secret = warSecret(); + if ( secret !== '' ) { params.push(`secret=${secret}`); } + if ( this.params !== undefined ) { + for ( const name of this.params ) { + const value = fctxt[name]; + if ( value === undefined ) { continue; } + params.push(`${name}=${encodeURIComponent(value)}`); + } + } + let url = `${this.warURL}`; + if ( params.length !== 0 ) { + url += `?${params.join('&')}`; + } + return url; + } + if ( this.data === undefined ) { return; } + // https://github.com/uBlockOrigin/uBlock-issues/issues/701 + if ( this.data === '' ) { + const mime = typeToMimeMap.get(fctxt.type); + if ( mime === '' ) { return; } + return `data:${mime},`; + } + if ( this.data.startsWith('data:') === false ) { + if ( this.mime.indexOf(';') === -1 ) { + this.data = `data:${this.mime};base64,${btoa(this.data)}`; + } else { + this.data = `data:${this.mime},${this.data}`; + } + } + return this.data; + } + + toContent() { + if ( this.data.startsWith('data:') ) { + const pos = this.data.indexOf(','); + const base64 = this.data.endsWith(';base64', pos); + this.data = this.data.slice(pos + 1); + if ( base64 ) { + this.data = atob(this.data); + } + } + return this.data; + } + + static fromDetails(details) { + const r = new RedirectEntry(); + Object.assign(r, details); + return r; + } +} + +/******************************************************************************/ +/******************************************************************************/ + +class RedirectEngine { + constructor() { + this.aliases = new Map(); + this.resources = new Map(); + this.reset(); + this.modifyTime = Date.now(); + } + + reset() { + } + + freeze() { + } + + tokenToURL( + fctxt, + token, + asDataURI = false + ) { + const entry = this.resources.get(this.aliases.get(token) || token); + if ( entry === undefined ) { return; } + return entry.toURL(fctxt, asDataURI); + } + + tokenToDNR(token) { + const entry = this.resources.get(this.aliases.get(token) || token); + if ( entry === undefined ) { return; } + if ( entry.warURL === undefined ) { return; } + return entry.warURL; + } + + hasToken(token) { + if ( token === 'none' ) { return true; } + const asDataURI = token.charCodeAt(0) === 0x25 /* '%' */; + if ( asDataURI ) { + token = token.slice(1); + } + return this.resources.get(this.aliases.get(token) || token) !== undefined; + } + + tokenRequiresTrust(token) { + const entry = this.resources.get(this.aliases.get(token) || token); + return entry && entry.requiresTrust === true || false; + } + + async toSelfie() { + } + + async fromSelfie() { + return true; + } + + contentFromName(name, mime = '') { + const entry = this.resources.get(this.aliases.get(name) || name); + if ( entry === undefined ) { return; } + if ( entry.mime.startsWith(mime) === false ) { return; } + return { + js: entry.toContent(), + world: entry.world, + dependencies: entry.dependencies.slice(), + }; + } + + // https://github.com/uBlockOrigin/uAssets/commit/deefe8755511 + // Consider 'none' a reserved keyword, to be used to disable redirection. + // https://github.com/uBlockOrigin/uBlock-issues/issues/1419 + // Append newlines to raw text to ensure processing of trailing resource. + + resourcesFromString(text) { + const lineIter = new LineIterator( + removeTopCommentBlock(text) + '\n\n' + ); + const reNonEmptyLine = /\S/; + let fields, encoded, details; + + while ( lineIter.eot() === false ) { + const line = lineIter.next(); + if ( line.startsWith('#') ) { continue; } + if ( line.startsWith('// ') ) { continue; } + + if ( fields === undefined ) { + if ( line === '' ) { continue; } + // Modern parser + if ( line.startsWith('/// ') ) { + const name = line.slice(4).trim(); + fields = [ name, mimeFromName(name) ]; + continue; + } + // Legacy parser + const head = line.trim().split(/\s+/); + if ( head.length !== 2 ) { continue; } + if ( head[0] === 'none' ) { continue; } + let pos = head[1].indexOf(';'); + if ( pos === -1 ) { pos = head[1].length; } + if ( validMimes.has(head[1].slice(0, pos)) === false ) { + continue; + } + encoded = head[1].indexOf(';') !== -1; + fields = head; + continue; + } + + if ( line.startsWith('/// ') ) { + if ( details === undefined ) { + details = []; + } + const [ prop, value ] = line.slice(4).trim().split(/\s+/); + if ( value !== undefined ) { + details.push({ prop, value }); + } + continue; + } + + if ( reNonEmptyLine.test(line) ) { + fields.push(encoded ? line.trim() : line); + continue; + } + + // No more data, add the resource. + const name = this.aliases.get(fields[0]) || fields[0]; + const mime = fields[1]; + const data = orphanizeString( + fields.slice(2).join(encoded ? '' : '\n') + ); + this.resources.set(name, RedirectEntry.fromDetails({ mime, data })); + if ( Array.isArray(details) ) { + const resource = this.resources.get(name); + for ( const { prop, value } of details ) { + switch ( prop ) { + case 'alias': + this.aliases.set(value, name); + break; + case 'world': + if ( /^isolated$/i.test(value) === false ) { break; } + resource.world = 'ISOLATED'; + break; + case 'dependency': + if ( this.resources.has(value) === false ) { break; } + resource.dependencies.push(value); + break; + default: + break; + } + } + } + + fields = undefined; + details = undefined; + } + + this.modifyTime = Date.now(); + } + + loadBuiltinResources(fetcher) { + this.resources = new Map(); + this.aliases = new Map(); + + const fetches = [ + import('/assets/resources/scriptlets.js').then(module => { + for ( const scriptlet of module.builtinScriptlets ) { + const details = {}; + details.mime = mimeFromName(scriptlet.name); + details.data = scriptlet.fn.toString(); + for ( const [ k, v ] of Object.entries(scriptlet) ) { + if ( k === 'fn' ) { continue; } + details[k] = v; + } + const entry = RedirectEntry.fromDetails(details); + this.resources.set(details.name, entry); + if ( Array.isArray(details.aliases) === false ) { continue; } + for ( const alias of details.aliases ) { + this.aliases.set(alias, details.name); + } + } + this.modifyTime = Date.now(); + }), + ]; + + const store = (name, data = undefined) => { + const details = redirectableResources.get(name); + const entry = RedirectEntry.fromDetails({ + mime: mimeFromName(name), + data, + warURL: `/web_accessible_resources/${name}`, + params: details.params, + }); + this.resources.set(name, entry); + if ( details.alias === undefined ) { return; } + if ( Array.isArray(details.alias) ) { + for ( const alias of details.alias ) { + this.aliases.set(alias, name); + } + } else { + this.aliases.set(details.alias, name); + } + }; + + const processBlob = (name, blob) => { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = ( ) => { + store(name, reader.result); + resolve(); + }; + reader.onabort = reader.onerror = ( ) => { + resolve(); + }; + reader.readAsDataURL(blob); + }); + }; + + const processText = (name, text) => { + store(name, removeTopCommentBlock(text)); + }; + + const process = result => { + const match = /^\/web_accessible_resources\/([^?]+)/.exec(result.url); + if ( match === null ) { return; } + const name = match[1]; + return result.content instanceof Blob + ? processBlob(name, result.content) + : processText(name, result.content); + }; + + for ( const [ name, details ] of redirectableResources ) { + if ( typeof details.data !== 'string' ) { + store(name); + continue; + } + fetches.push( + fetcher(`/web_accessible_resources/${name}`, { + responseType: details.data + }).then( + result => process(result) + ) + ); + } + + return Promise.all(fetches); + } + + getResourceDetails() { + const out = new Map([ + [ 'none', { canInject: false, canRedirect: true, aliasOf: '' } ], + ]); + for ( const [ name, entry ] of this.resources ) { + out.set(name, { + canInject: typeof entry.data === 'string', + canRedirect: entry.warURL !== undefined, + aliasOf: '', + extensionPath: entry.warURL, + }); + } + for ( const [ alias, name ] of this.aliases ) { + const original = out.get(name); + if ( original === undefined ) { continue; } + const aliased = Object.assign({}, original); + aliased.aliasOf = name; + out.set(alias, aliased); + } + return Array.from(out).sort((a, b) => { + return a[0].localeCompare(b[0]); + }); + } + + 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) { + storage.put( + RESOURCES_SELFIE_NAME, + JSON.stringify({ + version: RESOURCES_SELFIE_VERSION, + aliases: Array.from(this.aliases), + resources: Array.from(this.resources), + }) + ); + } + + async resourcesFromSelfie(storage) { + const result = await storage.get(RESOURCES_SELFIE_NAME); + let selfie; + try { + selfie = JSON.parse(result.content); + } catch(ex) { + } + if ( + selfie instanceof Object === false || + selfie.version !== RESOURCES_SELFIE_VERSION || + Array.isArray(selfie.resources) === false + ) { + return false; + } + this.aliases = new Map(selfie.aliases); + this.resources = new Map(); + for ( const [ token, entry ] of selfie.resources ) { + this.resources.set(token, RedirectEntry.fromDetails(entry)); + } + return true; + } + + invalidateResourcesSelfie(storage) { + storage.remove(RESOURCES_SELFIE_NAME); + } +} + +/******************************************************************************/ + +const redirectEngine = new RedirectEngine(); + +export { redirectEngine }; + +/******************************************************************************/ diff --git a/src/js/redirect-resources.js b/src/js/redirect-resources.js new file mode 100644 index 0000000..b8577e3 --- /dev/null +++ b/src/js/redirect-resources.js @@ -0,0 +1,182 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +// The resources referenced below are found in ./web_accessible_resources/ +// +// The content of the resources which declare a `data` property will be loaded +// in memory, and converted to a suitable internal format depending on the +// type of the loaded data. The `data` property allows for manual injection +// through `+js(...)`, or for redirection to a data: URI when a redirection +// to a web accessible resource is not desirable. + +export default new Map([ + [ '1x1.gif', { + alias: '1x1-transparent.gif', + data: 'blob', + } ], + [ '2x2.png', { + alias: '2x2-transparent.png', + data: 'blob', + } ], + [ '3x2.png', { + alias: '3x2-transparent.png', + data: 'blob', + } ], + [ '32x32.png', { + alias: '32x32-transparent.png', + data: 'blob', + } ], + [ 'amazon_ads.js', { + alias: 'amazon-adsystem.com/aax2/amzn_ads.js', + data: 'text', + } ], + [ 'amazon_apstag.js', { + } ], + [ 'ampproject_v0.js', { + alias: 'ampproject.org/v0.js', + } ], + [ 'chartbeat.js', { + alias: 'static.chartbeat.com/chartbeat.js', + } ], + [ 'click2load.html', { + params: [ 'aliasURL', 'url' ], + } ], + [ 'doubleclick_instream_ad_status.js', { + alias: 'doubleclick.net/instream/ad_status.js', + data: 'text', + } ], + [ 'empty', { + data: 'text', // Important! + } ], + [ 'fingerprint2.js', { + data: 'text', + } ], + [ 'fingerprint3.js', { + data: 'text', + } ], + [ 'google-analytics_analytics.js', { + alias: [ + 'google-analytics.com/analytics.js', + 'googletagmanager_gtm.js', + 'googletagmanager.com/gtm.js' + ], + data: 'text', + } ], + [ 'google-analytics_cx_api.js', { + alias: 'google-analytics.com/cx/api.js', + } ], + [ 'google-analytics_ga.js', { + alias: 'google-analytics.com/ga.js', + data: 'text', + } ], + [ 'google-analytics_inpage_linkid.js', { + alias: 'google-analytics.com/inpage_linkid.js', + } ], + [ 'google-ima.js', { + alias: 'google-ima3', /* adguard compatibility */ + } ], + [ 'googlesyndication_adsbygoogle.js', { + alias: [ + 'googlesyndication.com/adsbygoogle.js', + 'googlesyndication-adsbygoogle', /* adguard compatibility */ + ], + data: 'text', + } ], + [ 'googletagservices_gpt.js', { + alias: [ + 'googletagservices.com/gpt.js', + 'googletagservices-gpt', /* adguard compatibility */ + ], + data: 'text', + } ], + [ 'hd-main.js', { + } ], + [ 'nobab.js', { + alias: [ 'bab-defuser.js', 'prevent-bab.js' ], + data: 'text', + } ], + [ 'nobab2.js', { + data: 'text', + } ], + [ 'noeval.js', { + data: 'text', + } ], + [ 'noeval-silent.js', { + alias: 'silent-noeval.js', + data: 'text', + } ], + [ 'nofab.js', { + alias: 'fuckadblock.js-3.2.0', + data: 'text', + } ], + [ 'noop-0.1s.mp3', { + alias: [ 'noopmp3-0.1s', 'abp-resource:blank-mp3' ], + data: 'blob', + } ], + [ 'noop-0.5s.mp3', { + } ], + [ 'noop-1s.mp4', { + alias: [ 'noopmp4-1s', 'abp-resource:blank-mp4' ], + data: 'blob', + } ], + [ 'noop.css', { + data: 'text', + } ], + [ 'noop.html', { + alias: 'noopframe', + } ], + [ 'noop.js', { + alias: [ 'noopjs', 'abp-resource:blank-js' ], + data: 'text', + } ], + [ 'noop.json', { + alias: [ 'noopjson' ], + data: 'text', + } ], + [ 'noop.txt', { + alias: 'nooptext', + data: 'text', + } ], + [ 'noop-vmap1.0.xml', { + alias: 'noopvmap-1.0', + data: 'text', + } ], + [ 'outbrain-widget.js', { + alias: 'widgets.outbrain.com/outbrain.js', + } ], + [ 'popads.js', { + alias: [ 'popads.net.js', 'prevent-popads-net.js' ], + data: 'text', + } ], + [ 'popads-dummy.js', { + data: 'text', + } ], + [ 'prebid-ads.js', { + data: 'text', + } ], + [ 'scorecardresearch_beacon.js', { + alias: 'scorecardresearch.com/beacon.js', + } ], +]); diff --git a/src/js/reverselookup-worker.js b/src/js/reverselookup-worker.js new file mode 100644 index 0000000..37b8b65 --- /dev/null +++ b/src/js/reverselookup-worker.js @@ -0,0 +1,287 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +let listEntries = Object.create(null); + +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/2092 +// Order of ids matters + +const extractBlocks = function(content, ...ids) { + const out = []; + for ( const id of ids ) { + const pattern = `#block-start-${id}\n`; + let beg = content.indexOf(pattern); + if ( beg === -1 ) { continue; } + beg += pattern.length; + const end = content.indexOf(`#block-end-${id}`, beg); + out.push(content.slice(beg, end)); + } + return out.join('\n'); +}; + +/******************************************************************************/ + +// https://github.com/MajkiIT/polish-ads-filter/issues/14768#issuecomment-536006312 +// Avoid reporting badfilter-ed filters. + +const fromNetFilter = function(details) { + const lists = []; + const compiledFilter = details.compiledFilter; + + for ( const assetKey in listEntries ) { + const entry = listEntries[assetKey]; + if ( entry === undefined ) { continue; } + if ( entry.networkContent === undefined ) { + entry.networkContent = extractBlocks(entry.content, 'NETWORK_FILTERS:GOOD'); + } + const content = entry.networkContent; + let pos = 0; + for (;;) { + pos = content.indexOf(compiledFilter, pos); + if ( pos === -1 ) { break; } + // We need an exact match. + // https://github.com/gorhill/uBlock/issues/1392 + // https://github.com/gorhill/uBlock/issues/835 + const notFound = pos !== 0 && content.charCodeAt(pos - 1) !== 0x0A; + pos += compiledFilter.length; + if ( + notFound || + pos !== content.length && content.charCodeAt(pos) !== 0x0A + ) { + continue; + } + lists.push({ + assetKey: assetKey, + title: entry.title, + supportURL: entry.supportURL + }); + break; + } + } + + const response = {}; + response[details.rawFilter] = lists; + + self.postMessage({ id: details.id, response }); +}; + +/******************************************************************************/ + +// Looking up filter lists from a cosmetic filter is a bit more complicated +// than with network filters: +// +// The filter is its raw representation, not its compiled version. This is +// because the cosmetic filtering engine can't translate a live cosmetic +// filter into its compiled version. Reason is I do not want to burden +// cosmetic filtering with the resource overhead of being able to recompile +// live cosmetic filters. I want the cosmetic filtering code to be left +// completely unaffected by reverse lookup requirements. +// +// Mainly, given a CSS selector and a hostname as context, we will derive +// various versions of compiled filters and see if there are matches. This +// way the whole CPU cost is incurred by the reverse lookup code -- in a +// worker thread, and the cosmetic filtering engine incurs no cost at all. +// +// For this though, the reverse lookup code here needs some knowledge of +// the inners of the cosmetic filtering engine. +// FilterContainer.fromCompiledContent() is our reference code to create +// the various compiled versions. + +const fromExtendedFilter = function(details) { + const match = /^#@?#\^?/.exec(details.rawFilter); + const prefix = match[0]; + const exception = prefix.charAt(1) === '@'; + const selector = details.rawFilter.slice(prefix.length); + const isHtmlFilter = prefix.endsWith('^'); + const hostname = details.hostname; + + // The longer the needle, the lower the number of false positives. + // https://github.com/uBlockOrigin/uBlock-issues/issues/1139 + // Mind that there is no guarantee a selector has `\w` characters. + const needle = selector.match(/\w+|\*/g).reduce(function(a, b) { + return a.length > b.length ? a : b; + }); + + const regexFromLabels = (prefix, hn, suffix) => + new RegExp( + prefix + + hn.split('.').reduce((acc, item) => `(${acc}\\.)?${item}`) + + suffix + ); + + // https://github.com/uBlockOrigin/uBlock-issues/issues/803 + // Support looking up selectors of the form `*##...` + const reHostname = regexFromLabels('^', hostname, '$'); + let reEntity; + { + const domain = details.domain; + const pos = domain.indexOf('.'); + if ( pos !== -1 ) { + reEntity = regexFromLabels( + '^(', + hostname.slice(0, pos + hostname.length - domain.length), + '\\.)?\\*$' + ); + } + } + + const hostnameMatches = hn => { + if ( hn === '' ) { return true; } + if ( hn.charCodeAt(0) === 0x2F /* / */ ) { + return (new RegExp(hn.slice(1,-1))).test(hostname); + } + if ( reHostname.test(hn) ) { return true; } + if ( reEntity === undefined ) { return false; } + if ( reEntity.test(hn) ) { return true; } + return false; + }; + + const response = Object.create(null); + + for ( const assetKey in listEntries ) { + const entry = listEntries[assetKey]; + if ( entry === undefined ) { continue; } + if ( entry.extendedContent === undefined ) { + entry.extendedContent = extractBlocks( + entry.content, + 'COSMETIC_FILTERS:SPECIFIC', + 'COSMETIC_FILTERS:GENERIC', + 'SCRIPTLET_FILTERS', + 'HTML_FILTERS', + 'HTTPHEADER_FILTERS' + ); + } + const content = entry.extendedContent; + let found; + let pos = 0; + while ( (pos = content.indexOf(needle, pos)) !== -1 ) { + let beg = content.lastIndexOf('\n', pos); + if ( beg === -1 ) { beg = 0; } + let end = content.indexOf('\n', pos); + if ( end === -1 ) { end = content.length; } + pos = end; + const fargs = JSON.parse(content.slice(beg, end)); + const filterType = fargs[0]; + + // https://github.com/gorhill/uBlock/issues/2763 + if ( filterType === 0 && details.ignoreGeneric ) { continue; } + + // Do not confuse cosmetic filters with HTML ones. + if ( (filterType === 64) !== isHtmlFilter ) { continue; } + + switch ( filterType ) { + // Lowly generic cosmetic filters + case 0: + if ( exception ) { break; } + if ( fargs[2] !== selector ) { break; } + found = prefix + selector; + break; + // Highly generic cosmetic filters + case 4: // simple highly generic + case 5: // complex highly generic + if ( exception ) { break; } + if ( fargs[1] !== selector ) { break; } + found = prefix + selector; + break; + // Specific cosmetic filtering + // Generic exception + case 8: + // HTML filtering + // Response header filtering + case 64: { + if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; } + const isProcedural = (fargs[2] & 0b010) !== 0; + if ( + isProcedural === false && fargs[3] !== selector || + isProcedural && JSON.parse(fargs[3]).raw !== selector + ) { + break; + } + if ( hostnameMatches(fargs[1]) === false ) { break; } + // https://www.reddit.com/r/uBlockOrigin/comments/d6vxzj/ + // Ignore match if specific cosmetic filters are disabled + if ( + filterType === 8 && + exception === false && + details.ignoreSpecific + ) { + break; + } + found = fargs[1] + prefix + selector; + break; + } + // Scriptlet injection + case 32: + if ( exception !== ((fargs[2] & 0b001) !== 0) ) { break; } + if ( fargs[3] !== details.compiled ) { break; } + if ( hostnameMatches(fargs[1]) ) { + found = fargs[1] + prefix + selector; + } + break; + } + if ( found !== undefined ) { + if ( response[found] === undefined ) { + response[found] = []; + } + response[found].push({ + assetKey: assetKey, + title: entry.title, + supportURL: entry.supportURL + }); + break; + } + } + } + + self.postMessage({ id: details.id, response }); +}; + +/******************************************************************************/ + +self.onmessage = function(e) { + const msg = e.data; + + switch ( msg.what ) { + case 'resetLists': + listEntries = Object.create(null); + break; + + case 'setList': + listEntries[msg.details.assetKey] = msg.details; + break; + + case 'fromNetFilter': + fromNetFilter(msg); + break; + + case 'fromExtendedFilter': + fromExtendedFilter(msg); + break; + } +}; + +/******************************************************************************/ diff --git a/src/js/reverselookup.js b/src/js/reverselookup.js new file mode 100644 index 0000000..c21ca4b --- /dev/null +++ b/src/js/reverselookup.js @@ -0,0 +1,223 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import staticNetFilteringEngine from './static-net-filtering.js'; +import µb from './background.js'; +import { CompiledListWriter } from './static-filtering-io.js'; +import { i18n$ } from './i18n.js'; +import * as sfp from './static-filtering-parser.js'; + +import { + domainFromHostname, + hostnameFromURI, +} from './uri-utils.js'; + +/******************************************************************************/ + +const pendingResponses = new Map(); + +let worker = null; +let needLists = true; +let messageId = 1; + +const onWorkerMessage = function(e) { + const msg = e.data; + const resolver = pendingResponses.get(msg.id); + pendingResponses.delete(msg.id); + resolver(msg.response); +}; + +const stopWorker = function() { + workerTTLTimer.off(); + if ( worker === null ) { return; } + worker.terminate(); + worker = null; + needLists = true; + for ( const resolver of pendingResponses.values() ) { + resolver(); + } + pendingResponses.clear(); +}; + +const workerTTLTimer = vAPI.defer.create(stopWorker); +const workerTTL = { min: 5 }; + +const initWorker = function() { + if ( worker === null ) { + worker = new Worker('js/reverselookup-worker.js'); + worker.onmessage = onWorkerMessage; + } + + // The worker will be shutdown after n minutes without being used. + workerTTLTimer.offon(workerTTL); + + if ( needLists === false ) { + return Promise.resolve(); + } + needLists = false; + + const entries = new Map(); + + const onListLoaded = function(details) { + const entry = entries.get(details.assetKey); + + // https://github.com/gorhill/uBlock/issues/536 + // Use assetKey when there is no filter list title. + + worker.postMessage({ + what: 'setList', + details: { + assetKey: details.assetKey, + title: entry.title || details.assetKey, + supportURL: entry.supportURL, + content: details.content + } + }); + }; + + for ( const listKey in µb.availableFilterLists ) { + if ( µb.availableFilterLists.hasOwnProperty(listKey) === false ) { + continue; + } + const entry = µb.availableFilterLists[listKey]; + if ( entry.off === true ) { continue; } + entries.set(listKey, { + title: listKey !== µb.userFiltersPath ? + entry.title : + i18n$('1pPageName'), + supportURL: entry.supportURL || '' + }); + } + if ( entries.size === 0 ) { + return Promise.resolve(); + } + + const promises = []; + for ( const listKey of entries.keys() ) { + promises.push( + µb.getCompiledFilterList(listKey).then(details => { + onListLoaded(details); + }) + ); + } + return Promise.all(promises); +}; + +const fromNetFilter = async function(rawFilter) { + if ( typeof rawFilter !== 'string' || rawFilter === '' ) { return; } + + const writer = new CompiledListWriter(); + const parser = new sfp.AstFilterParser({ + trustedSource: true, + maxTokenLength: staticNetFilteringEngine.MAX_TOKEN_LENGTH, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); + parser.parse(rawFilter); + + const compiler = staticNetFilteringEngine.createCompiler(); + if ( compiler.compile(parser, writer) === false ) { return; } + + await initWorker(); + + const id = messageId++; + worker.postMessage({ + what: 'fromNetFilter', + id, + compiledFilter: writer.last(), + rawFilter, + }); + + return new Promise(resolve => { + pendingResponses.set(id, resolve); + }); +}; + +const fromExtendedFilter = async function(details) { + if ( + typeof details.rawFilter !== 'string' || + details.rawFilter === '' + ) { + return; + } + + await initWorker(); + + const id = messageId++; + const hostname = hostnameFromURI(details.url); + + const parser = new sfp.AstFilterParser({ + trustedSource: true, + nativeCssHas: vAPI.webextFlavor.env.includes('native_css_has'), + }); + parser.parse(details.rawFilter); + let compiled; + if ( parser.isScriptletFilter() ) { + compiled = JSON.stringify(parser.getScriptletArgs()); + } + + worker.postMessage({ + what: 'fromExtendedFilter', + id, + domain: domainFromHostname(hostname), + hostname, + ignoreGeneric: + staticNetFilteringEngine.matchRequestReverse( + 'generichide', + details.url + ) === 2, + ignoreSpecific: + staticNetFilteringEngine.matchRequestReverse( + 'specifichide', + details.url + ) === 2, + rawFilter: details.rawFilter, + compiled, + }); + + return new Promise(resolve => { + pendingResponses.set(id, resolve); + }); +}; + +// This tells the worker that filter lists may have changed. + +const resetLists = function() { + needLists = true; + if ( worker === null ) { return; } + worker.postMessage({ what: 'resetLists' }); +}; + +/******************************************************************************/ + +const staticFilteringReverseLookup = { + fromNetFilter, + fromExtendedFilter, + resetLists, + shutdown: stopWorker +}; + +export default staticFilteringReverseLookup; + +/******************************************************************************/ diff --git a/src/js/scriptlet-filtering-core.js b/src/js/scriptlet-filtering-core.js new file mode 100644 index 0000000..125eb87 --- /dev/null +++ b/src/js/scriptlet-filtering-core.js @@ -0,0 +1,300 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2017-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 +*/ + +'use strict'; + +/******************************************************************************/ + +import { redirectEngine as reng } from './redirect-engine.js'; +import { StaticExtFilteringHostnameDB } from './static-ext-filtering-db.js'; + +/******************************************************************************/ + +// Increment when internal representation changes +const VERSION = 1; + +const $scriptlets = new Set(); +const $exceptions = new Set(); +const $mainWorldMap = new Map(); +const $isolatedWorldMap = new Map(); + +/******************************************************************************/ + +const normalizeRawFilter = (parser, sourceIsTrusted = false) => { + 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); +}; + +const lookupScriptlet = (rawToken, mainMap, isolatedMap, debug = false) => { + if ( mainMap.has(rawToken) || isolatedMap.has(rawToken) ) { return; } + const args = JSON.parse(rawToken); + const token = `${args[0]}.js`; + const details = reng.contentFromName(token, 'text/javascript'); + if ( details === undefined ) { return; } + const targetWorldMap = details.world !== 'ISOLATED' ? mainMap : isolatedMap; + const content = patchScriptlet(details.js, args.slice(1)); + const dependencies = details.dependencies || []; + while ( dependencies.length !== 0 ) { + const token = dependencies.shift(); + if ( targetWorldMap.has(token) ) { continue; } + const details = reng.contentFromName(token, 'fn/javascript') || + reng.contentFromName(token, 'text/javascript'); + if ( details === undefined ) { continue; } + targetWorldMap.set(token, details.js); + if ( Array.isArray(details.dependencies) === false ) { continue; } + dependencies.push(...details.dependencies); + } + targetWorldMap.set(rawToken, [ + 'try {', + '// >>>> scriptlet start', + content, + '// <<<< scriptlet end', + '} catch (e) {', + debug ? 'console.error(e);' : '', + '}', + ].join('\n')); +}; + +// Fill-in scriptlet argument placeholders. +const patchScriptlet = (content, arglist) => { + if ( content.startsWith('function') && content.endsWith('}') ) { + content = `(${content})({{args}});`; + } + for ( let i = 0; i < arglist.length; i++ ) { + content = content.replace(`{{${i+1}}}`, arglist[i]); + } + return content.replace('{{args}}', + JSON.stringify(arglist).slice(1,-1).replace(/\$/g, '$$$') + ); +}; + +const decompile = json => { + const args = JSON.parse(json).map(s => s.replace(/,/g, '\\,')); + if ( args.length === 0 ) { return '+js()'; } + return `+js(${args.join(', ')})`; +}; + +/******************************************************************************/ + +export class ScriptletFilteringEngine { + constructor() { + this.acceptedCount = 0; + this.discardedCount = 0; + this.scriptletDB = new StaticExtFilteringHostnameDB(1, VERSION); + this.duplicates = new Set(); + } + + getFilterCount() { + return this.scriptletDB.size; + } + + reset() { + this.scriptletDB.clear(); + this.duplicates.clear(); + this.acceptedCount = 0; + this.discardedCount = 0; + } + + freeze() { + this.duplicates.clear(); + this.scriptletDB.collectGarbage(); + } + + // parser: instance of AstFilterParser from static-filtering-parser.js + // writer: instance of CompiledListWriter from static-filtering-io.js + compile(parser, writer) { + writer.select('SCRIPTLET_FILTERS'); + + // Only exception filters are allowed to be global. + const isException = parser.isException(); + const normalized = normalizeRawFilter(parser, writer.properties.get('trustedSource')); + + // Can fail if there is a mismatch with trust requirement + if ( normalized === undefined ) { return; } + + // Tokenless is meaningful only for exception filters. + if ( normalized === '[]' && isException === false ) { return; } + + if ( parser.hasOptions() === false ) { + if ( isException ) { + writer.push([ 32, '', 1, normalized ]); + } + return; + } + + // https://github.com/gorhill/uBlock/issues/3375 + // Ignore instances of exception filter with negated hostnames, + // because there is no way to create an exception to an exception. + + for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) { + if ( bad ) { continue; } + let kind = 0; + if ( isException ) { + if ( not ) { continue; } + kind |= 1; + } else if ( not ) { + kind |= 1; + } + writer.push([ 32, hn, kind, normalized ]); + } + } + + // writer: instance of CompiledListReader from static-filtering-io.js + fromCompiledContent(reader) { + reader.select('SCRIPTLET_FILTERS'); + + while ( reader.next() ) { + this.acceptedCount += 1; + const fingerprint = reader.fingerprint(); + if ( this.duplicates.has(fingerprint) ) { + this.discardedCount += 1; + continue; + } + this.duplicates.add(fingerprint); + const args = reader.args(); + if ( args.length < 4 ) { continue; } + this.scriptletDB.store(args[1], args[2], args[3]); + } + } + + toSelfie() { + return this.scriptletDB.toSelfie(); + } + + fromSelfie(selfie) { + if ( selfie instanceof Object === false ) { return false; } + if ( selfie.version !== VERSION ) { return false; } + this.scriptletDB.fromSelfie(selfie); + return true; + } + + retrieve(request, options = {}) { + if ( this.scriptletDB.size === 0 ) { return; } + + $scriptlets.clear(); + $exceptions.clear(); + + const { hostname } = request; + + this.scriptletDB.retrieve(hostname, [ $scriptlets, $exceptions ]); + const entity = request.entity !== '' + ? `${hostname.slice(0, -request.domain.length)}${request.entity}` + : '*'; + this.scriptletDB.retrieve(entity, [ $scriptlets, $exceptions ], 1); + if ( $scriptlets.size === 0 ) { return; } + + // Wholly disable scriptlet injection? + if ( $exceptions.has('[]') ) { + return { filters: '#@#+js()' }; + } + + for ( const token of $exceptions ) { + if ( $scriptlets.has(token) ) { + $scriptlets.delete(token); + } else { + $exceptions.delete(token); + } + } + + for ( const token of $scriptlets ) { + lookupScriptlet(token, $mainWorldMap, $isolatedWorldMap, options.debug); + } + + const mainWorldCode = []; + for ( const js of $mainWorldMap.values() ) { + mainWorldCode.push(js); + } + + const isolatedWorldCode = []; + for ( const js of $isolatedWorldMap.values() ) { + isolatedWorldCode.push(js); + } + + const scriptletDetails = { + mainWorld: mainWorldCode.join('\n\n'), + isolatedWorld: isolatedWorldCode.join('\n\n'), + filters: [ + ...Array.from($scriptlets).map(s => `##${decompile(s)}`), + ...Array.from($exceptions).map(s => `#@#${decompile(s)}`), + ].join('\n'), + }; + $mainWorldMap.clear(); + $isolatedWorldMap.clear(); + + if ( scriptletDetails.mainWorld === '' ) { + if ( scriptletDetails.isolatedWorld === '' ) { + return { filters: scriptletDetails.filters }; + } + } + + const scriptletGlobals = options.scriptletGlobals || []; + + if ( options.debug ) { + scriptletGlobals.push([ 'canDebug', true ]); + } + + return { + mainWorld: scriptletDetails.mainWorld === '' ? '' : [ + '(function() {', + '// >>>> start of private namespace', + '', + options.debugScriptlets ? 'debugger;' : ';', + '', + // For use by scriptlets to share local data among themselves + `const scriptletGlobals = new Map(${JSON.stringify(scriptletGlobals, null, 2)});`, + '', + scriptletDetails.mainWorld, + '', + '// <<<< end of private namespace', + '})();', + ].join('\n'), + isolatedWorld: scriptletDetails.isolatedWorld === '' ? '' : [ + 'function() {', + '// >>>> start of private namespace', + '', + options.debugScriptlets ? 'debugger;' : ';', + '', + // For use by scriptlets to share local data among themselves + `const scriptletGlobals = new Map(${JSON.stringify(scriptletGlobals, null, 2)});`, + '', + scriptletDetails.isolatedWorld, + '', + '// <<<< end of private namespace', + '}', + ].join('\n'), + filters: scriptletDetails.filters, + }; + } +} + +/******************************************************************************/ diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js new file mode 100644 index 0000000..10da19f --- /dev/null +++ b/src/js/scriptlet-filtering.js @@ -0,0 +1,328 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2017-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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ + +import µb from './background.js'; +import logger from './logger.js'; +import { onBroadcast } from './broadcast.js'; +import { redirectEngine as reng } from './redirect-engine.js'; +import { sessionFirewall } from './filtering-engines.js'; +import { MRUCache } from './mrucache.js'; +import { ScriptletFilteringEngine } from './scriptlet-filtering-core.js'; + +import { + domainFromHostname, + entityFromDomain, + hostnameFromURI, +} from './uri-utils.js'; + +/******************************************************************************/ + +const contentScriptRegisterer = new (class { + constructor() { + this.hostnameToDetails = new Map(); + if ( browser.contentScripts === undefined ) { return; } + onBroadcast(msg => { + if ( msg.what !== 'filteringBehaviorChanged' ) { return; } + if ( msg.direction > 0 ) { return; } + if ( msg.hostname ) { return this.flush(msg.hostname); } + this.reset(); + }); + } + register(hostname, code) { + if ( browser.contentScripts === undefined ) { return false; } + if ( hostname === '' ) { return false; } + const details = this.hostnameToDetails.get(hostname); + if ( details !== undefined ) { + if ( code === details.code ) { + return details.handle instanceof Promise === false; + } + details.handle.unregister(); + this.hostnameToDetails.delete(hostname); + } + const promise = browser.contentScripts.register({ + js: [ { code } ], + allFrames: true, + matches: [ `*://*.${hostname}/*` ], + matchAboutBlank: true, + runAt: 'document_start', + }).then(handle => { + this.hostnameToDetails.set(hostname, { handle, code }); + }).catch(( ) => { + this.hostnameToDetails.delete(hostname); + }); + this.hostnameToDetails.set(hostname, { handle: promise, code }); + return false; + } + unregister(hostname) { + if ( this.hostnameToDetails.size === 0 ) { return; } + const details = this.hostnameToDetails.get(hostname); + if ( details === undefined ) { return; } + this.hostnameToDetails.delete(hostname); + this.unregisterHandle(details.handle); + } + flush(hostname) { + if ( hostname === '*' ) { return this.reset(); } + for ( const hn of this.hostnameToDetails.keys() ) { + if ( hn.endsWith(hostname) === false ) { continue; } + const pos = hn.length - hostname.length; + if ( pos !== 0 && hn.charCodeAt(pos-1) !== 0x2E /* . */ ) { continue; } + this.unregister(hn); + } + } + reset() { + if ( this.hostnameToDetails.size === 0 ) { return; } + for ( const details of this.hostnameToDetails.values() ) { + this.unregisterHandle(details.handle); + } + this.hostnameToDetails.clear(); + } + unregisterHandle(handle) { + if ( handle instanceof Promise ) { + handle.then(handle => { handle.unregister(); }); + } else { + handle.unregister(); + } + } +})(); + +/******************************************************************************/ + +const mainWorldInjector = (( ) => { + const parts = [ + '(', + function(injector, details) { + if ( typeof self.uBO_scriptletsInjected === 'string' ) { return; } + const doc = document; + if ( doc.location === null ) { return; } + const hostname = doc.location.hostname; + if ( hostname !== '' && details.hostname !== hostname ) { return; } + injector(doc, details); + return 0; + }.toString(), + ')(', + vAPI.scriptletsInjector, ', ', + 'json-slot', + ');', + ]; + return { + parts, + jsonSlot: parts.indexOf('json-slot'), + assemble: function(hostname, scriptlets, filters) { + this.parts[this.jsonSlot] = JSON.stringify({ + hostname, + scriptlets, + filters, + }); + return this.parts.join(''); + }, + }; +})(); + +const isolatedWorldInjector = (( ) => { + const parts = [ + '(', + function(details) { + if ( self.uBO_isolatedScriptlets === 'done' ) { return; } + const doc = document; + if ( doc.location === null ) { return; } + const hostname = doc.location.hostname; + if ( hostname !== '' && details.hostname !== hostname ) { return; } + const isolatedScriptlets = function(){}; + isolatedScriptlets(); + self.uBO_isolatedScriptlets = 'done'; + return 0; + }.toString(), + ')(', + 'json-slot', + ');', + ]; + return { + parts, + jsonSlot: parts.indexOf('json-slot'), + assemble: function(hostname, scriptlets) { + this.parts[this.jsonSlot] = JSON.stringify({ hostname }); + const code = this.parts.join(''); + // Manually substitute noop function with scriptlet wrapper + // function, so as to not suffer instances of special + // replacement characters `$`,`\` when using String.replace() + // with scriptlet code. + const match = /function\(\)\{\}/.exec(code); + return code.slice(0, match.index) + + scriptlets + + code.slice(match.index + match[0].length); + }, + }; +})(); + +/******************************************************************************/ + +export class ScriptletFilteringEngineEx extends ScriptletFilteringEngine { + constructor() { + super(); + this.warOrigin = vAPI.getURL('/web_accessible_resources'); + this.warSecret = undefined; + this.scriptletCache = new MRUCache(32); + this.isDevBuild = undefined; + onBroadcast(msg => { + if ( msg.what !== 'hiddenSettingsChanged' ) { return; } + this.scriptletCache.reset(); + this.isDevBuild = undefined; + }); + } + + reset() { + super.reset(); + this.warSecret = vAPI.warSecret.long(this.warSecret); + this.scriptletCache.reset(); + contentScriptRegisterer.reset(); + } + + freeze() { + super.freeze(); + this.warSecret = vAPI.warSecret.long(this.warSecret); + this.scriptletCache.reset(); + contentScriptRegisterer.reset(); + } + + retrieve(request) { + const { hostname } = request; + + // https://github.com/gorhill/uBlock/issues/2835 + // Do not inject scriptlets if the site is under an `allow` rule. + if ( µb.userSettings.advancedUserEnabled ) { + if ( sessionFirewall.evaluateCellZY(hostname, hostname, '*') === 2 ) { + return; + } + } + + if ( this.scriptletCache.resetTime < reng.modifyTime ) { + this.warSecret = vAPI.warSecret.long(this.warSecret); + this.scriptletCache.reset(); + } + + let scriptletDetails = this.scriptletCache.lookup(hostname); + if ( scriptletDetails !== undefined ) { + return scriptletDetails || undefined; + } + + if ( this.isDevBuild === undefined ) { + this.isDevBuild = vAPI.webextFlavor.soup.has('devbuild') || + µb.hiddenSettings.filterAuthorMode; + } + + if ( this.warSecret === undefined ) { + this.warSecret = vAPI.warSecret.long(); + } + + const options = { + scriptletGlobals: [ + [ 'warOrigin', this.warOrigin ], + [ 'warSecret', this.warSecret ], + ], + debug: this.isDevBuild, + debugScriptlets: µb.hiddenSettings.debugScriptlets, + }; + + scriptletDetails = super.retrieve(request, options); + + this.scriptletCache.add(hostname, scriptletDetails || null); + + return scriptletDetails; + } + + injectNow(details) { + if ( typeof details.frameId !== 'number' ) { return; } + + const request = { + tabId: details.tabId, + frameId: details.frameId, + url: details.url, + hostname: hostnameFromURI(details.url), + domain: undefined, + entity: undefined + }; + + request.domain = domainFromHostname(request.hostname); + request.entity = entityFromDomain(request.domain); + + const scriptletDetails = this.retrieve(request); + if ( scriptletDetails === undefined ) { + contentScriptRegisterer.unregister(request.hostname); + return; + } + + const contentScript = []; + if ( µb.hiddenSettings.debugScriptletInjector ) { + contentScript.push('debugger'); + } + const { mainWorld = '', isolatedWorld = '', filters } = scriptletDetails; + if ( mainWorld !== '' ) { + contentScript.push(mainWorldInjector.assemble(request.hostname, mainWorld, filters)); + } + if ( isolatedWorld !== '' ) { + contentScript.push(isolatedWorldInjector.assemble(request.hostname, isolatedWorld)); + } + + const code = contentScript.join('\n\n'); + + const isAlreadyInjected = contentScriptRegisterer.register(request.hostname, code); + if ( isAlreadyInjected !== true ) { + vAPI.tabs.executeScript(details.tabId, { + code, + frameId: details.frameId, + matchAboutBlank: true, + runAt: 'document_start', + }); + } + + return scriptletDetails; + } + + toLogger(request, details) { + if ( details === undefined ) { return; } + if ( logger.enabled !== true ) { return; } + if ( typeof details.filters !== 'string' ) { return; } + const fctxt = µb.filteringContext + .duplicate() + .fromTabId(request.tabId) + .setRealm('extended') + .setType('scriptlet') + .setURL(request.url) + .setDocOriginFromURL(request.url); + for ( const raw of details.filters.split('\n') ) { + fctxt.setFilter({ source: 'extended', raw }).toLogger(); + } + } +} + +/******************************************************************************/ + +const scriptletFilteringEngine = new ScriptletFilteringEngineEx(); + +export default scriptletFilteringEngine; + +/******************************************************************************/ diff --git a/src/js/scriptlets/cosmetic-logger.js b/src/js/scriptlets/cosmetic-logger.js new file mode 100644 index 0000000..5d1f1b9 --- /dev/null +++ b/src/js/scriptlets/cosmetic-logger.js @@ -0,0 +1,365 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ + +(( ) => { +// >>>>>>>> start of private namespace + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } +if ( vAPI.domWatcher instanceof Object === false ) { return; } + +const reHasCSSCombinators = /[ >+~]/; +const simpleDeclarativeSet = new Set(); +let simpleDeclarativeStr; +const complexDeclarativeSet = new Set(); +let complexDeclarativeStr; +const proceduralDict = new Map(); +const exceptionDict = new Map(); +let exceptionStr; +const proceduralExceptionDict = new Map(); +const nodesToProcess = new Set(); +const loggedSelectors = new Set(); + +/******************************************************************************/ + +const rePseudoElements = /:(?::?after|:?before|:[a-z-]+)$/; + +function hasSelector(selector, context = document) { + try { + return context.querySelector(selector) !== null; + } + catch(ex) { + } + return false; +} + +function safeMatchSelector(selector, context) { + const safeSelector = rePseudoElements.test(selector) + ? selector.replace(rePseudoElements, '') + : selector; + try { + return context.matches(safeSelector); + } + catch(ex) { + } + return false; +} + +function safeQuerySelector(selector, context = document) { + const safeSelector = rePseudoElements.test(selector) + ? selector.replace(rePseudoElements, '') + : selector; + try { + return context.querySelector(safeSelector); + } + catch(ex) { + } + return null; +} + +function safeGroupSelectors(selectors) { + const arr = Array.isArray(selectors) + ? selectors + : Array.from(selectors); + return arr.map(s => { + return rePseudoElements.test(s) + ? s.replace(rePseudoElements, '') + : s; + }).join(',\n'); +} + +/******************************************************************************/ + +function processDeclarativeSimple(node, out) { + if ( simpleDeclarativeSet.size === 0 ) { return; } + if ( simpleDeclarativeStr === undefined ) { + simpleDeclarativeStr = safeGroupSelectors(simpleDeclarativeSet); + } + if ( + (node === document || node.matches(simpleDeclarativeStr) === false) && + (hasSelector(simpleDeclarativeStr, node) === false) + ) { + return; + } + for ( const selector of simpleDeclarativeSet ) { + if ( + (node === document || safeMatchSelector(selector, node) === false) && + (safeQuerySelector(selector, node) === null) + ) { + continue; + } + out.push(`##${selector}`); + simpleDeclarativeSet.delete(selector); + simpleDeclarativeStr = undefined; + loggedSelectors.add(selector); + } +} + +/******************************************************************************/ + +function processDeclarativeComplex(out) { + if ( complexDeclarativeSet.size === 0 ) { return; } + if ( complexDeclarativeStr === undefined ) { + complexDeclarativeStr = safeGroupSelectors(complexDeclarativeSet); + } + if ( hasSelector(complexDeclarativeStr) === false ) { return; } + for ( const selector of complexDeclarativeSet ) { + if ( safeQuerySelector(selector) === null ) { continue; } + out.push(`##${selector}`); + complexDeclarativeSet.delete(selector); + complexDeclarativeStr = undefined; + loggedSelectors.add(selector); + } +} + +/******************************************************************************/ + +function processProcedural(out) { + if ( proceduralDict.size === 0 ) { return; } + for ( const [ raw, pselector ] of proceduralDict ) { + if ( pselector.converted ) { + if ( safeQuerySelector(pselector.selector) === null ) { continue; } + } else if ( pselector.hit === false && pselector.exec().length === 0 ) { + continue; + } + out.push(`##${raw}`); + proceduralDict.delete(raw); + } +} + +/******************************************************************************/ + +function processExceptions(out) { + if ( exceptionDict.size === 0 ) { return; } + if ( exceptionStr === undefined ) { + exceptionStr = safeGroupSelectors(exceptionDict.keys()); + } + if ( hasSelector(exceptionStr) === false ) { return; } + for ( const [ selector, raw ] of exceptionDict ) { + if ( safeQuerySelector(selector) === null ) { continue; } + out.push(`#@#${raw}`); + exceptionDict.delete(selector); + exceptionStr = undefined; + loggedSelectors.add(raw); + } +} + +/******************************************************************************/ + +function processProceduralExceptions(out) { + if ( proceduralExceptionDict.size === 0 ) { return; } + for ( const exception of proceduralExceptionDict.values() ) { + if ( exception.test() === false ) { continue; } + out.push(`#@#${exception.raw}`); + proceduralExceptionDict.delete(exception.raw); + } +} + +/******************************************************************************/ + +const processTimer = new vAPI.SafeAnimationFrame(( ) => { + //console.time('dom logger/scanning for matches'); + processTimer.clear(); + if ( nodesToProcess.size === 0 ) { return; } + + if ( nodesToProcess.size !== 1 && nodesToProcess.has(document) ) { + nodesToProcess.clear(); + nodesToProcess.add(document); + } + + const toLog = []; + if ( simpleDeclarativeSet.size !== 0 ) { + for ( const node of nodesToProcess ) { + processDeclarativeSimple(node, toLog); + } + } + + processDeclarativeComplex(toLog); + processProcedural(toLog); + processExceptions(toLog); + processProceduralExceptions(toLog); + + nodesToProcess.clear(); + + if ( toLog.length === 0 ) { return; } + + const location = vAPI.effectiveSelf.location; + + vAPI.messaging.send('scriptlets', { + what: 'logCosmeticFilteringData', + frameURL: location.href, + frameHostname: location.hostname, + matchedSelectors: toLog, + }); + //console.timeEnd('dom logger/scanning for matches'); +}); + +/******************************************************************************/ + +const attributeObserver = new MutationObserver(mutations => { + if ( nodesToProcess.has(document) ) { return; } + for ( const mutation of mutations ) { + const node = mutation.target; + if ( node.nodeType !== 1 ) { continue; } + nodesToProcess.add(node); + } + if ( nodesToProcess.size !== 0 ) { + processTimer.start(100); + } +}); + +/******************************************************************************/ + +const handlers = { + onFiltersetChanged: function(changes) { + //console.time('dom logger/filterset changed'); + for ( const block of (changes.declarative || []) ) { + for ( const selector of block.split(',\n') ) { + if ( loggedSelectors.has(selector) ) { continue; } + if ( reHasCSSCombinators.test(selector) ) { + complexDeclarativeSet.add(selector); + complexDeclarativeStr = undefined; + } else { + simpleDeclarativeSet.add(selector); + simpleDeclarativeStr = undefined; + } + } + } + if ( + Array.isArray(changes.procedural) && + changes.procedural.length !== 0 + ) { + for ( const selector of changes.procedural ) { + proceduralDict.set(selector.raw, selector); + } + } + if ( Array.isArray(changes.exceptions) ) { + for ( const selector of changes.exceptions ) { + if ( loggedSelectors.has(selector) ) { continue; } + if ( selector.charCodeAt(0) !== 0x7B /* '{' */ ) { + exceptionDict.set(selector, selector); + continue; + } + const details = JSON.parse(selector); + if ( + details.action !== undefined && + details.tasks === undefined && + details.action[0] === 'style' + ) { + exceptionDict.set(details.selector, details.raw); + continue; + } + proceduralExceptionDict.set( + details.raw, + vAPI.domFilterer.createProceduralFilter(details) + ); + } + exceptionStr = undefined; + } + nodesToProcess.clear(); + nodesToProcess.add(document); + processTimer.start(1); + //console.timeEnd('dom logger/filterset changed'); + }, + + onDOMCreated: function() { + if ( vAPI.domFilterer instanceof Object === false ) { + return shutdown(); + } + handlers.onFiltersetChanged(vAPI.domFilterer.getAllSelectors()); + vAPI.domFilterer.addListener(handlers); + attributeObserver.observe(document.body, { + attributes: true, + subtree: true + }); + }, + + onDOMChanged: function(addedNodes) { + if ( nodesToProcess.has(document) ) { return; } + for ( const node of addedNodes ) { + if ( node.parentNode === null ) { continue; } + nodesToProcess.add(node); + } + if ( nodesToProcess.size !== 0 ) { + processTimer.start(100); + } + } +}; + +vAPI.domWatcher.addListener(handlers); + +/******************************************************************************/ + +const broadcastHandler = msg => { + if ( msg.what === 'loggerDisabled' ) { + shutdown(); + } +}; + +browser.runtime.onMessage.addListener(broadcastHandler); + +/******************************************************************************/ + +function shutdown() { + browser.runtime.onMessage.removeListener(broadcastHandler); + processTimer.clear(); + attributeObserver.disconnect(); + if ( typeof vAPI !== 'object' ) { return; } + if ( vAPI.domFilterer instanceof Object ) { + vAPI.domFilterer.removeListener(handlers); + } + if ( vAPI.domWatcher instanceof Object ) { + vAPI.domWatcher.removeListener(handlers); + } +} + +/******************************************************************************/ + +// <<<<<<<< end of private namespace +})(); + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; + diff --git a/src/js/scriptlets/cosmetic-off.js b/src/js/scriptlets/cosmetic-off.js new file mode 100644 index 0000000..f1301e2 --- /dev/null +++ b/src/js/scriptlets/cosmetic-off.js @@ -0,0 +1,48 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-2018 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 +*/ + +'use strict'; + +/******************************************************************************/ + +if ( typeof vAPI === 'object' && vAPI.domFilterer ) { + vAPI.domFilterer.toggle(false); +} + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/cosmetic-on.js b/src/js/scriptlets/cosmetic-on.js new file mode 100644 index 0000000..7b30976 --- /dev/null +++ b/src/js/scriptlets/cosmetic-on.js @@ -0,0 +1,48 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-2018 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 +*/ + +'use strict'; + +/******************************************************************************/ + +if ( typeof vAPI === 'object' && vAPI.domFilterer ) { + vAPI.domFilterer.toggle(true); +} + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/cosmetic-report.js b/src/js/scriptlets/cosmetic-report.js new file mode 100644 index 0000000..a968d4d --- /dev/null +++ b/src/js/scriptlets/cosmetic-report.js @@ -0,0 +1,142 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +(( ) => { +// >>>>>>>> start of private namespace + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } +if ( typeof vAPI.domFilterer !== 'object' ) { return; } +if ( vAPI.domFilterer === null ) { return; } + +/******************************************************************************/ + +const rePseudoElements = /:(?::?after|:?before|:[a-z-]+)$/; + +const hasSelector = selector => { + try { + return document.querySelector(selector) !== null; + } + catch(ex) { + } + return false; +}; + +const safeQuerySelector = selector => { + const safeSelector = rePseudoElements.test(selector) + ? selector.replace(rePseudoElements, '') + : selector; + try { + return document.querySelector(safeSelector); + } + catch(ex) { + } + return null; +}; + +const safeGroupSelectors = selectors => { + const arr = Array.isArray(selectors) + ? selectors + : Array.from(selectors); + return arr.map(s => { + return rePseudoElements.test(s) + ? s.replace(rePseudoElements, '') + : s; + }).join(',\n'); +}; + +const allSelectors = vAPI.domFilterer.getAllSelectors(); +const matchedSelectors = []; + +if ( Array.isArray(allSelectors.declarative) ) { + const declarativeSet = new Set(); + for ( const block of allSelectors.declarative ) { + for ( const selector of block.split(',\n') ) { + declarativeSet.add(selector); + } + } + if ( hasSelector(safeGroupSelectors(declarativeSet)) ) { + for ( const selector of declarativeSet ) { + if ( safeQuerySelector(selector) === null ) { continue; } + matchedSelectors.push(`##${selector}`); + } + } +} + +if ( + Array.isArray(allSelectors.procedural) && + allSelectors.procedural.length !== 0 +) { + for ( const pselector of allSelectors.procedural ) { + if ( pselector.hit === false && pselector.exec().length === 0 ) { continue; } + matchedSelectors.push(`##${pselector.raw}`); + } +} + +if ( Array.isArray(allSelectors.exceptions) ) { + const exceptionDict = new Map(); + for ( const selector of allSelectors.exceptions ) { + if ( selector.charCodeAt(0) !== 0x7B /* '{' */ ) { + exceptionDict.set(selector, selector); + continue; + } + const details = JSON.parse(selector); + if ( + details.action !== undefined && + details.tasks === undefined && + details.action[0] === 'style' + ) { + exceptionDict.set(details.selector, details.raw); + continue; + } + const pselector = vAPI.domFilterer.createProceduralFilter(details); + if ( pselector.test() === false ) { continue; } + matchedSelectors.push(`#@#${pselector.raw}`); + } + if ( + exceptionDict.size !== 0 && + hasSelector(safeGroupSelectors(exceptionDict.keys())) + ) { + for ( const [ selector, raw ] of exceptionDict ) { + if ( safeQuerySelector(selector) === null ) { continue; } + matchedSelectors.push(`#@#${raw}`); + } + } +} + +if ( typeof self.uBO_scriptletsInjected === 'string' ) { + matchedSelectors.push(...self.uBO_scriptletsInjected.split('\n')); +} + +if ( matchedSelectors.length === 0 ) { return; } + +return matchedSelectors; + +/******************************************************************************/ + +// <<<<<<<< end of private namespace +})(); + diff --git a/src/js/scriptlets/dom-inspector.js b/src/js/scriptlets/dom-inspector.js new file mode 100644 index 0000000..b5317d5 --- /dev/null +++ b/src/js/scriptlets/dom-inspector.js @@ -0,0 +1,924 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +/* globals browser */ + +'use strict'; + +/******************************************************************************/ +/******************************************************************************/ + +(async ( ) => { + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } +if ( typeof vAPI === null ) { return; } +if ( vAPI.domFilterer instanceof Object === false ) { return; } + +if ( vAPI.inspectorFrame ) { return; } +vAPI.inspectorFrame = true; + +const inspectorUniqueId = vAPI.randomToken(); + +const nodeToIdMap = new WeakMap(); // No need to iterate + +let blueNodes = []; +const roRedNodes = new Map(); // node => current cosmetic filter +const rwRedNodes = new Set(); // node => new cosmetic filter (toggle node) +const rwGreenNodes = new Set(); // node => new exception cosmetic filter (toggle filter) +//const roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle) + +const reHasCSSCombinators = /[ >+~]/; + +/******************************************************************************/ + +const domLayout = (( ) => { + const skipTagNames = new Set([ + 'br', 'head', 'link', 'meta', 'script', 'style', 'title' + ]); + const resourceAttrNames = new Map([ + [ 'a', 'href' ], + [ 'iframe', 'src' ], + [ 'img', 'src' ], + [ 'object', 'data' ] + ]); + + let idGenerator = 1; + + // This will be used to uniquely identify nodes across process. + + const newNodeId = node => { + const nid = `n${(idGenerator++).toString(36)}`; + nodeToIdMap.set(node, nid); + return nid; + }; + + const selectorFromNode = node => { + const tag = node.localName; + let selector = CSS.escape(tag); + // Id + if ( typeof node.id === 'string' ) { + let str = node.id.trim(); + if ( str !== '' ) { + selector += `#${CSS.escape(str)}`; + } + } + // Class + const cl = node.classList; + if ( cl ) { + for ( let i = 0; i < cl.length; i++ ) { + selector += `.${CSS.escape(cl[i])}`; + } + } + // Tag-specific attributes + const attr = resourceAttrNames.get(tag); + if ( attr !== undefined ) { + let str = node.getAttribute(attr) || ''; + str = str.trim(); + const pos = str.startsWith('data:') ? 5 : str.search(/[#?]/); + let sw = ''; + if ( pos !== -1 ) { + str = str.slice(0, pos); + sw = '^'; + } + if ( str !== '' ) { + selector += `[${attr}${sw}="${CSS.escape(str, true)}"]`; + } + } + return selector; + }; + + function DomRoot() { + this.nid = newNodeId(document.body); + this.lvl = 0; + this.sel = 'body'; + this.cnt = 0; + this.filter = roRedNodes.get(document.body); + } + + function DomNode(node, level) { + this.nid = newNodeId(node); + this.lvl = level; + this.sel = selectorFromNode(node); + this.cnt = 0; + this.filter = roRedNodes.get(node); + } + + const domNodeFactory = (level, node) => { + const localName = node.localName; + if ( skipTagNames.has(localName) ) { return null; } + // skip uBlock's own nodes + if ( node === inspectorFrame ) { return null; } + if ( level === 0 && localName === 'body' ) { + return new DomRoot(); + } + return new DomNode(node, level); + }; + + // Collect layout data + + const getLayoutData = ( ) => { + const layout = []; + const stack = []; + let lvl = 0; + let node = document.documentElement; + if ( node === null ) { return layout; } + + for (;;) { + const domNode = domNodeFactory(lvl, node); + if ( domNode !== null ) { + layout.push(domNode); + } + // children + if ( domNode !== null && node.firstElementChild !== null ) { + stack.push(node); + lvl += 1; + node = node.firstElementChild; + continue; + } + // sibling + if ( node instanceof Element ) { + if ( node.nextElementSibling === null ) { + do { + node = stack.pop(); + if ( !node ) { break; } + lvl -= 1; + } while ( node.nextElementSibling === null ); + if ( !node ) { break; } + } + node = node.nextElementSibling; + } + } + + return layout; + }; + + // Descendant count for each node. + + const patchLayoutData = layout => { + const stack = []; + let ptr; + let lvl = 0; + let i = layout.length; + + while ( i-- ) { + const domNode = layout[i]; + if ( domNode.lvl === lvl ) { + stack[ptr] += 1; + continue; + } + if ( domNode.lvl > lvl ) { + while ( lvl < domNode.lvl ) { + stack.push(0); + lvl += 1; + } + ptr = lvl - 1; + stack[ptr] += 1; + continue; + } + // domNode.lvl < lvl + const cnt = stack.pop(); + domNode.cnt = cnt; + lvl -= 1; + ptr = lvl - 1; + stack[ptr] += cnt + 1; + } + return layout; + }; + + // Track and report mutations of the DOM + + let mutationObserver = null; + let mutationTimer; + let addedNodelists = []; + let removedNodelist = []; + + const previousElementSiblingId = node => { + let sibling = node; + for (;;) { + sibling = sibling.previousElementSibling; + if ( sibling === null ) { return null; } + if ( skipTagNames.has(sibling.localName) ) { continue; } + return nodeToIdMap.get(sibling); + } + }; + + const journalFromBranch = (root, newNodes, newNodeToIdMap) => { + let node = root.firstElementChild; + while ( node !== null ) { + const domNode = domNodeFactory(undefined, node); + if ( domNode !== null ) { + newNodeToIdMap.set(domNode.nid, domNode); + newNodes.push(node); + } + // down + if ( node.firstElementChild !== null ) { + node = node.firstElementChild; + continue; + } + // right + if ( node.nextElementSibling !== null ) { + node = node.nextElementSibling; + continue; + } + // up then right + for (;;) { + if ( node.parentElement === root ) { return; } + node = node.parentElement; + if ( node.nextElementSibling !== null ) { + node = node.nextElementSibling; + break; + } + } + } + }; + + const journalFromMutations = ( ) => { + mutationTimer = undefined; + + // This is used to temporarily hold all added nodes, before resolving + // their node id and relative position. + const newNodes = []; + const journalEntries = []; + const newNodeToIdMap = new Map(); + + for ( const nodelist of addedNodelists ) { + for ( const node of nodelist ) { + if ( node.nodeType !== 1 ) { continue; } + if ( node.parentElement === null ) { continue; } + cosmeticFilterMapper.incremental(node); + const domNode = domNodeFactory(undefined, node); + if ( domNode !== null ) { + newNodeToIdMap.set(domNode.nid, domNode); + newNodes.push(node); + } + journalFromBranch(node, newNodes, newNodeToIdMap); + } + } + addedNodelists = []; + for ( const nodelist of removedNodelist ) { + for ( const node of nodelist ) { + if ( node.nodeType !== 1 ) { continue; } + const nid = nodeToIdMap.get(node); + if ( nid === undefined ) { continue; } + journalEntries.push({ what: -1, nid }); + } + } + removedNodelist = []; + for ( const node of newNodes ) { + journalEntries.push({ + what: 1, + nid: nodeToIdMap.get(node), + u: nodeToIdMap.get(node.parentElement), + l: previousElementSiblingId(node) + }); + } + + if ( journalEntries.length === 0 ) { return; } + + contentInspectorChannel.toLogger({ + what: 'domLayoutIncremental', + url: window.location.href, + hostname: window.location.hostname, + journal: journalEntries, + nodes: Array.from(newNodeToIdMap) + }); + }; + + const onMutationObserved = mutationRecords => { + for ( const record of mutationRecords ) { + if ( record.addedNodes.length !== 0 ) { + addedNodelists.push(record.addedNodes); + } + if ( record.removedNodes.length !== 0 ) { + removedNodelist.push(record.removedNodes); + } + } + if ( mutationTimer === undefined ) { + mutationTimer = vAPI.setTimeout(journalFromMutations, 1000); + } + }; + + // API + + const getLayout = ( ) => { + cosmeticFilterMapper.reset(); + mutationObserver = new MutationObserver(onMutationObserved); + mutationObserver.observe(document.body, { + childList: true, + subtree: true + }); + + return { + what: 'domLayoutFull', + url: window.location.href, + hostname: window.location.hostname, + layout: patchLayoutData(getLayoutData()) + }; + }; + + const reset = ( ) => { + shutdown(); + }; + + const shutdown = ( ) => { + if ( mutationTimer !== undefined ) { + clearTimeout(mutationTimer); + mutationTimer = undefined; + } + if ( mutationObserver !== null ) { + mutationObserver.disconnect(); + mutationObserver = null; + } + addedNodelists = []; + removedNodelist = []; + }; + + return { + get: getLayout, + reset, + shutdown, + }; +})(); + +/******************************************************************************/ +/******************************************************************************/ + +const cosmeticFilterMapper = (( ) => { + const nodesFromStyleTag = rootNode => { + const filterMap = roRedNodes; + const details = vAPI.domFilterer.getAllSelectors(); + + // Declarative selectors. + for ( const block of (details.declarative || []) ) { + for ( const selector of block.split(',\n') ) { + let nodes; + if ( reHasCSSCombinators.test(selector) ) { + nodes = document.querySelectorAll(selector); + } else { + if ( + filterMap.has(rootNode) === false && + rootNode.matches(selector) + ) { + filterMap.set(rootNode, selector); + } + nodes = rootNode.querySelectorAll(selector); + } + for ( const node of nodes ) { + if ( filterMap.has(node) ) { continue; } + filterMap.set(node, selector); + } + } + } + + // Procedural selectors. + for ( const entry of (details.procedural || []) ) { + const nodes = entry.exec(); + for ( const node of nodes ) { + // Upgrade declarative selector to procedural one + filterMap.set(node, entry.raw); + } + } + }; + + const incremental = rootNode => { + nodesFromStyleTag(rootNode); + }; + + const reset = ( ) => { + roRedNodes.clear(); + if ( document.documentElement !== null ) { + incremental(document.documentElement); + } + }; + + const shutdown = ( ) => { + vAPI.domFilterer.toggle(true); + }; + + return { + incremental, + reset, + shutdown, + }; +})(); + +/******************************************************************************/ + +const elementsFromSelector = function(selector, context) { + if ( !context ) { + context = document; + } + if ( selector.indexOf(':') !== -1 ) { + const out = elementsFromSpecialSelector(selector); + if ( out !== undefined ) { return out; } + } + // plain CSS selector + try { + return context.querySelectorAll(selector); + } catch (ex) { + } + return []; +}; + +const elementsFromSpecialSelector = function(selector) { + const out = []; + let matches = /^(.+?):has\((.+?)\)$/.exec(selector); + if ( matches !== null ) { + let nodes; + try { + nodes = document.querySelectorAll(matches[1]); + } catch(ex) { + nodes = []; + } + for ( const node of nodes ) { + if ( node.querySelector(matches[2]) === null ) { continue; } + out.push(node); + } + return out; + } + + matches = /^:xpath\((.+?)\)$/.exec(selector); + if ( matches === null ) { return; } + const xpr = document.evaluate( + matches[1], + document, + null, + XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, + null + ); + let i = xpr.snapshotLength; + while ( i-- ) { + out.push(xpr.snapshotItem(i)); + } + return out; +}; + +/******************************************************************************/ + +const highlightElements = ( ) => { + const paths = []; + + const path = []; + for ( const elem of rwRedNodes.keys() ) { + if ( elem === inspectorFrame ) { continue; } + if ( rwGreenNodes.has(elem) ) { continue; } + if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; } + const rect = elem.getBoundingClientRect(); + const xl = rect.left; + const w = rect.width; + const yt = rect.top; + const h = rect.height; + const ws = w.toFixed(1); + const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) + + 'h' + ws + + 'v' + h.toFixed(1) + + 'h-' + ws + + 'z'; + path.push(poly); + } + paths.push(path.join('') || 'M0 0'); + + path.length = 0; + for ( const elem of rwGreenNodes ) { + if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; } + const rect = elem.getBoundingClientRect(); + const xl = rect.left; + const w = rect.width; + const yt = rect.top; + const h = rect.height; + const ws = w.toFixed(1); + const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) + + 'h' + ws + + 'v' + h.toFixed(1) + + 'h-' + ws + + 'z'; + path.push(poly); + } + paths.push(path.join('') || 'M0 0'); + + path.length = 0; + for ( const elem of roRedNodes.keys() ) { + if ( elem === inspectorFrame ) { continue; } + if ( rwGreenNodes.has(elem) ) { continue; } + if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; } + const rect = elem.getBoundingClientRect(); + const xl = rect.left; + const w = rect.width; + const yt = rect.top; + const h = rect.height; + const ws = w.toFixed(1); + const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) + + 'h' + ws + + 'v' + h.toFixed(1) + + 'h-' + ws + + 'z'; + path.push(poly); + } + paths.push(path.join('') || 'M0 0'); + + path.length = 0; + for ( const elem of blueNodes ) { + if ( elem === inspectorFrame ) { continue; } + if ( typeof elem.getBoundingClientRect !== 'function' ) { continue; } + const rect = elem.getBoundingClientRect(); + const xl = rect.left; + const w = rect.width; + const yt = rect.top; + const h = rect.height; + const ws = w.toFixed(1); + const poly = 'M' + xl.toFixed(1) + ' ' + yt.toFixed(1) + + 'h' + ws + + 'v' + h.toFixed(1) + + 'h-' + ws + + 'z'; + path.push(poly); + } + paths.push(path.join('') || 'M0 0'); + + contentInspectorChannel.toFrame({ + what: 'svgPaths', + paths, + }); +}; + +/******************************************************************************/ + +const onScrolled = (( ) => { + let timer; + return ( ) => { + if ( timer ) { return; } + timer = window.requestAnimationFrame(( ) => { + timer = undefined; + highlightElements(); + }); + }; +})(); + +const onMouseOver = ( ) => { + if ( blueNodes.length === 0 ) { return; } + blueNodes = []; + highlightElements(); +}; + +/******************************************************************************/ + +const selectNodes = (selector, nid) => { + const nodes = elementsFromSelector(selector); + if ( nid === '' ) { return nodes; } + for ( const node of nodes ) { + if ( nodeToIdMap.get(node) === nid ) { + return [ node ]; + } + } + return []; +}; + +/******************************************************************************/ + +const nodesFromFilter = selector => { + const out = []; + for ( const entry of roRedNodes ) { + if ( entry[1] === selector ) { + out.push(entry[0]); + } + } + return out; +}; + +/******************************************************************************/ + +const toggleExceptions = (nodes, targetState) => { + for ( const node of nodes ) { + if ( targetState ) { + rwGreenNodes.add(node); + } else { + rwGreenNodes.delete(node); + } + } +}; + +const toggleFilter = (nodes, targetState) => { + for ( const node of nodes ) { + if ( targetState ) { + rwRedNodes.delete(node); + } else { + rwRedNodes.add(node); + } + } +}; + +const resetToggledNodes = ( ) => { + rwGreenNodes.clear(); + rwRedNodes.clear(); +}; + +/******************************************************************************/ + +const startInspector = ( ) => { + const onReady = ( ) => { + window.addEventListener('scroll', onScrolled, { + capture: true, + passive: true, + }); + window.addEventListener('mouseover', onMouseOver, { + capture: true, + passive: true, + }); + contentInspectorChannel.toLogger(domLayout.get()); + vAPI.domFilterer.toggle(false, highlightElements); + }; + if ( document.readyState === 'loading' ) { + document.addEventListener('DOMContentLoaded', onReady, { once: true }); + } else { + onReady(); + } +}; + +/******************************************************************************/ + +const shutdownInspector = ( ) => { + cosmeticFilterMapper.shutdown(); + domLayout.shutdown(); + window.removeEventListener('scroll', onScrolled, { + capture: true, + passive: true, + }); + window.removeEventListener('mouseover', onMouseOver, { + capture: true, + passive: true, + }); + contentInspectorChannel.shutdown(); + if ( inspectorFrame ) { + inspectorFrame.remove(); + inspectorFrame = null; + } + vAPI.userStylesheet.remove(inspectorCSS); + vAPI.userStylesheet.apply(); + vAPI.inspectorFrame = false; +}; + +/******************************************************************************/ +/******************************************************************************/ + +const onMessage = request => { + switch ( request.what ) { + case 'startInspector': + startInspector(); + break; + + case 'quitInspector': + shutdownInspector(); + break; + + case 'commitFilters': + highlightElements(); + break; + + case 'domLayout': + domLayout.get(); + highlightElements(); + break; + + case 'highlightMode': + break; + + case 'highlightOne': + blueNodes = selectNodes(request.selector, request.nid); + if ( blueNodes.length !== 0 ) { + blueNodes[0].scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'nearest', + }); + } + highlightElements(); + break; + + case 'resetToggledNodes': + resetToggledNodes(); + highlightElements(); + break; + + case 'showCommitted': + blueNodes = []; + // TODO: show only the new filters and exceptions. + highlightElements(); + break; + + case 'showInteractive': + blueNodes = []; + highlightElements(); + break; + + case 'toggleFilter': { + const nodes = selectNodes(request.selector, request.nid); + if ( nodes.length !== 0 ) { + nodes[0].scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'nearest', + }); + } + toggleExceptions(nodesFromFilter(request.filter), request.target); + highlightElements(); + break; + } + case 'toggleNodes': { + const nodes = selectNodes(request.selector, request.nid); + if ( nodes.length !== 0 ) { + nodes[0].scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'nearest', + }); + } + toggleFilter(nodes, request.target); + highlightElements(); + break; + } + default: + break; + } +}; + +/******************************************************************************* + * + * Establish two-way communication with logger/inspector window and + * inspector frame + * + * */ + +const contentInspectorChannel = (( ) => { + let toLoggerPort; + let toFramePort; + + const toLogger = msg => { + if ( toLoggerPort === undefined ) { return; } + try { + toLoggerPort.postMessage(msg); + } catch(_) { + shutdownInspector(); + } + }; + + const onLoggerMessage = msg => { + onMessage(msg); + }; + + const onLoggerDisconnect = ( ) => { + shutdownInspector(); + }; + + const onLoggerConnect = port => { + browser.runtime.onConnect.removeListener(onLoggerConnect); + toLoggerPort = port; + port.onMessage.addListener(onLoggerMessage); + port.onDisconnect.addListener(onLoggerDisconnect); + }; + + const toFrame = msg => { + if ( toFramePort === undefined ) { return; } + toFramePort.postMessage(msg); + }; + + const shutdown = ( ) => { + if ( toFramePort !== undefined ) { + toFrame({ what: 'quitInspector' }); + toFramePort.onmessage = null; + toFramePort.close(); + toFramePort = undefined; + } + if ( toLoggerPort !== undefined ) { + toLoggerPort.onMessage.removeListener(onLoggerMessage); + toLoggerPort.onDisconnect.removeListener(onLoggerDisconnect); + toLoggerPort.disconnect(); + toLoggerPort = undefined; + } + browser.runtime.onConnect.removeListener(onLoggerConnect); + }; + + const start = async ( ) => { + browser.runtime.onConnect.addListener(onLoggerConnect); + const inspectorArgs = await vAPI.messaging.send('domInspectorContent', { + what: 'getInspectorArgs', + }); + if ( typeof inspectorArgs !== 'object' ) { return; } + if ( inspectorArgs === null ) { return; } + return new Promise(resolve => { + const iframe = document.createElement('iframe'); + iframe.setAttribute(inspectorUniqueId, ''); + document.documentElement.append(iframe); + iframe.addEventListener('load', ( ) => { + iframe.setAttribute(`${inspectorUniqueId}-loaded`, ''); + const channel = new MessageChannel(); + toFramePort = channel.port1; + toFramePort.onmessage = ev => { + const msg = ev.data || {}; + if ( msg.what !== 'startInspector' ) { return; } + }; + iframe.contentWindow.postMessage( + { what: 'startInspector' }, + inspectorArgs.inspectorURL, + [ channel.port2 ] + ); + resolve(iframe); + }, { once: true }); + iframe.contentWindow.location = inspectorArgs.inspectorURL; + }); + }; + + return { start, toLogger, toFrame, shutdown }; +})(); + + +// Install DOM inspector widget +const inspectorCSSStyle = [ + 'background: transparent', + 'border: 0', + 'border-radius: 0', + 'box-shadow: none', + 'color-scheme: light dark', + 'display: block', + 'filter: none', + 'height: 100%', + 'left: 0', + 'margin: 0', + 'max-height: none', + 'max-width: none', + 'min-height: unset', + 'min-width: unset', + 'opacity: 1', + 'outline: 0', + 'padding: 0', + 'pointer-events: none', + 'position: fixed', + 'top: 0', + 'transform: none', + 'visibility: hidden', + 'width: 100%', + 'z-index: 2147483647', + '' +].join(' !important;\n'); + +const inspectorCSS = ` +:root > [${inspectorUniqueId}] { + ${inspectorCSSStyle} +} +:root > [${inspectorUniqueId}-loaded] { + visibility: visible !important; +} +`; + +vAPI.userStylesheet.add(inspectorCSS); +vAPI.userStylesheet.apply(); + +let inspectorFrame = await contentInspectorChannel.start(); +if ( inspectorFrame instanceof HTMLIFrameElement === false ) { + return shutdownInspector(); +} + +startInspector(); + +/******************************************************************************/ + +})(); + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/dom-survey-elements.js b/src/js/scriptlets/dom-survey-elements.js new file mode 100644 index 0000000..1582596 --- /dev/null +++ b/src/js/scriptlets/dom-survey-elements.js @@ -0,0 +1,72 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +// https://github.com/uBlockOrigin/uBlock-issues/issues/756 +// Keep in mind CPU usage with large DOM and/or filterset. + +(( ) => { + if ( typeof vAPI !== 'object' ) { return; } + + const t0 = Date.now(); + + if ( vAPI.domSurveyElements instanceof Object === false ) { + vAPI.domSurveyElements = { + busy: false, + hiddenElementCount: Number.NaN, + surveyTime: t0, + }; + } + const surveyResults = vAPI.domSurveyElements; + + if ( surveyResults.busy ) { return; } + surveyResults.busy = true; + + if ( surveyResults.surveyTime < vAPI.domMutationTime ) { + surveyResults.hiddenElementCount = Number.NaN; + } + surveyResults.surveyTime = t0; + + if ( isNaN(surveyResults.hiddenElementCount) ) { + surveyResults.hiddenElementCount = (( ) => { + if ( vAPI.domFilterer instanceof Object === false ) { return 0; } + const details = vAPI.domFilterer.getAllSelectors(0b11); + if ( + Array.isArray(details.declarative) === false || + details.declarative.length === 0 + ) { + return 0; + } + return document.querySelectorAll( + details.declarative.join(',\n') + ).length; + })(); + } + + surveyResults.busy = false; + + // IMPORTANT: This is returned to the injector, so this MUST be + // the last statement. + return surveyResults.hiddenElementCount; +})(); diff --git a/src/js/scriptlets/dom-survey-scripts.js b/src/js/scriptlets/dom-survey-scripts.js new file mode 100644 index 0000000..e5300ff --- /dev/null +++ b/src/js/scriptlets/dom-survey-scripts.js @@ -0,0 +1,126 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +// Scriptlets to count the number of script tags in a document. + +(( ) => { + if ( typeof vAPI !== 'object' ) { return; } + + const t0 = Date.now(); + + if ( vAPI.domSurveyScripts instanceof Object === false ) { + vAPI.domSurveyScripts = { + busy: false, + scriptCount: -1, + surveyTime: t0, + }; + } + const surveyResults = vAPI.domSurveyScripts; + + if ( surveyResults.busy ) { return; } + surveyResults.busy = true; + + if ( surveyResults.surveyTime < vAPI.domMutationTime ) { + surveyResults.scriptCount = -1; + } + surveyResults.surveyTime = t0; + + if ( surveyResults.scriptCount === -1 ) { + const reInlineScript = /^(data:|blob:|$)/; + let inlineScriptCount = 0; + let scriptCount = 0; + for ( const script of document.scripts ) { + if ( reInlineScript.test(script.src) ) { + inlineScriptCount = 1; + continue; + } + scriptCount += 1; + if ( scriptCount === 99 ) { break; } + } + scriptCount += inlineScriptCount; + if ( scriptCount !== 0 ) { + surveyResults.scriptCount = scriptCount; + } + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/756 + // Keep trying to find inline script-like instances but only if we + // have the time-budget to do so. + if ( surveyResults.scriptCount === -1 ) { + if ( document.querySelector('a[href^="javascript:"]') !== null ) { + surveyResults.scriptCount = 1; + } + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1756 + // Mind that there might be no body element. + if ( surveyResults.scriptCount === -1 && document.body !== null ) { + surveyResults.scriptCount = 0; + const onHandlers = new Set([ + 'onabort', 'onblur', 'oncancel', 'oncanplay', + 'oncanplaythrough', 'onchange', 'onclick', 'onclose', + 'oncontextmenu', 'oncuechange', 'ondblclick', 'ondrag', + 'ondragend', 'ondragenter', 'ondragexit', 'ondragleave', + 'ondragover', 'ondragstart', 'ondrop', 'ondurationchange', + 'onemptied', 'onended', 'onerror', 'onfocus', + 'oninput', 'oninvalid', 'onkeydown', 'onkeypress', + 'onkeyup', 'onload', 'onloadeddata', 'onloadedmetadata', + 'onloadstart', 'onmousedown', 'onmouseenter', 'onmouseleave', + 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', + 'onwheel', 'onpause', 'onplay', 'onplaying', + 'onprogress', 'onratechange', 'onreset', 'onresize', + 'onscroll', 'onseeked', 'onseeking', 'onselect', + 'onshow', 'onstalled', 'onsubmit', 'onsuspend', + 'ontimeupdate', 'ontoggle', 'onvolumechange', 'onwaiting', + 'onafterprint', 'onbeforeprint', 'onbeforeunload', 'onhashchange', + 'onlanguagechange', 'onmessage', 'onoffline', 'ononline', + 'onpagehide', 'onpageshow', 'onrejectionhandled', 'onpopstate', + 'onstorage', 'onunhandledrejection', 'onunload', + 'oncopy', 'oncut', 'onpaste' + ]); + const nodeIter = document.createNodeIterator( + document.body, + NodeFilter.SHOW_ELEMENT + ); + for (;;) { + const node = nodeIter.nextNode(); + if ( node === null ) { break; } + if ( node.hasAttributes() === false ) { continue; } + for ( const attr of node.getAttributeNames() ) { + if ( onHandlers.has(attr) === false ) { continue; } + surveyResults.scriptCount = 1; + break; + } + } + } + + surveyResults.busy = false; + + // IMPORTANT: This is returned to the injector, so this MUST be + // the last statement. + if ( surveyResults.scriptCount !== -1 ) { + return surveyResults.scriptCount; + } +})(); diff --git a/src/js/scriptlets/epicker.js b/src/js/scriptlets/epicker.js new file mode 100644 index 0000000..80489e8 --- /dev/null +++ b/src/js/scriptlets/epicker.js @@ -0,0 +1,1356 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient 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 +*/ + +/* global CSS */ + +'use strict'; + +/******************************************************************************/ +/******************************************************************************/ + +(async ( ) => { + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } +if ( typeof vAPI === null ) { return; } + +if ( vAPI.pickerFrame ) { return; } +vAPI.pickerFrame = true; + +const pickerUniqueId = vAPI.randomToken(); + +const reCosmeticAnchor = /^#(\$|\?|\$\?)?#/; + +const netFilterCandidates = []; +const cosmeticFilterCandidates = []; + +let targetElements = []; +let candidateElements = []; +let bestCandidateFilter = null; + +const lastNetFilterSession = window.location.host + window.location.pathname; +let lastNetFilterHostname = ''; +let lastNetFilterUnion = ''; + +const hideBackgroundStyle = 'background-image:none!important;'; + +/******************************************************************************/ + +const safeQuerySelectorAll = function(node, selector) { + if ( node !== null ) { + try { + return node.querySelectorAll(selector); + } catch (e) { + } + } + return []; +}; + +/******************************************************************************/ + +const getElementBoundingClientRect = function(elem) { + let rect = typeof elem.getBoundingClientRect === 'function' + ? elem.getBoundingClientRect() + : { height: 0, left: 0, top: 0, width: 0 }; + + // https://github.com/gorhill/uBlock/issues/1024 + // Try not returning an empty bounding rect. + if ( rect.width !== 0 && rect.height !== 0 ) { + return rect; + } + if ( elem.shadowRoot instanceof DocumentFragment ) { + return getElementBoundingClientRect(elem.shadowRoot); + } + + let left = rect.left, + right = left + rect.width, + top = rect.top, + bottom = top + rect.height; + + for ( const child of elem.children ) { + rect = getElementBoundingClientRect(child); + if ( rect.width === 0 || rect.height === 0 ) { continue; } + if ( rect.left < left ) { left = rect.left; } + if ( rect.right > right ) { right = rect.right; } + if ( rect.top < top ) { top = rect.top; } + if ( rect.bottom > bottom ) { bottom = rect.bottom; } + } + + return { + bottom, + height: bottom - top, + left, + right, + top, + width: right - left + }; +}; + +/******************************************************************************/ + +const highlightElements = function(elems, force) { + // To make mouse move handler more efficient + if ( + (force !== true) && + (elems.length === targetElements.length) && + (elems.length === 0 || elems[0] === targetElements[0]) + ) { + return; + } + targetElements = []; + + const ow = self.innerWidth; + const oh = self.innerHeight; + const islands = []; + + for ( const elem of elems ) { + if ( elem === pickerFrame ) { continue; } + targetElements.push(elem); + const rect = getElementBoundingClientRect(elem); + // Ignore offscreen areas + if ( + rect.left > ow || rect.top > oh || + rect.left + rect.width < 0 || rect.top + rect.height < 0 + ) { + continue; + } + islands.push( + `M${rect.left} ${rect.top}h${rect.width}v${rect.height}h-${rect.width}z` + ); + } + + pickerFramePort.postMessage({ + what: 'svgPaths', + ocean: `M0 0h${ow}v${oh}h-${ow}z`, + islands: islands.join(''), + }); +}; + +/******************************************************************************/ + +const mergeStrings = function(urls) { + if ( urls.length === 0 ) { return ''; } + if ( + urls.length === 1 || + self.diff_match_patch instanceof Function === false + ) { + return urls[0]; + } + const differ = new self.diff_match_patch(); + let merged = urls[0]; + for ( let i = 1; i < urls.length; i++ ) { + // The differ works at line granularity: we insert a linefeed after + // each character to trick the differ to work at character granularity. + const diffs = differ.diff_main( + urls[i].split('').join('\n'), + merged.split('').join('\n') + ); + const result = []; + for ( const diff of diffs ) { + if ( diff[0] !== 0 ) { + result.push('*'); + } else { + result.push(diff[1].replace(/\n+/g, '')); + } + merged = result.join(''); + } + } + // Keep usage of wildcards to a sane level, too many of them can cause + // high overhead filters + merged = merged.replace(/^\*+$/, '') + .replace(/\*{2,}/g, '*') + .replace(/([^*]{1,3}\*)(?:[^*]{1,3}\*)+/g, '$1'); + + // https://github.com/uBlockOrigin/uBlock-issues/issues/1494 + let pos = merged.indexOf('/'); + if ( pos === -1 ) { pos = merged.length; } + return merged.slice(0, pos).includes('*') ? urls[0] : merged; +}; + +/******************************************************************************/ + +// Remove fragment part from a URL. + +const trimFragmentFromURL = function(url) { + const pos = url.indexOf('#'); + return pos !== -1 ? url.slice(0, pos) : url; +}; + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/1897 +// Ignore `data:` URI, they can't be handled by an HTTP observer. + +const backgroundImageURLFromElement = function(elem) { + const style = window.getComputedStyle(elem); + const bgImg = style.backgroundImage || ''; + const matches = /^url\((["']?)([^"']+)\1\)$/.exec(bgImg); + const url = matches !== null && matches.length === 3 ? matches[2] : ''; + return url.lastIndexOf('data:', 0) === -1 + ? trimFragmentFromURL(url.slice(0, 1024)) + : ''; +}; + +/******************************************************************************/ + +// https://github.com/gorhill/uBlock/issues/1725#issuecomment-226479197 +// Limit returned string to 1024 characters. +// Also, return only URLs which will be seen by an HTTP observer. +// https://github.com/uBlockOrigin/uBlock-issues/issues/2260 +// Maybe get to the actual URL indirectly. +const resourceURLsFromElement = function(elem) { + const urls = []; + const tagName = elem.localName; + const prop = netFilter1stSources[tagName]; + if ( prop === undefined ) { + const url = backgroundImageURLFromElement(elem); + if ( url !== '' ) { urls.push(url); } + return urls; + } + let s = elem[prop]; + if ( s instanceof SVGAnimatedString ) { + s = s.baseVal; + } + if ( typeof s === 'string' && /^https?:\/\//.test(s) ) { + urls.push(trimFragmentFromURL(s.slice(0, 1024))); + } + resourceURLsFromSrcset(elem, urls); + resourceURLsFromPicture(elem, urls); + return urls; +}; + +// https://html.spec.whatwg.org/multipage/images.html#parsing-a-srcset-attribute +// https://github.com/uBlockOrigin/uBlock-issues/issues/1071 +const resourceURLsFromSrcset = function(elem, out) { + let srcset = elem.srcset; + if ( typeof srcset !== 'string' || srcset === '' ) { return; } + for(;;) { + // trim whitespace + srcset = srcset.trim(); + if ( srcset.length === 0 ) { break; } + // abort in case of leading comma + if ( /^,/.test(srcset) ) { break; } + // collect and consume all non-whitespace characters + let match = /^\S+/.exec(srcset); + if ( match === null ) { break; } + srcset = srcset.slice(match.index + match[0].length); + let url = match[0]; + // consume descriptor, if any + if ( /,$/.test(url) ) { + url = url.replace(/,$/, ''); + if ( /,$/.test(url) ) { break; } + } else { + match = /^[^,]*(?:\(.+?\))?[^,]*(?:,|$)/.exec(srcset); + if ( match === null ) { break; } + srcset = srcset.slice(match.index + match[0].length); + } + const parsedURL = new URL(url, document.baseURI); + if ( parsedURL.pathname.length === 0 ) { continue; } + out.push(trimFragmentFromURL(parsedURL.href)); + } +}; + +// https://github.com/uBlockOrigin/uBlock-issues/issues/2069#issuecomment-1080600661 +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture +const resourceURLsFromPicture = function(elem, out) { + if ( elem.localName === 'source' ) { return; } + const picture = elem.parentElement; + if ( picture === null || picture.localName !== 'picture' ) { return; } + const sources = picture.querySelectorAll(':scope > source'); + for ( const source of sources ) { + const urls = resourceURLsFromElement(source); + if ( urls.length === 0 ) { continue; } + out.push(...urls); + } +}; + +/******************************************************************************/ + +const netFilterFromUnion = function(patternIn, out) { + // Reset reference filter when dealing with unrelated URLs + const currentHostname = self.location.hostname; + if ( + lastNetFilterUnion === '' || + currentHostname === '' || + currentHostname !== lastNetFilterHostname + ) { + lastNetFilterHostname = currentHostname; + lastNetFilterUnion = patternIn; + vAPI.messaging.send('elementPicker', { + what: 'elementPickerEprom', + lastNetFilterSession, + lastNetFilterHostname, + lastNetFilterUnion, + }); + return; + } + + // Related URLs + lastNetFilterHostname = currentHostname; + let patternOut = mergeStrings([ patternIn, lastNetFilterUnion ]); + if ( patternOut !== '/*' && patternOut !== patternIn ) { + const filter = `||${patternOut}`; + if ( out.indexOf(filter) === -1 ) { + out.push(filter); + } + lastNetFilterUnion = patternOut; + } + + // Remember across element picker sessions + vAPI.messaging.send('elementPicker', { + what: 'elementPickerEprom', + lastNetFilterSession, + lastNetFilterHostname, + lastNetFilterUnion, + }); +}; + +/******************************************************************************/ + +// Extract the best possible net filter, i.e. as specific as possible. + +const netFilterFromElement = function(elem) { + if ( elem === null ) { return 0; } + if ( elem.nodeType !== 1 ) { return 0; } + const urls = resourceURLsFromElement(elem); + if ( urls.length === 0 ) { return 0; } + + if ( candidateElements.indexOf(elem) === -1 ) { + candidateElements.push(elem); + } + + const candidates = netFilterCandidates; + const len = candidates.length; + + for ( let i = 0; i < urls.length; i++ ) { + urls[i] = urls[i].replace(/^https?:\/\//, ''); + } + const pattern = mergeStrings(urls); + + + if ( bestCandidateFilter === null && elem.matches('html,body') === false ) { + bestCandidateFilter = { + type: 'net', + filters: candidates, + slot: candidates.length + }; + } + + candidates.push(`||${pattern}`); + + // Suggest a less narrow filter if possible + const pos = pattern.indexOf('?'); + if ( pos !== -1 ) { + candidates.push(`||${pattern.slice(0, pos)}`); + } + + // Suggest a filter which is a result of combining more than one URL. + netFilterFromUnion(pattern, candidates); + + return candidates.length - len; +}; + +const netFilter1stSources = { + 'audio': 'src', + 'embed': 'src', + 'iframe': 'src', + 'img': 'src', + 'image': 'href', + 'object': 'data', + 'source': 'src', + 'video': 'src' +}; + +const filterTypes = { + 'audio': 'media', + 'embed': 'object', + 'iframe': 'subdocument', + 'img': 'image', + 'object': 'object', + 'video': 'media', +}; + +/******************************************************************************/ + +// Extract the best possible cosmetic filter, i.e. as specific as possible. + +// https://github.com/gorhill/uBlock/issues/1725 +// Also take into account the `src` attribute for `img` elements -- and limit +// the value to the 1024 first characters. + +const cosmeticFilterFromElement = function(elem) { + if ( elem === null ) { return 0; } + if ( elem.nodeType !== 1 ) { return 0; } + if ( noCosmeticFiltering ) { return 0; } + + if ( candidateElements.indexOf(elem) === -1 ) { + candidateElements.push(elem); + } + + let selector = ''; + + // Id + let v = typeof elem.id === 'string' && CSS.escape(elem.id); + if ( v ) { + selector = '#' + v; + } + + // Class(es) + v = elem.classList; + if ( v ) { + let i = v.length || 0; + while ( i-- ) { + selector += '.' + CSS.escape(v.item(i)); + } + } + + // Tag name + const tagName = CSS.escape(elem.localName); + + // Use attributes if still no selector found. + // https://github.com/gorhill/uBlock/issues/1901 + // Trim attribute value, this may help in case of malformed HTML. + // + // https://github.com/uBlockOrigin/uBlock-issues/issues/1923 + // Escape unescaped `"` in attribute values + if ( selector === '' ) { + let attributes = [], attr; + switch ( tagName ) { + case 'a': + v = elem.getAttribute('href'); + if ( v ) { + v = v.trim().replace(/\?.*$/, ''); + if ( v.length ) { + attributes.push({ k: 'href', v: v }); + } + } + break; + case 'iframe': + case 'img': + v = elem.getAttribute('src'); + if ( v && v.length !== 0 ) { + v = v.trim(); + if ( v.startsWith('data:') ) { + let pos = v.indexOf(','); + if ( pos !== -1 ) { + v = v.slice(0, pos + 1); + } + } else if ( v.startsWith('blob:') ) { + v = new URL(v.slice(5)); + v.pathname = ''; + v = 'blob:' + v.href; + } + attributes.push({ k: 'src', v: v.slice(0, 256) }); + break; + } + v = elem.getAttribute('alt'); + if ( v && v.length !== 0 ) { + attributes.push({ k: 'alt', v: v }); + break; + } + break; + default: + break; + } + while ( (attr = attributes.pop()) ) { + if ( attr.v.length === 0 ) { continue; } + const w = attr.v.replace(/([^\\])"/g, '$1\\"'); + v = elem.getAttribute(attr.k); + if ( attr.v === v ) { + selector += `[${attr.k}="${w}"]`; + } else if ( v.startsWith(attr.v) ) { + selector += `[${attr.k}^="${w}"]`; + } else { + selector += `[${attr.k}*="${w}"]`; + } + } + } + + // https://github.com/uBlockOrigin/uBlock-issues/issues/17 + // If selector is ambiguous at this point, add the element name to + // further narrow it down. + const parentNode = elem.parentNode; + if ( + selector === '' || + safeQuerySelectorAll(parentNode, `:scope > ${selector}`).length > 1 + ) { + selector = tagName + selector; + } + + // https://github.com/chrisaljoudi/uBlock/issues/637 + // If the selector is still ambiguous at this point, further narrow using + // `nth-of-type`. It is preferable to use `nth-of-type` as opposed to + // `nth-child`, as `nth-of-type` is less volatile. + if ( safeQuerySelectorAll(parentNode, `:scope > ${selector}`).length > 1 ) { + let i = 1; + while ( elem.previousSibling !== null ) { + elem = elem.previousSibling; + if ( + typeof elem.localName === 'string' && + elem.localName === tagName + ) { + i++; + } + } + selector += `:nth-of-type(${i})`; + } + + if ( bestCandidateFilter === null ) { + bestCandidateFilter = { + type: 'cosmetic', + filters: cosmeticFilterCandidates, + slot: cosmeticFilterCandidates.length + }; + } + + cosmeticFilterCandidates.push(`##${selector}`); + + return 1; +}; + +/******************************************************************************/ + +const filtersFrom = function(x, y) { + bestCandidateFilter = null; + netFilterCandidates.length = 0; + cosmeticFilterCandidates.length = 0; + candidateElements.length = 0; + + // We need at least one element. + let first = null; + if ( typeof x === 'number' ) { + first = elementFromPoint(x, y); + } else if ( x instanceof HTMLElement ) { + first = x; + x = undefined; + } + + // https://github.com/gorhill/uBlock/issues/1545 + // Network filter candidates from all other elements found at [x,y]. + // https://www.reddit.com/r/uBlockOrigin/comments/qmjk36/ + // Extract network candidates first. + if ( typeof x === 'number' ) { + const magicAttr = `${pickerUniqueId}-clickblind`; + pickerFrame.setAttribute(magicAttr, ''); + const elems = document.elementsFromPoint(x, y); + pickerFrame.removeAttribute(magicAttr); + for ( const elem of elems ) { + netFilterFromElement(elem); + } + } else if ( first !== null ) { + netFilterFromElement(first); + } + + // Cosmetic filter candidates from ancestors. + // https://github.com/gorhill/uBlock/issues/2519 + // https://github.com/uBlockOrigin/uBlock-issues/issues/17 + // Prepend `body` if full selector is ambiguous. + let elem = first; + while ( elem && elem !== document.body ) { + cosmeticFilterFromElement(elem); + elem = elem.parentNode; + } + // The body tag is needed as anchor only when the immediate child + // uses `nth-of-type`. + let i = cosmeticFilterCandidates.length; + if ( i !== 0 ) { + const selector = cosmeticFilterCandidates[i-1].slice(2); + if ( safeQuerySelectorAll(document.body, selector).length > 1 ) { + cosmeticFilterCandidates.push('##body'); + } + } + + // https://github.com/gorhill/uBlock/commit/ebaa8a8bb28aef043a68c99965fe6c128a3fe5e4#commitcomment-63818019 + // If still no best candidate, just use whatever is available in network + // filter candidates -- which may have been previously skipped in favor + // of cosmetic filters. + if ( bestCandidateFilter === null && netFilterCandidates.length !== 0 ) { + bestCandidateFilter = { + type: 'net', + filters: netFilterCandidates, + slot: 0 + }; + } + + return netFilterCandidates.length + cosmeticFilterCandidates.length; +}; + +/******************************************************************************* + + filterToDOMInterface.queryAll + @desc Look-up all the HTML elements matching the filter passed in + argument. + @param string, a cosmetic or network filter. + @param function, called once all items matching the filter have been + collected. + @return array, or undefined if the filter is invalid. + + filterToDOMInterface.preview + @desc Apply/unapply filter to the DOM. + @param string, a cosmetic of network filter, or literal false to remove + the effects of the filter on the DOM. + @return undefined. + + TODO: need to be revised once I implement chained cosmetic operators. + +*/ + +const filterToDOMInterface = (( ) => { + const reHnAnchorPrefix = '^[\\w-]+://(?:[^/?#]+\\.)?'; + const reCaret = '(?:[^%.0-9a-z_-]|$)'; + const rePseudoElements = /:(?::?after|:?before|:[a-z-]+)$/; + + // Net filters: we need to lookup manually -- translating into a foolproof + // CSS selector is just not possible. + // + // https://github.com/chrisaljoudi/uBlock/issues/945 + // Transform into a regular expression, this allows the user to + // edit and insert wildcard(s) into the proposed filter. + // https://www.reddit.com/r/uBlockOrigin/comments/c5do7w/ + // Better handling of pure hostname filters. Also, discard single + // alphanumeric character filters. + const fromNetworkFilter = function(filter) { + const out = []; + if ( /^[0-9a-z]$/i.test(filter) ) { return out; } + let reStr = ''; + if ( + filter.length > 2 && + filter.startsWith('/') && + filter.endsWith('/') + ) { + reStr = filter.slice(1, -1); + } else if ( /^\w[\w.-]*[a-z]$/i.test(filter) ) { + reStr = reHnAnchorPrefix + + filter.toLowerCase().replace(/\./g, '\\.') + + reCaret; + } else { + let rePrefix = '', reSuffix = ''; + if ( filter.startsWith('||') ) { + rePrefix = reHnAnchorPrefix; + filter = filter.slice(2); + } else if ( filter.startsWith('|') ) { + rePrefix = '^'; + filter = filter.slice(1); + } + if ( filter.endsWith('|') ) { + reSuffix = '$'; + filter = filter.slice(0, -1); + } + reStr = rePrefix + + filter.replace(/[.+?${}()|[\]\\]/g, '\\$&') + .replace(/\*+/g, '.*') + .replace(/\^/g, reCaret) + + reSuffix; + } + let reFilter = null; + try { + reFilter = new RegExp(reStr, 'i'); + } + catch (e) { + return out; + } + + // Lookup by tag names. + // https://github.com/uBlockOrigin/uBlock-issues/issues/2260 + // Maybe get to the actual URL indirectly. + const elems = document.querySelectorAll( + Object.keys(netFilter1stSources).join() + ); + for ( const elem of elems ) { + const srcProp = netFilter1stSources[elem.localName]; + let src = elem[srcProp]; + if ( src instanceof SVGAnimatedString ) { + src = src.baseVal; + } + if ( + typeof src === 'string' && + reFilter.test(src) || + typeof elem.currentSrc === 'string' && + reFilter.test(elem.currentSrc) + ) { + out.push({ + elem, + src: srcProp, + opt: filterTypes[elem.localName], + style: vAPI.hideStyle, + }); + } + } + + // Find matching background image in current set of candidate elements. + for ( const elem of candidateElements ) { + if ( reFilter.test(backgroundImageURLFromElement(elem)) ) { + out.push({ + elem, + bg: true, + opt: 'image', + style: hideBackgroundStyle, + }); + } + } + + return out; + }; + + // Cosmetic filters: these are straight CSS selectors. + // + // https://github.com/uBlockOrigin/uBlock-issues/issues/389 + // Test filter using comma-separated list to better detect invalid CSS + // selectors. + // + // https://github.com/gorhill/uBlock/issues/2515 + // Remove trailing pseudo-element when querying. + const fromPlainCosmeticFilter = function(raw) { + let elems; + try { + document.documentElement.matches(`${raw},\na`); + elems = document.querySelectorAll( + raw.replace(rePseudoElements, '') + ); + } + catch (e) { + return; + } + const out = []; + for ( const elem of elems ) { + if ( elem === pickerFrame ) { continue; } + out.push({ elem, raw, style: vAPI.hideStyle }); + } + return out; + }; + + // https://github.com/gorhill/uBlock/issues/1772 + // Handle procedural cosmetic filters. + // + // https://github.com/gorhill/uBlock/issues/2515 + // Remove trailing pseudo-element when querying. + const fromCompiledCosmeticFilter = function(raw) { + if ( noCosmeticFiltering ) { return; } + if ( typeof raw !== 'string' ) { return; } + let elems, style; + try { + const o = JSON.parse(raw); + elems = vAPI.domFilterer.createProceduralFilter(o).exec(); + switch ( o.action && o.action[0] || '' ) { + case '': + case 'remove': + style = vAPI.hideStyle; + break; + case 'style': + style = o.action[1]; + break; + default: + break; + } + } catch(ex) { + return; + } + if ( !elems ) { return; } + const out = []; + for ( const elem of elems ) { + out.push({ elem, raw, style }); + } + return out; + }; + + vAPI.epickerStyleProxies = vAPI.epickerStyleProxies || new Map(); + + let lastFilter; + let lastResultset; + let previewing = false; + + const queryAll = function(details) { + let { filter, compiled } = details; + filter = filter.trim(); + if ( filter === lastFilter ) { return lastResultset; } + unapply(); + if ( filter === '' || filter === '!' ) { + lastFilter = ''; + lastResultset = undefined; + return; + } + lastFilter = filter; + if ( reCosmeticAnchor.test(filter) === false ) { + lastResultset = fromNetworkFilter(filter); + if ( previewing ) { apply(); } + return lastResultset; + } + lastResultset = fromPlainCosmeticFilter(compiled); + if ( lastResultset ) { + if ( previewing ) { apply(); } + return lastResultset; + } + // Procedural cosmetic filter + lastResultset = fromCompiledCosmeticFilter(compiled); + if ( previewing ) { apply(); } + return lastResultset; + }; + + const apply = function() { + unapply(); + if ( Array.isArray(lastResultset) === false ) { return; } + const rootElem = document.documentElement; + for ( const { elem, style } of lastResultset ) { + if ( elem === pickerFrame ) { continue; } + if ( style === undefined ) { continue; } + if ( elem === rootElem && style === vAPI.hideStyle ) { continue; } + let styleToken = vAPI.epickerStyleProxies.get(style); + if ( styleToken === undefined ) { + styleToken = vAPI.randomToken(); + vAPI.epickerStyleProxies.set(style, styleToken); + vAPI.userStylesheet.add(`[${styleToken}]\n{${style}}`, true); + } + elem.setAttribute(styleToken, ''); + } + }; + + const unapply = function() { + for ( const styleToken of vAPI.epickerStyleProxies.values() ) { + for ( const elem of document.querySelectorAll(`[${styleToken}]`) ) { + elem.removeAttribute(styleToken); + } + } + }; + + // https://www.reddit.com/r/uBlockOrigin/comments/c62irc/ + // Support injecting the cosmetic filters into the DOM filterer + // immediately rather than wait for the next page load. + const preview = function(state, permanent = false) { + previewing = state !== false; + if ( previewing === false ) { + return unapply(); + } + if ( Array.isArray(lastResultset) === false ) { return; } + if ( permanent === false || reCosmeticAnchor.test(lastFilter) === false ) { + return apply(); + } + if ( noCosmeticFiltering ) { return; } + const cssSelectors = new Set(); + const proceduralSelectors = new Set(); + for ( const { raw } of lastResultset ) { + if ( raw.startsWith('{') ) { + proceduralSelectors.add(raw); + } else { + cssSelectors.add(raw); + } + } + if ( cssSelectors.size !== 0 ) { + vAPI.domFilterer.addCSS( + `${Array.from(cssSelectors).join('\n')}\n{${vAPI.hideStyle}}`, + { mustInject: true } + ); + } + if ( proceduralSelectors.size !== 0 ) { + vAPI.domFilterer.addProceduralSelectors( + Array.from(proceduralSelectors) + ); + } + }; + + return { preview, queryAll }; +})(); + +/******************************************************************************/ + +const onOptimizeCandidates = function(details) { + const { candidates } = details; + const results = []; + for ( const paths of candidates ) { + let count = Number.MAX_SAFE_INTEGER; + let selector = ''; + for ( let i = 0, n = paths.length; i < n; i++ ) { + const s = paths.slice(n - i - 1).join(''); + const elems = document.querySelectorAll(s); + if ( elems.length < count ) { + selector = s; + count = elems.length; + } + } + results.push({ selector: `##${selector}`, count }); + } + // Sort by most match count and shortest selector to least match count and + // longest selector. + results.sort((a, b) => { + const r = b.count - a.count; + if ( r !== 0 ) { return r; } + return a.selector.length - b.selector.length; + }); + pickerFramePort.postMessage({ + what: 'candidatesOptimized', + candidates: results.map(a => a.selector), + slot: details.slot, + }); +}; + +/******************************************************************************/ + +const showDialog = function(options) { + pickerFramePort.postMessage({ + what: 'showDialog', + url: self.location.href, + netFilters: netFilterCandidates, + cosmeticFilters: cosmeticFilterCandidates, + filter: bestCandidateFilter, + options, + }); +}; + +/******************************************************************************/ + +const elementFromPoint = (( ) => { + let lastX, lastY; + + return (x, y) => { + if ( x !== undefined ) { + lastX = x; lastY = y; + } else if ( lastX !== undefined ) { + x = lastX; y = lastY; + } else { + return null; + } + if ( !pickerFrame ) { return null; } + const magicAttr = `${pickerUniqueId}-clickblind`; + pickerFrame.setAttribute(magicAttr, ''); + let elem = document.elementFromPoint(x, y); + if ( + elem === null || /* to skip following tests */ + elem === document.body || + elem === document.documentElement || ( + pickerBootArgs.zap !== true && + noCosmeticFiltering && + resourceURLsFromElement(elem).length === 0 + ) + ) { + elem = null; + } + // https://github.com/uBlockOrigin/uBlock-issues/issues/380 + pickerFrame.removeAttribute(magicAttr); + return elem; + }; +})(); + +/******************************************************************************/ + +const highlightElementAtPoint = function(mx, my) { + const elem = elementFromPoint(mx, my); + highlightElements(elem ? [ elem ] : []); +}; + +/******************************************************************************/ + +const filterElementAtPoint = function(mx, my, broad) { + if ( filtersFrom(mx, my) === 0 ) { return; } + showDialog({ broad }); +}; + +/******************************************************************************/ + +// https://www.reddit.com/r/uBlockOrigin/comments/bktxtb/scrolling_doesnt_work/emn901o +// Override 'fixed' position property on body element if present. + +// With touch-driven devices, first highlight the element and remove only +// when tapping again the highlighted area. + +const zapElementAtPoint = function(mx, my, options) { + if ( options.highlight ) { + const elem = elementFromPoint(mx, my); + if ( elem ) { + highlightElements([ elem ]); + } + return; + } + + let elemToRemove = targetElements.length !== 0 && targetElements[0] || null; + if ( elemToRemove === null && mx !== undefined ) { + elemToRemove = elementFromPoint(mx, my); + } + + if ( elemToRemove instanceof Element === false ) { return; } + + const getStyleValue = (elem, prop) => { + const style = window.getComputedStyle(elem); + return style ? style[prop] : ''; + }; + + // Heuristic to detect scroll-locking: remove such lock when detected. + let maybeScrollLocked = elemToRemove.shadowRoot instanceof DocumentFragment; + if ( maybeScrollLocked === false ) { + let elem = elemToRemove; + do { + maybeScrollLocked = + parseInt(getStyleValue(elem, 'zIndex'), 10) >= 1000 || + getStyleValue(elem, 'position') === 'fixed'; + elem = elem.parentElement; + } while ( elem !== null && maybeScrollLocked === false ); + } + if ( maybeScrollLocked ) { + const doc = document; + if ( getStyleValue(doc.body, 'overflowY') === 'hidden' ) { + doc.body.style.setProperty('overflow', 'auto', 'important'); + } + if ( getStyleValue(doc.body, 'position') === 'fixed' ) { + doc.body.style.setProperty('position', 'initial', 'important'); + } + if ( getStyleValue(doc.documentElement, 'position') === 'fixed' ) { + doc.documentElement.style.setProperty('position', 'initial', 'important'); + } + if ( getStyleValue(doc.documentElement, 'overflowY') === 'hidden' ) { + doc.documentElement.style.setProperty('overflow', 'auto', 'important'); + } + } + elemToRemove.remove(); + highlightElementAtPoint(mx, my); +}; + +/******************************************************************************/ + +const onKeyPressed = function(ev) { + // Delete + if ( + (ev.key === 'Delete' || ev.key === 'Backspace') && + pickerBootArgs.zap + ) { + ev.stopPropagation(); + ev.preventDefault(); + zapElementAtPoint(); + return; + } + // Esc + if ( ev.key === 'Escape' || ev.which === 27 ) { + ev.stopPropagation(); + ev.preventDefault(); + filterToDOMInterface.preview(false); + quitPicker(); + return; + } +}; + +/******************************************************************************/ + +// https://github.com/chrisaljoudi/uBlock/issues/190 +// May need to dynamically adjust the height of the overlay + new position +// of highlighted elements. + +const onViewportChanged = function() { + highlightElements(targetElements, true); +}; + +/******************************************************************************/ + +// Auto-select a specific target, if any, and if possible + +const startPicker = function() { + pickerFrame.focus(); + + self.addEventListener('scroll', onViewportChanged, { passive: true }); + self.addEventListener('resize', onViewportChanged, { passive: true }); + self.addEventListener('keydown', onKeyPressed, true); + + // Try using mouse position + if ( + pickerBootArgs.mouse && + vAPI.mouseClick instanceof Object && + typeof vAPI.mouseClick.x === 'number' && + vAPI.mouseClick.x > 0 + ) { + if ( filtersFrom(vAPI.mouseClick.x, vAPI.mouseClick.y) !== 0 ) { + return showDialog(); + } + } + + // No mouse position available, use suggested target + const target = pickerBootArgs.target || ''; + const pos = target.indexOf('\t'); + if ( pos === -1 ) { return; } + + const srcAttrMap = { + 'a': 'href', + 'audio': 'src', + 'embed': 'src', + 'iframe': 'src', + 'img': 'src', + 'video': 'src', + }; + const tagName = target.slice(0, pos); + const url = target.slice(pos + 1); + const attr = srcAttrMap[tagName]; + if ( attr === undefined ) { return; } + const elems = document.getElementsByTagName(tagName); + for ( const elem of elems ) { + if ( elem === pickerFrame ) { continue; } + const srcs = resourceURLsFromElement(elem); + if ( + (srcs.length !== 0 && srcs.includes(url) === false) || + (srcs.length === 0 && url !== 'about:blank') + ) { + continue; + } + filtersFrom(elem); + if ( + netFilterCandidates.length !== 0 || + cosmeticFilterCandidates.length !== 0 + ) { + if ( pickerBootArgs.mouse !== true ) { + elem.scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }); + } + showDialog({ broad: true }); + } + return; + } + + // A target was specified, but it wasn't found: abort. + quitPicker(); +}; + +/******************************************************************************/ + +// Let's have the element picker code flushed from memory when no longer +// in use: to ensure this, release all local references. + +const quitPicker = function() { + self.removeEventListener('scroll', onViewportChanged, { passive: true }); + self.removeEventListener('resize', onViewportChanged, { passive: true }); + self.removeEventListener('keydown', onKeyPressed, true); + vAPI.shutdown.remove(quitPicker); + if ( pickerFramePort ) { + pickerFramePort.close(); + pickerFramePort = null; + } + if ( pickerFrame ) { + pickerFrame.remove(); + pickerFrame = null; + } + vAPI.userStylesheet.remove(pickerCSS); + vAPI.userStylesheet.apply(); + vAPI.pickerFrame = false; + self.focus(); +}; + +vAPI.shutdown.add(quitPicker); + +/******************************************************************************/ + +const onDialogMessage = function(msg) { + switch ( msg.what ) { + case 'start': + startPicker(); + if ( pickerFramePort === null ) { break; } + if ( targetElements.length === 0 ) { + highlightElements([], true); + } + break; + case 'optimizeCandidates': + onOptimizeCandidates(msg); + break; + case 'dialogCreate': + filterToDOMInterface.queryAll(msg); + filterToDOMInterface.preview(true, true); + quitPicker(); + break; + case 'dialogSetFilter': { + const resultset = filterToDOMInterface.queryAll(msg) || []; + highlightElements(resultset.map(a => a.elem), true); + if ( msg.filter === '!' ) { break; } + pickerFramePort.postMessage({ + what: 'resultsetDetails', + count: resultset.length, + opt: resultset.length !== 0 ? resultset[0].opt : undefined, + }); + break; + } + case 'quitPicker': + filterToDOMInterface.preview(false); + quitPicker(); + break; + case 'highlightElementAtPoint': + highlightElementAtPoint(msg.mx, msg.my); + break; + case 'unhighlight': + highlightElements([]); + break; + case 'filterElementAtPoint': + filterElementAtPoint(msg.mx, msg.my, msg.broad); + break; + case 'zapElementAtPoint': + zapElementAtPoint(msg.mx, msg.my, msg.options); + if ( msg.options.highlight !== true && msg.options.stay !== true ) { + quitPicker(); + } + break; + case 'togglePreview': + filterToDOMInterface.preview(msg.state); + if ( msg.state === false ) { + highlightElements(targetElements, true); + } + break; + default: + break; + } +}; + +/******************************************************************************/ + +// epicker-ui.html will be injected in the page through an iframe, and +// is a sandboxed so as to prevent the page from interfering with its +// content and behavior. +// +// The purpose of epicker.js is to: +// - Install the element picker UI, and wait for the component to establish +// a direct communication channel. +// - Lookup candidate filters from elements at a specific position. +// - Highlight element(s) at a specific position or according to whether +// they match candidate filters; +// - Preview the result of applying a candidate filter; +// +// When the element picker is installed on a page, the only change the page +// sees is an iframe with a random attribute. The page can't see the content +// of the iframe, and cannot interfere with its style properties. However the +// page can remove the iframe. + +// The DOM filterer will not be present when cosmetic filtering is disabled. +const noCosmeticFiltering = + vAPI.domFilterer instanceof Object === false || + vAPI.noSpecificCosmeticFiltering === true; + +// https://github.com/gorhill/uBlock/issues/1529 +// In addition to inline styles, harden the element picker styles by using +// dedicated CSS rules. +const pickerCSSStyle = [ + 'background: transparent', + 'border: 0', + 'border-radius: 0', + 'box-shadow: none', + 'color-scheme: light dark', + 'display: block', + 'filter: none', + 'height: 100vh', + 'left: 0', + 'margin: 0', + 'max-height: none', + 'max-width: none', + 'min-height: unset', + 'min-width: unset', + 'opacity: 1', + 'outline: 0', + 'padding: 0', + 'pointer-events: auto', + 'position: fixed', + 'top: 0', + 'transform: none', + 'visibility: hidden', + 'width: 100%', + 'z-index: 2147483647', + '' +].join(' !important;\n'); + + +const pickerCSS = ` +:root > [${pickerUniqueId}] { + ${pickerCSSStyle} +} +:root > [${pickerUniqueId}-loaded] { + visibility: visible !important; +} +:root [${pickerUniqueId}-clickblind] { + pointer-events: none !important; +} +`; + +vAPI.userStylesheet.add(pickerCSS); +vAPI.userStylesheet.apply(); + +let pickerBootArgs; +let pickerFramePort = null; + +const bootstrap = async ( ) => { + pickerBootArgs = await vAPI.messaging.send('elementPicker', { + what: 'elementPickerArguments', + }); + if ( typeof pickerBootArgs !== 'object' ) { return; } + if ( pickerBootArgs === null ) { return; } + // Restore net filter union data if origin is the same. + const eprom = pickerBootArgs.eprom || null; + if ( eprom !== null && eprom.lastNetFilterSession === lastNetFilterSession ) { + lastNetFilterHostname = eprom.lastNetFilterHostname || ''; + lastNetFilterUnion = eprom.lastNetFilterUnion || ''; + } + const url = new URL(pickerBootArgs.pickerURL); + if ( pickerBootArgs.zap ) { + url.searchParams.set('zap', '1'); + } + return new Promise(resolve => { + const iframe = document.createElement('iframe'); + iframe.setAttribute(pickerUniqueId, ''); + document.documentElement.append(iframe); + iframe.addEventListener('load', ( ) => { + iframe.setAttribute(`${pickerUniqueId}-loaded`, ''); + const channel = new MessageChannel(); + pickerFramePort = channel.port1; + pickerFramePort.onmessage = ev => { + onDialogMessage(ev.data || {}); + }; + pickerFramePort.onmessageerror = ( ) => { + quitPicker(); + }; + iframe.contentWindow.postMessage( + { what: 'epickerStart' }, + url.href, + [ channel.port2 ] + ); + resolve(iframe); + }, { once: true }); + iframe.contentWindow.location = url.href; + }); +}; + +let pickerFrame = await bootstrap(); +if ( Boolean(pickerFrame) === false ) { + quitPicker(); +} + +/******************************************************************************/ + +})(); + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/load-3p-css.js b/src/js/scriptlets/load-3p-css.js new file mode 100644 index 0000000..bb7d542 --- /dev/null +++ b/src/js/scriptlets/load-3p-css.js @@ -0,0 +1,67 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2020-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 +*/ + +'use strict'; + +/******************************************************************************/ + +(( ) => { + if ( typeof vAPI !== 'object' ) { return; } + + if ( vAPI.dynamicReloadToken === undefined ) { + vAPI.dynamicReloadToken = vAPI.randomToken(); + } + + for ( const sheet of Array.from(document.styleSheets) ) { + let loaded = false; + try { + loaded = sheet.rules.length !== 0; + } catch(ex) { + } + if ( loaded ) { continue; } + const link = sheet.ownerNode || null; + if ( link === null || link.localName !== 'link' ) { continue; } + if ( link.hasAttribute(vAPI.dynamicReloadToken) ) { continue; } + const clone = link.cloneNode(true); + clone.setAttribute(vAPI.dynamicReloadToken, ''); + link.replaceWith(clone); + } +})(); + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/load-large-media-all.js b/src/js/scriptlets/load-large-media-all.js new file mode 100644 index 0000000..a44539e --- /dev/null +++ b/src/js/scriptlets/load-large-media-all.js @@ -0,0 +1,62 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-2018 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 +*/ + +'use strict'; + +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +if ( + typeof vAPI !== 'object' || + vAPI.loadAllLargeMedia instanceof Function === false +) { + return; +} + +vAPI.loadAllLargeMedia(); +vAPI.loadAllLargeMedia = undefined; + +/******************************************************************************/ + +})(); + + + + + + + + +/******************************************************************************* + + DO NOT: + - Remove the following code + - Add code beyond the following code + Reason: + - https://github.com/gorhill/uBlock/pull/3721 + - uBO never uses the return value from injected content scripts + +**/ + +void 0; diff --git a/src/js/scriptlets/load-large-media-interactive.js b/src/js/scriptlets/load-large-media-interactive.js new file mode 100644 index 0000000..57198e4 --- /dev/null +++ b/src/js/scriptlets/load-large-media-interactive.js @@ -0,0 +1,299 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2015-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 +*/ + +'use strict'; + +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +// This can happen +if ( typeof vAPI !== 'object' || vAPI.loadAllLargeMedia instanceof Function ) { + return; +} + +/******************************************************************************/ + +const largeMediaElementAttribute = 'data-' + vAPI.sessionId; +const largeMediaElementSelector = + ':root audio[' + largeMediaElementAttribute + '],\n' + + ':root img[' + largeMediaElementAttribute + '],\n' + + ':root picture[' + largeMediaElementAttribute + '],\n' + + ':root video[' + largeMediaElementAttribute + ']'; + +/******************************************************************************/ + +const isMediaElement = function(elem) { + return /^(?:audio|img|picture|video)$/.test(elem.localName); +}; + +/******************************************************************************/ + +const mediaNotLoaded = function(elem) { + switch ( elem.localName ) { + case 'audio': + case 'video': { + const src = elem.src || ''; + if ( src.startsWith('blob:') ) { + elem.autoplay = false; + elem.pause(); + } + return elem.readyState === 0 || elem.error !== null; + } + case 'img': { + if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) { + break; + } + const style = window.getComputedStyle(elem); + // For some reason, style can be null with Pale Moon. + return style !== null ? + style.getPropertyValue('display') !== 'none' : + elem.offsetHeight !== 0 && elem.offsetWidth !== 0; + } + default: + break; + } + return false; +}; + +/******************************************************************************/ + +// For all media resources which have failed to load, trigger a reload. + +//
+ +
+
+
+
+ + + + + +
+
+
+
    +
    +
    +
    +
    +
    + + + + + + + + + angle-up +
    +
    +
    + +
    css/fontimagemediascript
    +
    xhrframedomscriptletother
    +
    +
    +
    tabless
    +
    getheadpost
    +
    + +
    csppermissionsredirect
    +
    removeparamurltransform
    +
    +
    + +
    +
    +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    00:00:00 ** 3,3optionsinline-script 
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + diff --git a/src/no-dashboard.html b/src/no-dashboard.html new file mode 100644 index 0000000..35b27c9 --- /dev/null +++ b/src/no-dashboard.html @@ -0,0 +1,27 @@ + + + + + +uBlock — About + + + + + + + +
    + Your administrator removed the ability to access the dashboard +
    + + + + + + + + + + + diff --git a/src/popup-fenix.html b/src/popup-fenix.html new file mode 100644 index 0000000..9abf3dd --- /dev/null +++ b/src/popup-fenix.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + +
    +
    +
    +
    ­
    +
    +
    + lock + eraser +
    +
    + + + + + + + +
    +
    + refresh +
    +
    +
    +
    + ph-popups + film + eye-slash + ph-readermode-text-size + code +
    +
    +
    + __ + __ + __ +
    +
    + bolt + eye-dropper + comment-alt + list-alt + cogs +
    +
    + +
    +
    +
    + +
    +
    +
    + + angle-up + + + angle-up + +
    +
    +
    +
    filter
    ___
    ___
    +
    _
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + diff --git a/src/settings.html b/src/settings.html new file mode 100644 index 0000000..92dfca3 --- /dev/null +++ b/src/settings.html @@ -0,0 +1,98 @@ + + + + + +uBlock — Settings + + + + + + + + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +   + + + +
    +
    +
    +
    +
    + +
    +
    +
    + + +
    +
    +
    +
    +
    + + +
    +
    + + + +
    +
    + + + + + + + + + + + + + + + + diff --git a/src/support.html b/src/support.html new file mode 100644 index 0000000..1232942 --- /dev/null +++ b/src/support.html @@ -0,0 +1,130 @@ + + + + + +uBlock Origin — Support + + + + + + + + + + + + + + +
    +
    +

    +
    +
    +

    +

    + +
    +
    +
    +
    +

    +
    +
    +

    +

    + +
    +
    +
    +
    +

    +
    +
    +

    +

    +

    +

    + +
    +
    +
    +
    +

    +
    +
    +

    +

    + +
    +
    +
    +
    +

    +

    +
    +
    +

    _

    + + _ +
    +
    +
    +

    + +
    +
    +
    +

    +
    + +

    +

    +
    + +

    +

    + +

    + +
    +
    +

    _ ▸

    +
    +
    +

    +

    +

    + + +

    +
    +
    + + + + + + + + + + + + + + + + diff --git a/src/web_accessible_resources/1x1.gif b/src/web_accessible_resources/1x1.gif new file mode 100644 index 0000000..e565824 Binary files /dev/null and b/src/web_accessible_resources/1x1.gif differ diff --git a/src/web_accessible_resources/2x2.png b/src/web_accessible_resources/2x2.png new file mode 100644 index 0000000..3639dc7 Binary files /dev/null and b/src/web_accessible_resources/2x2.png differ diff --git a/src/web_accessible_resources/32x32.png b/src/web_accessible_resources/32x32.png new file mode 100644 index 0000000..7bee0a0 Binary files /dev/null and b/src/web_accessible_resources/32x32.png differ diff --git a/src/web_accessible_resources/3x2.png b/src/web_accessible_resources/3x2.png new file mode 100644 index 0000000..a056d86 Binary files /dev/null and b/src/web_accessible_resources/3x2.png differ diff --git a/src/web_accessible_resources/README.txt b/src/web_accessible_resources/README.txt new file mode 100644 index 0000000..f9ab5c3 --- /dev/null +++ b/src/web_accessible_resources/README.txt @@ -0,0 +1,11 @@ +IMPORTANT + +Content of this folder cannot be accessed without the internal secret token +created for each request to any of the "web accessible resources". + +Any fetch operation made without uBlock Origin's internal secret will result +in failure. This means that despite the content of the folder here declared as +"web accessible resources", it still cannot be seen by the outside world. + +Only uBlock Origin knows the secret token at runtime and hence only +uBlock Origin can access the content of this folder. diff --git a/src/web_accessible_resources/amazon_ads.js b/src/web_accessible_resources/amazon_ads.js new file mode 100644 index 0000000..0b6e052 --- /dev/null +++ b/src/web_accessible_resources/amazon_ads.js @@ -0,0 +1,70 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + if ( amznads ) { + return; + } + var w = window; + var noopfn = function() { + ; + }.bind(); + var amznads = { + appendScriptTag: noopfn, + appendTargetingToAdServerUrl: noopfn, + appendTargetingToQueryString: noopfn, + clearTargetingFromGPTAsync: noopfn, + doAllTasks: noopfn, + doGetAdsAsync: noopfn, + doTask: noopfn, + detectIframeAndGetURL: noopfn, + getAds: noopfn, + getAdsAsync: noopfn, + getAdForSlot: noopfn, + getAdsCallback: noopfn, + getDisplayAds: noopfn, + getDisplayAdsAsync: noopfn, + getDisplayAdsCallback: noopfn, + getKeys: noopfn, + getReferrerURL: noopfn, + getScriptSource: noopfn, + getTargeting: noopfn, + getTokens: noopfn, + getValidMilliseconds: noopfn, + getVideoAds: noopfn, + getVideoAdsAsync: noopfn, + getVideoAdsCallback: noopfn, + handleCallBack: noopfn, + hasAds: noopfn, + renderAd: noopfn, + saveAds: noopfn, + setTargeting: noopfn, + setTargetingForGPTAsync: noopfn, + setTargetingForGPTSync: noopfn, + tryGetAdsAsync: noopfn, + updateAds: noopfn + }; + w.amznads = amznads; + w.amzn_ads = w.amzn_ads || noopfn; + w.aax_write = w.aax_write || noopfn; + w.aax_render_ad = w.aax_render_ad || noopfn; +})(); diff --git a/src/web_accessible_resources/amazon_apstag.js b/src/web_accessible_resources/amazon_apstag.js new file mode 100644 index 0000000..1ddd5a4 --- /dev/null +++ b/src/web_accessible_resources/amazon_apstag.js @@ -0,0 +1,62 @@ +/******************************************************************************* + + 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 +*/ + +// https://www.reddit.com/r/uBlockOrigin/comments/ghjqph/ +// https://github.com/NanoMeow/QuickReports/issues/3717 +// https://www.reddit.com/r/uBlockOrigin/comments/qyx7en/ + +// https://searchfox.org/mozilla-central/source/browser/extensions/webcompat/shims/apstag.js +// Import queue-related initialization code. + +(function() { + 'use strict'; + const w = window; + const noopfn = function() { + ; // jshint ignore:line + }.bind(); + const _Q = w.apstag && w.apstag._Q || []; + const apstag = { + _Q, + fetchBids: function(a, b) { + if ( typeof b === 'function' ) { + b([]); + } + }, + init: noopfn, + setDisplayBids: noopfn, + targetingKeys: noopfn, + }; + w.apstag = apstag; + _Q.push = function(prefix, args) { + try { + switch (prefix) { + case 'f': + apstag.fetchBids(...args); + break; + } + } catch (e) { + console.trace(e); + } + }; + for ( const cmd of _Q ) { + _Q.push(cmd); + } +})(); diff --git a/src/web_accessible_resources/ampproject_v0.js b/src/web_accessible_resources/ampproject_v0.js new file mode 100644 index 0000000..e822f9d --- /dev/null +++ b/src/web_accessible_resources/ampproject_v0.js @@ -0,0 +1,34 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const head = document.head; + if ( !head ) { return; } + const style = document.createElement('style'); + style.textContent = [ + 'body {', + ' animation: none !important;', + ' overflow: unset !important;', + '}' + ].join('\n'); + head.appendChild(style); +})(); diff --git a/src/web_accessible_resources/chartbeat.js b/src/web_accessible_resources/chartbeat.js new file mode 100644 index 0000000..76e7a29 --- /dev/null +++ b/src/web_accessible_resources/chartbeat.js @@ -0,0 +1,30 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + window.pSUPERFLY = { + activity: noopfn, + virtualPage: noopfn + }; +})(); diff --git a/src/web_accessible_resources/click2load.html b/src/web_accessible_resources/click2load.html new file mode 100644 index 0000000..7ec52b9 --- /dev/null +++ b/src/web_accessible_resources/click2load.html @@ -0,0 +1,28 @@ + + + + + +uBlock Origin Click-to-Load + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/web_accessible_resources/dom-inspector.html b/src/web_accessible_resources/dom-inspector.html new file mode 100644 index 0000000..d338610 --- /dev/null +++ b/src/web_accessible_resources/dom-inspector.html @@ -0,0 +1,25 @@ + + + + + + +uBlock Origin Inspector + + + + + + + + + + + + + + + + + + diff --git a/src/web_accessible_resources/doubleclick_instream_ad_status.js b/src/web_accessible_resources/doubleclick_instream_ad_status.js new file mode 100644 index 0000000..dfec48c --- /dev/null +++ b/src/web_accessible_resources/doubleclick_instream_ad_status.js @@ -0,0 +1 @@ +window.google_ad_status = 1; diff --git a/src/web_accessible_resources/empty b/src/web_accessible_resources/empty new file mode 100644 index 0000000..e69de29 diff --git a/src/web_accessible_resources/epicker-ui.html b/src/web_accessible_resources/epicker-ui.html new file mode 100644 index 0000000..bd92f50 --- /dev/null +++ b/src/web_accessible_resources/epicker-ui.html @@ -0,0 +1,75 @@ + + + + + + +uBlock Origin Element Picker + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/web_accessible_resources/fingerprint2.js b/src/web_accessible_resources/fingerprint2.js new file mode 100644 index 0000000..24a39b9 --- /dev/null +++ b/src/web_accessible_resources/fingerprint2.js @@ -0,0 +1,55 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + 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 +*/ + +// Reference: +// https://github.com/fingerprintjs/fingerprintjs/tree/v2 + +(function() { + 'use strict'; + const hex32 = len => { + return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + .toString(16) + .slice(-len) + .padStart(len, '0'); + }; + const browserId = `${hex32(8)}${hex32(8)}${hex32(8)}${hex32(8)}`; + const fp2 = function(){}; + fp2.get = function(opts, cb) { + if ( !cb ) { cb = opts; } + setTimeout(( ) => { cb([]); }, 1); + }; + fp2.getPromise = function() { + return Promise.resolve([]); + }; + fp2.getV18 = function() { + return browserId; + }; + fp2.x64hash128 = function() { + return browserId; + }; + fp2.prototype = { + get: function(opts, cb) { + if ( !cb ) { cb = opts; } + setTimeout(( ) => { cb(browserId, []); }, 1); + }, + }; + self.Fingerprint2 = fp2; +})(); diff --git a/src/web_accessible_resources/fingerprint3.js b/src/web_accessible_resources/fingerprint3.js new file mode 100644 index 0000000..1bf1529 --- /dev/null +++ b/src/web_accessible_resources/fingerprint3.js @@ -0,0 +1,45 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + 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 +*/ + +(function() { + 'use strict'; + const visitorId = (( ) => { + let id = ''; + for ( let i = 0; i < 8; i++ ) { + id += (Math.random() * 0x10000 + 0x1000 | 0).toString(16).slice(-4); + } + return id; + })(); + const FingerprintJS = class { + static hashComponents() { + return visitorId; + } + static load() { + return Promise.resolve(new FingerprintJS()); + } + get() { + return Promise.resolve({ + visitorId, + }); + } + }; + window.FingerprintJS = FingerprintJS; +})(); diff --git a/src/web_accessible_resources/google-analytics_analytics.js b/src/web_accessible_resources/google-analytics_analytics.js new file mode 100644 index 0000000..6fdf396 --- /dev/null +++ b/src/web_accessible_resources/google-analytics_analytics.js @@ -0,0 +1,110 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + // https://developers.google.com/analytics/devguides/collection/analyticsjs/ + const noopfn = function() { + }; + // + const Tracker = function() { + }; + const p = Tracker.prototype; + p.get = noopfn; + p.set = noopfn; + p.send = noopfn; + // + const w = window; + const gaName = w.GoogleAnalyticsObject || 'ga'; + const gaQueue = w[gaName]; + // https://github.com/uBlockOrigin/uAssets/pull/4115 + const ga = function() { + const len = arguments.length; + if ( len === 0 ) { return; } + const args = Array.from(arguments); + let fn; + let a = args[len-1]; + if ( a instanceof Object && a.hitCallback instanceof Function ) { + fn = a.hitCallback; + } else if ( a instanceof Function ) { + fn = ( ) => { a(ga.create()); }; + } else { + const pos = args.indexOf('hitCallback'); + if ( pos !== -1 && args[pos+1] instanceof Function ) { + fn = args[pos+1]; + } + } + if ( fn instanceof Function === false ) { return; } + try { + fn(); + } catch (ex) { + } + }; + ga.create = function() { + return new Tracker(); + }; + ga.getByName = function() { + return new Tracker(); + }; + ga.getAll = function() { + return [new Tracker()]; + }; + ga.remove = noopfn; + // https://github.com/uBlockOrigin/uAssets/issues/2107 + ga.loaded = true; + w[gaName] = ga; + // https://github.com/gorhill/uBlock/issues/3075 + const dl = w.dataLayer; + if ( dl instanceof Object ) { + if ( dl.hide instanceof Object && typeof dl.hide.end === 'function' ) { + dl.hide.end(); + dl.hide.end = ()=>{}; + } + if ( typeof dl.push === 'function' ) { + const doCallback = function(item) { + if ( item instanceof Object === false ) { return; } + if ( typeof item.eventCallback !== 'function' ) { return; } + setTimeout(item.eventCallback, 1); + item.eventCallback = ()=>{}; + }; + dl.push = new Proxy(dl.push, { + apply: function(target, thisArg, args) { + doCallback(args[0]); + return Reflect.apply(target, thisArg, args); + } + }); + if ( Array.isArray(dl) ) { + const q = dl.slice(); + for ( const item of q ) { + doCallback(item); + } + } + } + } + // empty ga queue + if ( gaQueue instanceof Function && Array.isArray(gaQueue.q) ) { + const q = gaQueue.q.slice(); + gaQueue.q.length = 0; + for ( const entry of q ) { + ga(...entry); + } + } +})(); diff --git a/src/web_accessible_resources/google-analytics_cx_api.js b/src/web_accessible_resources/google-analytics_cx_api.js new file mode 100644 index 0000000..9f63ebe --- /dev/null +++ b/src/web_accessible_resources/google-analytics_cx_api.js @@ -0,0 +1,36 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + window.cxApi = { + chooseVariation: function() { + return 0; + }, + getChosenVariation: noopfn, + setAllowHash: noopfn, + setChosenVariation: noopfn, + setCookiePath: noopfn, + setDomainName: noopfn + }; +})(); diff --git a/src/web_accessible_resources/google-analytics_ga.js b/src/web_accessible_resources/google-analytics_ga.js new file mode 100644 index 0000000..c969b38 --- /dev/null +++ b/src/web_accessible_resources/google-analytics_ga.js @@ -0,0 +1,130 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + // + const Gaq = function() { + }; + Gaq.prototype.Na = noopfn; + Gaq.prototype.O = noopfn; + Gaq.prototype.Sa = noopfn; + Gaq.prototype.Ta = noopfn; + Gaq.prototype.Va = noopfn; + Gaq.prototype._createAsyncTracker = noopfn; + Gaq.prototype._getAsyncTracker = noopfn; + Gaq.prototype._getPlugin = noopfn; + Gaq.prototype.push = function(a) { + if ( typeof a === 'function' ) { + a(); return; + } + if ( Array.isArray(a) === false ) { return; } + // https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiDomainDirectory#_gat.GA_Tracker_._link + // https://github.com/uBlockOrigin/uBlock-issues/issues/1807 + if ( + typeof a[0] === 'string' && + /(^|\.)_link$/.test(a[0]) && + typeof a[1] === 'string' + ) { + try { + window.location.assign(a[1]); + } catch(ex) { + } + } + // https://github.com/gorhill/uBlock/issues/2162 + if ( a[0] === '_set' && a[1] === 'hitCallback' && typeof a[2] === 'function' ) { + a[2](); + } + }; + // + const tracker = (function() { + const out = {}; + const api = [ + '_addIgnoredOrganic _addIgnoredRef _addItem _addOrganic', + '_addTrans _clearIgnoredOrganic _clearIgnoredRef _clearOrganic', + '_cookiePathCopy _deleteCustomVar _getName _setAccount', + '_getAccount _getClientInfo _getDetectFlash _getDetectTitle', + '_getLinkerUrl _getLocalGifPath _getServiceMode _getVersion', + '_getVisitorCustomVar _initData _linkByPost', + '_setAllowAnchor _setAllowHash _setAllowLinker _setCampContentKey', + '_setCampMediumKey _setCampNameKey _setCampNOKey _setCampSourceKey', + '_setCampTermKey _setCampaignCookieTimeout _setCampaignTrack _setClientInfo', + '_setCookiePath _setCookiePersistence _setCookieTimeout _setCustomVar', + '_setDetectFlash _setDetectTitle _setDomainName _setLocalGifPath', + '_setLocalRemoteServerMode _setLocalServerMode _setReferrerOverride _setRemoteServerMode', + '_setSampleRate _setSessionTimeout _setSiteSpeedSampleRate _setSessionCookieTimeout', + '_setVar _setVisitorCookieTimeout _trackEvent _trackPageLoadTime', + '_trackPageview _trackSocial _trackTiming _trackTrans', + '_visitCode' + ].join(' ').split(/\s+/); + for ( const method of api ) { + out[method] = noopfn; + } + out._getLinkerUrl = function(a) { + return a; + }; + // https://github.com/AdguardTeam/Scriptlets/issues/154 + out._link = function(a) { + if ( typeof a !== 'string' ) { return; } + try { + window.location.assign(a); + } catch(ex) { + } + }; + return out; + })(); + // + const Gat = function() { + }; + Gat.prototype._anonymizeIP = noopfn; + Gat.prototype._createTracker = noopfn; + Gat.prototype._forceSSL = noopfn; + Gat.prototype._getPlugin = noopfn; + Gat.prototype._getTracker = function() { + return tracker; + }; + Gat.prototype._getTrackerByName = function() { + return tracker; + }; + Gat.prototype._getTrackers = noopfn; + Gat.prototype.aa = noopfn; + Gat.prototype.ab = noopfn; + Gat.prototype.hb = noopfn; + Gat.prototype.la = noopfn; + Gat.prototype.oa = noopfn; + Gat.prototype.pa = noopfn; + Gat.prototype.u = noopfn; + const gat = new Gat(); + window._gat = gat; + // + const gaq = new Gaq(); + (function() { + const aa = window._gaq || []; + if ( Array.isArray(aa) ) { + while ( aa[0] ) { + gaq.push(aa.shift()); + } + } + })(); + window._gaq = gaq.qf = gaq; +})(); diff --git a/src/web_accessible_resources/google-analytics_inpage_linkid.js b/src/web_accessible_resources/google-analytics_inpage_linkid.js new file mode 100644 index 0000000..e893ca9 --- /dev/null +++ b/src/web_accessible_resources/google-analytics_inpage_linkid.js @@ -0,0 +1,28 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + window._gaq = window._gaq || { + push: function() { + } + }; +})(); diff --git a/src/web_accessible_resources/google-ima.js b/src/web_accessible_resources/google-ima.js new file mode 100644 index 0000000..4556516 --- /dev/null +++ b/src/web_accessible_resources/google-ima.js @@ -0,0 +1,855 @@ +/** + * + * Source below is based on Mozilla source code: + * https://searchfox.org/mozilla-central/rev/d317e93d9a59c9e4c06ada85fbff9f6a1ceaaad1/browser/extensions/webcompat/shims/google-ima.js + * + * Modifications to the original code below this comment: + * - Avoid JS syntax not supported by older browser versions + * - Add missing shim event + * - Modified to avoid jshint warnings as per uBO's config + * - Added `OmidVerificationVendor` to `ima` + * - Have `AdError.getInnerError()` return `null` + * - Have `AdDisplayContainer` constructor add DIV element to container + * - Added missing event dispatcher functionality + * - Corrected return type of `Ad.getUniversalAdIds()` + * - Corrected typo in `UniversalAdIdInfo.getAdIdValue()` method name + * - Corrected dispatch of LOAD event when preloading is enabled + * - Corrected dispatch of CONTENT_PAUSE/RESUME_REQUESTED events + * + * Related issue: + * - https://github.com/uBlockOrigin/uBlock-issues/issues/2158 + * +**/ + +'use strict'; + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Bug 1713690 - Shim Google Interactive Media Ads ima3.js + * + * Many sites use ima3.js for ad bidding and placement, often in conjunction + * with Google Publisher Tags, Prebid.js and/or other scripts. This shim + * provides a stubbed-out version of the API which helps work around related + * site breakage, such as black bxoes where videos ought to be placed. + */ + +if (!window.google || !window.google.ima || !window.google.ima.VERSION) { + const VERSION = "3.517.2"; + + const CheckCanAutoplay = (function() { + // Sourced from: https://searchfox.org/mozilla-central/source/dom/media/gtest/negative_duration.mp4 + const TEST_VIDEO = new Blob( + [ + new Uint32Array([ + 469762048, + 1887007846, + 1752392036, + 0, + 913273705, + 1717987696, + 828601953, + -1878917120, + 1987014509, + 1811939328, + 1684567661, + 0, + 0, + 0, + -402456576, + 0, + 256, + 1, + 0, + 0, + 256, + 0, + 0, + 0, + 256, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 33554432, + -201261056, + 1801548404, + 1744830464, + 1684564852, + 251658241, + 0, + 0, + 0, + 0, + 16777216, + 0, + -1, + -1, + 0, + 0, + 0, + 0, + 256, + 0, + 0, + 0, + 256, + 0, + 0, + 0, + 64, + 5, + 53250, + -2080309248, + 1634296941, + 738197504, + 1684563053, + 1, + 0, + 0, + 0, + 0, + -2137614336, + -1, + -1, + 50261, + 754974720, + 1919706216, + 0, + 0, + 1701079414, + 0, + 0, + 0, + 1701079382, + 1851869295, + 1919249508, + 16777216, + 1852402979, + 102, + 1752004116, + 100, + 1, + 0, + 0, + 1852400676, + 102, + 1701995548, + 102, + 0, + 1, + 1819440396, + 32, + 1, + 1651799011, + 108, + 1937011607, + 100, + 0, + 1, + 1668702599, + 49, + 0, + 1, + 0, + 0, + 0, + 33555712, + 4718800, + 4718592, + 0, + 65536, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 16776984, + 1630601216, + 21193590, + -14745500, + 1729626337, + -1407254428, + 89161945, + 1049019, + 9453056, + -251611125, + 27269507, + -379058688, + -1329024392, + 268435456, + 1937011827, + 0, + 0, + 268435456, + 1668510835, + 0, + 0, + 335544320, + 2054386803, + 0, + 0, + 0, + 268435456, + 1868788851, + 0, + 0, + 671088640, + 2019915373, + 536870912, + 2019914356, + 0, + 16777216, + 16777216, + 0, + 0, + 0, + ]), + ], + { type: "video/mp4" } + ); + + let testVideo; + + return function() { + if (!testVideo) { + testVideo = document.createElement("video"); + testVideo.style = + "position:absolute; width:0; height:0; left:0; right:0; z-index:-1; border:0"; + testVideo.setAttribute("muted", "muted"); + testVideo.setAttribute("playsinline", "playsinline"); + testVideo.src = URL.createObjectURL(TEST_VIDEO); + document.body.appendChild(testVideo); + } + return testVideo.play(); + }; + })(); + + const ima = {}; + + class AdDisplayContainer { + constructor(containerElement) { + const divElement = document.createElement("div"); + divElement.style.setProperty("display", "none", "important"); + divElement.style.setProperty("visibility", "collapse", "important"); + containerElement.appendChild(divElement); + } + destroy() {} + initialize() {} + } + + class ImaSdkSettings { + constructor() { + this.c = true; + this.f = {}; + this.i = false; + this.l = ""; + this.p = ""; + this.r = 0; + this.t = ""; + this.v = ""; + } + getCompanionBackfill() {} + getDisableCustomPlaybackForIOS10Plus() { + return this.i; + } + getFeatureFlags() { + return this.f; + } + getLocale() { + return this.l; + } + getNumRedirects() { + return this.r; + } + getPlayerType() { + return this.t; + } + getPlayerVersion() { + return this.v; + } + getPpid() { + return this.p; + } + isCookiesEnabled() { + return this.c; + } + setAutoPlayAdBreaks() {} + setCompanionBackfill() {} + setCookiesEnabled(c) { + this.c = !!c; + } + setDisableCustomPlaybackForIOS10Plus(i) { + this.i = !!i; + } + setFeatureFlags(f) { + this.f = f; + } + setLocale(l) { + this.l = l; + } + setNumRedirects(r) { + this.r = r; + } + setPlayerType(t) { + this.t = t; + } + setPlayerVersion(v) { + this.v = v; + } + setPpid(p) { + this.p = p; + } + setSessionId(/*s*/) {} + setVpaidAllowed(/*a*/) {} + setVpaidMode(/*m*/) {} + + // https://github.com/uBlockOrigin/uBlock-issues/issues/2265#issuecomment-1637094149 + getDisableFlashAds() { + } + setDisableFlashAds() { + } + } + ImaSdkSettings.CompanionBackfillMode = { + ALWAYS: "always", + ON_MASTER_AD: "on_master_ad", + }; + ImaSdkSettings.VpaidMode = { + DISABLED: 0, + ENABLED: 1, + INSECURE: 2, + }; + + class EventHandler { + constructor() { + this.listeners = new Map(); + } + + _dispatch(e) { + let listeners = this.listeners.get(e.type); + listeners = listeners ? Array.from(listeners.values()) : []; + for (const listener of listeners) { + try { + listener(e); + } catch (r) { + console.error(r); + } + } + } + + addEventListener(types, c, options, context) { + if (!Array.isArray(types)) { + types = [types]; + } + + for (const t of types) { + if (!this.listeners.has(t)) { + this.listeners.set(t, new Map()); + } + this.listeners.get(t).set(c, c.bind(context || this)); + } + } + + removeEventListener(types, c) { + if (!Array.isArray(types)) { + types = [types]; + } + + for (const t of types) { + const typeSet = this.listeners.get(t); + if (typeSet) { + typeSet.delete(c); + } + } + } + } + + class AdsLoader extends EventHandler { + constructor() { + super(); + this.settings = new ImaSdkSettings(); + } + contentComplete() {} + destroy() {} + getSettings() { + return this.settings; + } + getVersion() { + return VERSION; + } + requestAds(/*r, c*/) { + // If autoplay is disabled and the page is trying to autoplay a tracking + // ad, then IMA fails with an error, and the page is expected to request + // ads again later when the user clicks to play. + CheckCanAutoplay().then( + () => { + const { ADS_MANAGER_LOADED } = AdsManagerLoadedEvent.Type; + this._dispatch(new ima.AdsManagerLoadedEvent(ADS_MANAGER_LOADED)); + }, + () => { + const e = new ima.AdError( + "adPlayError", + 1205, + 1205, + "The browser prevented playback initiated without user interaction." + ); + this._dispatch(new ima.AdErrorEvent(e)); + } + ); + } + } + + class AdsManager extends EventHandler { + constructor() { + super(); + this.volume = 1; + this._enablePreloading = false; + } + collapse() {} + configureAdsManager() {} + destroy() {} + discardAdBreak() {} + expand() {} + focus() {} + getAdSkippableState() { + return false; + } + getCuePoints() { + return [0]; + } + getCurrentAd() { + return currentAd; + } + getCurrentAdCuePoints() { + return []; + } + getRemainingTime() { + return 0; + } + getVolume() { + return this.volume; + } + init(/*w, h, m, e*/) { + if (this._enablePreloading) { + this._dispatch(new ima.AdEvent(AdEvent.Type.LOADED)); + } + } + isCustomClickTrackingUsed() { + return false; + } + isCustomPlaybackUsed() { + return false; + } + pause() {} + requestNextAdBreak() {} + resize(/*w, h, m*/) {} + resume() {} + setVolume(v) { + this.volume = v; + } + skip() {} + start() { + requestAnimationFrame(() => { + for (const type of [ + AdEvent.Type.LOADED, + AdEvent.Type.STARTED, + AdEvent.Type.CONTENT_PAUSE_REQUESTED, + AdEvent.Type.AD_BUFFERING, + AdEvent.Type.FIRST_QUARTILE, + AdEvent.Type.MIDPOINT, + AdEvent.Type.THIRD_QUARTILE, + AdEvent.Type.COMPLETE, + AdEvent.Type.ALL_ADS_COMPLETED, + AdEvent.Type.CONTENT_RESUME_REQUESTED, + ]) { + try { + this._dispatch(new ima.AdEvent(type)); + } catch (e) { + console.error(e); + } + } + }); + } + stop() {} + updateAdsRenderingSettings(/*s*/) {} + } + + class AdsRenderingSettings {} + + class AdsRequest { + setAdWillAutoPlay() {} + setAdWillPlayMuted() {} + setContinuousPlayback() {} + } + + class AdPodInfo { + getAdPosition() { + return 1; + } + getIsBumper() { + return false; + } + getMaxDuration() { + return -1; + } + getPodIndex() { + return 1; + } + getTimeOffset() { + return 0; + } + getTotalAds() { + return 1; + } + } + + class Ad { + constructor() { + this._pi = new AdPodInfo(); + } + getAdId() { + return ""; + } + getAdPodInfo() { + return this._pi; + } + getAdSystem() { + return ""; + } + getAdvertiserName() { + return ""; + } + getApiFramework() { + return null; + } + getCompanionAds() { + return []; + } + getContentType() { + return ""; + } + getCreativeAdId() { + return ""; + } + getCreativeId() { + return ""; + } + getDealId() { + return ""; + } + getDescription() { + return ""; + } + getDuration() { + return 8.5; + } + getHeight() { + return 0; + } + getMediaUrl() { + return null; + } + getMinSuggestedDuration() { + return -2; + } + getSkipTimeOffset() { + return -1; + } + getSurveyUrl() { + return null; + } + getTitle() { + return ""; + } + getTraffickingParameters() { + return {}; + } + getTraffickingParametersString() { + return ""; + } + getUiElements() { + return [""]; + } + getUniversalAdIdRegistry() { + return "unknown"; + } + getUniversalAdIds() { + return [new UniversalAdIdInfo()]; + } + getUniversalAdIdValue() { + return "unknown"; + } + getVastMediaBitrate() { + return 0; + } + getVastMediaHeight() { + return 0; + } + getVastMediaWidth() { + return 0; + } + getWidth() { + return 0; + } + getWrapperAdIds() { + return [""]; + } + getWrapperAdSystems() { + return [""]; + } + getWrapperCreativeIds() { + return [""]; + } + isLinear() { + return true; + } + isSkippable() { + return true; + } + } + + class CompanionAd { + getAdSlotId() { + return ""; + } + getContent() { + return ""; + } + getContentType() { + return ""; + } + getHeight() { + return 1; + } + getWidth() { + return 1; + } + } + + class AdError { + constructor(type, code, vast, message) { + this.errorCode = code; + this.message = message; + this.type = type; + this.vastErrorCode = vast; + } + getErrorCode() { + return this.errorCode; + } + getInnerError() { + return null; + } + getMessage() { + return this.message; + } + getType() { + return this.type; + } + getVastErrorCode() { + return this.vastErrorCode; + } + toString() { + return `AdError ${this.errorCode}: ${this.message}`; + } + } + AdError.ErrorCode = {}; + AdError.Type = {}; + + const isEngadget = () => { + try { + for (const ctx of Object.values(window.vidible._getContexts())) { + const player = ctx.getPlayer(); + if (!player) { continue;} + const div = player.div; + if (!div) { continue; } + if (div.innerHTML.includes("www.engadget.com")) { + return true; + } + } + } catch (_) {} + return false; + }; + + const currentAd = isEngadget() ? undefined : new Ad(); + + class AdEvent { + constructor(type) { + this.type = type; + } + getAd() { + return currentAd; + } + getAdData() { + return {}; + } + } + AdEvent.Type = { + AD_BREAK_READY: "adBreakReady", + AD_BUFFERING: "adBuffering", + AD_CAN_PLAY: "adCanPlay", + AD_METADATA: "adMetadata", + AD_PROGRESS: "adProgress", + ALL_ADS_COMPLETED: "allAdsCompleted", + CLICK: "click", + COMPLETE: "complete", + CONTENT_PAUSE_REQUESTED: "contentPauseRequested", + CONTENT_RESUME_REQUESTED: "contentResumeRequested", + DURATION_CHANGE: "durationChange", + EXPANDED_CHANGED: "expandedChanged", + FIRST_QUARTILE: "firstQuartile", + IMPRESSION: "impression", + INTERACTION: "interaction", + LINEAR_CHANGE: "linearChange", + LINEAR_CHANGED: "linearChanged", + LOADED: "loaded", + LOG: "log", + MIDPOINT: "midpoint", + PAUSED: "pause", + RESUMED: "resume", + SKIPPABLE_STATE_CHANGED: "skippableStateChanged", + SKIPPED: "skip", + STARTED: "start", + THIRD_QUARTILE: "thirdQuartile", + USER_CLOSE: "userClose", + VIDEO_CLICKED: "videoClicked", + VIDEO_ICON_CLICKED: "videoIconClicked", + VIEWABLE_IMPRESSION: "viewable_impression", + VOLUME_CHANGED: "volumeChange", + VOLUME_MUTED: "mute", + }; + + class AdErrorEvent { + constructor(error) { + this.type = "adError"; + this.error = error; + } + getError() { + return this.error; + } + getUserRequestContext() { + return {}; + } + } + AdErrorEvent.Type = { + AD_ERROR: "adError", + }; + + const manager = new AdsManager(); + + class AdsManagerLoadedEvent { + constructor(type) { + this.type = type; + } + getAdsManager(c, settings) { + if (settings && settings.enablePreloading) { + manager._enablePreloading = true; + } + return manager; + } + getUserRequestContext() { + return {}; + } + } + AdsManagerLoadedEvent.Type = { + ADS_MANAGER_LOADED: "adsManagerLoaded", + }; + + class CustomContentLoadedEvent {} + CustomContentLoadedEvent.Type = { + CUSTOM_CONTENT_LOADED: "deprecated-event", + }; + + class CompanionAdSelectionSettings {} + CompanionAdSelectionSettings.CreativeType = { + ALL: "All", + FLASH: "Flash", + IMAGE: "Image", + }; + CompanionAdSelectionSettings.ResourceType = { + ALL: "All", + HTML: "Html", + IFRAME: "IFrame", + STATIC: "Static", + }; + CompanionAdSelectionSettings.SizeCriteria = { + IGNORE: "IgnoreSize", + SELECT_EXACT_MATCH: "SelectExactMatch", + SELECT_NEAR_MATCH: "SelectNearMatch", + }; + + class AdCuePoints { + getCuePoints() { + return []; + } + } + + class AdProgressData {} + + class UniversalAdIdInfo { + getAdIdRegistry() { + return ""; + } + getAdIdValue() { + return ""; + } + } + + Object.assign(ima, { + AdCuePoints, + AdDisplayContainer, + AdError, + AdErrorEvent, + AdEvent, + AdPodInfo, + AdProgressData, + AdsLoader, + AdsManager: manager, + AdsManagerLoadedEvent, + AdsRenderingSettings, + AdsRequest, + CompanionAd, + CompanionAdSelectionSettings, + CustomContentLoadedEvent, + gptProxyInstance: {}, + ImaSdkSettings, + OmidAccessMode: { + DOMAIN: "domain", + FULL: "full", + LIMITED: "limited", + }, + OmidVerificationVendor: { + 1: "OTHER", + 2: "GOOGLE", + GOOGLE: 2, + OTHER: 1 + }, + settings: new ImaSdkSettings(), + UiElements: { + AD_ATTRIBUTION: "adAttribution", + COUNTDOWN: "countdown", + }, + UniversalAdIdInfo, + VERSION, + ViewMode: { + FULLSCREEN: "fullscreen", + NORMAL: "normal", + }, + }); + + if (!window.google) { + window.google = {}; + } + + window.google.ima = ima; +} diff --git a/src/web_accessible_resources/googlesyndication_adsbygoogle.js b/src/web_accessible_resources/googlesyndication_adsbygoogle.js new file mode 100644 index 0000000..dec634b --- /dev/null +++ b/src/web_accessible_resources/googlesyndication_adsbygoogle.js @@ -0,0 +1,56 @@ +/******************************************************************************* + + 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 +*/ + +(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); + phs[i].appendChild(fr); + } + }; + if ( + document.querySelectorAll('.adsbygoogle').length === 0 && + document.readyState === 'loading' + ) { + window.addEventListener('DOMContentLoaded', init, { once: true }); + } else { + init(); + } +})(); + +/* +pagead2.googlesyndication.com/pagead/js/adsbygoogle.js,adsbygoogle-placeholder,adsbygoogleStatus,google_ad_channel,google_ad_client,google_ad_format,google_ad_frequency_hint,google_ad_height,google_ad_host,google_ad_host_channel,google_ad_modifications,google_ad_region,google_ad_resizable,google_ad_resize,google_ad_section,google_ad_semantic_area,google_ad_width,google_adbreak_test,google_ads_frame,google_ads_iframe,google_adtest,google_admob_interstitial_slot,google_admob_rewarded_slot,google_admob_ads_only,google-adsense-platform-account,google_adsense_settings,google_ama_config,google-ama-order-assurance,google_ama_settings,google_ama_state,google_apltlad,google_audio_sense,google-auto-placed-read-aloud-player-reserved,google_debug_params,google_full_width_responsive,google_full_width_responsive_allowed,google_image_requests,google_js_errors,google_js_reporting_queue,google_loader_features_used,google_llp,google_logging_queue,google_max_ad_content_rating,google_measure_js_timing,google_ml_rank,google_overlays,google_override_format,google_package,google_page_url,google_persistent_state_async,google_pgb_reactive,google_placement_id,google_prev_ad_formats_by_region,google_prev_ad_slotnames_by_region,google_reactive_ad_format,google_reactive_ads_global_state,google_resizing_height,google_resizing_width,google_responsive_auto_format,google_responsive_dummy_ad,google_responsive_formats,google_restrict_data_processing,google_rum_task_id_counter,google_safe_for_responsive_override,google_shadow_mode,google_srt,google_tag_for_under_age_of_consent,google_tag_origin,google_tag_partner,google_traffic_source,google_unique_id,googletag +*/ diff --git a/src/web_accessible_resources/googletagmanager_gtm.js b/src/web_accessible_resources/googletagmanager_gtm.js new file mode 100644 index 0000000..09f4658 --- /dev/null +++ b/src/web_accessible_resources/googletagmanager_gtm.js @@ -0,0 +1,43 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + const w = window; + w.ga = w.ga || noopfn; + const dl = w.dataLayer; + if ( dl instanceof Object === false ) { return; } + if ( dl.hide instanceof Object && typeof dl.hide.end === 'function' ) { + dl.hide.end(); + } + if ( typeof dl.push === 'function' ) { + dl.push = function(o) { + if ( + o instanceof Object && + typeof o.eventCallback === 'function' + ) { + setTimeout(o.eventCallback, 1); + } + }; + } +})(); diff --git a/src/web_accessible_resources/googletagservices_gpt.js b/src/web_accessible_resources/googletagservices_gpt.js new file mode 100644 index 0000000..b151936 --- /dev/null +++ b/src/web_accessible_resources/googletagservices_gpt.js @@ -0,0 +1,154 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + // https://developers.google.com/doubleclick-gpt/reference + const noopfn = function() { + }.bind(); + const noopthisfn = function() { + return this; + }; + const noopnullfn = function() { + return null; + }; + const nooparrayfn = function() { + return []; + }; + const noopstrfn = function() { + return ''; + }; + // + const companionAdsService = { + addEventListener: noopthisfn, + enableSyncLoading: noopfn, + setRefreshUnfilledSlots: noopfn + }; + const contentService = { + addEventListener: noopthisfn, + setContent: noopfn + }; + const PassbackSlot = function() { + }; + let p = PassbackSlot.prototype; + p.display = noopfn; + p.get = noopnullfn; + p.set = noopthisfn; + p.setClickUrl = noopthisfn; + p.setTagForChildDirectedTreatment = noopthisfn; + p.setTargeting = noopthisfn; + p.updateTargetingFromMap = noopthisfn; + const pubAdsService = { + addEventListener: noopthisfn, + clear: noopfn, + clearCategoryExclusions: noopthisfn, + clearTagForChildDirectedTreatment: noopthisfn, + clearTargeting: noopthisfn, + collapseEmptyDivs: noopfn, + defineOutOfPagePassback: function() { return new PassbackSlot(); }, + definePassback: function() { return new PassbackSlot(); }, + disableInitialLoad: noopfn, + display: noopfn, + enableAsyncRendering: noopfn, + enableLazyLoad: noopfn, + enableSingleRequest: noopfn, + enableSyncRendering: noopfn, + enableVideoAds: noopfn, + get: noopnullfn, + getAttributeKeys: nooparrayfn, + getTargeting: nooparrayfn, + getTargetingKeys: nooparrayfn, + getSlots: nooparrayfn, + refresh: noopfn, + removeEventListener: noopfn, + set: noopthisfn, + setCategoryExclusion: noopthisfn, + setCentering: noopfn, + setCookieOptions: noopthisfn, + setForceSafeFrame: noopthisfn, + setLocation: noopthisfn, + setPublisherProvidedId: noopthisfn, + setPrivacySettings: noopthisfn, + setRequestNonPersonalizedAds: noopthisfn, + setSafeFrameConfig: noopthisfn, + setTagForChildDirectedTreatment: noopthisfn, + setTargeting: noopthisfn, + setVideoContent: noopthisfn, + updateCorrelator: noopfn + }; + const SizeMappingBuilder = function() { + }; + p = SizeMappingBuilder.prototype; + p.addSize = noopthisfn; + p.build = noopnullfn; + const Slot = function() { + }; + p = Slot.prototype; + p.addService = noopthisfn; + p.clearCategoryExclusions = noopthisfn; + p.clearTargeting = noopthisfn; + p.defineSizeMapping = noopthisfn; + p.get = noopnullfn; + p.getAdUnitPath = nooparrayfn; + p.getAttributeKeys = nooparrayfn; + p.getCategoryExclusions = nooparrayfn; + p.getDomId = noopstrfn; + p.getResponseInformation = noopnullfn; + p.getSlotElementId = noopstrfn; + p.getSlotId = noopthisfn; + p.getTargeting = nooparrayfn; + p.getTargetingKeys = nooparrayfn; + p.set = noopthisfn; + p.setCategoryExclusion = noopthisfn; + p.setClickUrl = noopthisfn; + p.setCollapseEmptyDiv = noopthisfn; + p.setTargeting = noopthisfn; + p.updateTargetingFromMap = noopthisfn; + // + const gpt = window.googletag || {}; + const cmd = gpt.cmd || []; + gpt.apiReady = true; + gpt.cmd = []; + gpt.cmd.push = function(a) { + try { + a(); + } catch (ex) { + } + return 1; + }; + gpt.companionAds = function() { return companionAdsService; }; + gpt.content = function() { return contentService; }; + gpt.defineOutOfPageSlot = function() { return new Slot(); }; + gpt.defineSlot = function() { return new Slot(); }; + gpt.destroySlots = noopfn; + gpt.disablePublisherConsole = noopfn; + gpt.display = noopfn; + gpt.enableServices = noopfn; + gpt.getVersion = noopstrfn; + gpt.pubads = function() { return pubAdsService; }; + gpt.pubadsReady = true; + gpt.setAdIframeTitle = noopfn; + gpt.sizeMapping = function() { return new SizeMappingBuilder(); }; + window.googletag = gpt; + while ( cmd.length !== 0 ) { + gpt.cmd.push(cmd.shift()); + } +})(); diff --git a/src/web_accessible_resources/hd-main.js b/src/web_accessible_resources/hd-main.js new file mode 100644 index 0000000..149d603 --- /dev/null +++ b/src/web_accessible_resources/hd-main.js @@ -0,0 +1,46 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const l = {}; + const noopfn = function() { + }; + const props = [ + "$j","Ad","Bd","Cd","Dd","Ed","Fd","Gd","Hd","Id","Jd","Nj","Oc","Pc","Pe", + "Qc","Qe","Rc","Re","Ri","Sc","Tc","Uc","Vc","Wc","Wg","Xc","Xg","Yc","Yd", + "ad","ae","bd","bf","cd","dd","ed","ef","ek","fd","fg","fh","fk","gd","hd", + "ig","ij","jd","kd","ke","ld","md","mi","nd","od","oh","pd","pf","qd","rd", + "sd","td","ud","vd","wd","wg","xd","xh","yd","zd", + "$d","$e","$k","Ae","Af","Aj","Be","Ce","De","Ee","Ek","Eo","Ep","Fe","Fo", + "Ge","Gh","Hk","Ie","Ip","Je","Ke","Kk","Kq","Le","Lh","Lk","Me","Mm","Ne", + "Oe","Pe","Qe","Re","Rp","Se","Te","Ue","Ve","Vp","We","Xd","Xe","Yd","Ye", + "Zd","Ze","Zf","Zk","ae","af","al","be","bf","bg","ce","cp","df","di","ee", + "ef","fe","ff","gf","gm","he","hf","ie","je","jf","ke","kf","kl","le","lf", + "lk","mf","mg","mn","nf","oe","of","pe","pf","pg","qe","qf","re","rf","se", + "sf","te","tf","ti","ue","uf","ve","vf","we","wf","wg","wi","xe","ye","yf", + "yk","yl","ze","zf","zk" + ]; + for ( let i = 0; i < props.length; i++ ) { + l[props[i]] = noopfn; + } + window.L = window.J = l; +})(); diff --git a/src/web_accessible_resources/nobab.js b/src/web_accessible_resources/nobab.js new file mode 100644 index 0000000..32a2983 --- /dev/null +++ b/src/web_accessible_resources/nobab.js @@ -0,0 +1,87 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const signatures = [ + [ 'blockadblock' ], + [ 'babasbm' ], + [ /getItem\('babn'\)/ ], + [ + 'getElementById', + 'String.fromCharCode', + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + 'charAt', + 'DOMContentLoaded', + 'AdBlock', + 'addEventListener', + 'doScroll', + 'fromCharCode', + '<<2|r>>4', + 'sessionStorage', + 'clientWidth', + 'localStorage', + 'Math', + 'random' + ], + ]; + const check = function(s) { + for ( let i = 0; i < signatures.length; i++ ) { + const tokens = signatures[i]; + 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; } + } + 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); + } + } + }); + 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); + } + } + }); +})(); diff --git a/src/web_accessible_resources/nobab2.js b/src/web_accessible_resources/nobab2.js new file mode 100644 index 0000000..ea3b210 --- /dev/null +++ b/src/web_accessible_resources/nobab2.js @@ -0,0 +1,42 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2021-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 +*/ + +(function() { + 'use strict'; + const script = document.currentScript; + if ( script === null ) { return; } + const src = script.src; + if ( typeof src !== 'string' ) { return; } + // The scriplet is meant to act ONLY when it's being used as a redirection + // for specific domains. + const re = new RegExp( + '^https?://[\\w-]+\\.(' + + [ + 'adclixx\\.net', + 'adnetasia\\.com', + 'adtrackers\\.net', + 'bannertrack\\.net', + ].join('|') + + ')/.' + ); + if ( re.test(src) === false ) { return; } + window.nH7eXzOsG = 858; +})(); diff --git a/src/web_accessible_resources/noeval-silent.js b/src/web_accessible_resources/noeval-silent.js new file mode 100644 index 0000000..cfe6e3b --- /dev/null +++ b/src/web_accessible_resources/noeval-silent.js @@ -0,0 +1,28 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + window.eval = new Proxy(window.eval, { // jshint ignore: line + apply: function() { + } + }); +})(); diff --git a/src/web_accessible_resources/noeval.js b/src/web_accessible_resources/noeval.js new file mode 100644 index 0000000..e1f2a74 --- /dev/null +++ b/src/web_accessible_resources/noeval.js @@ -0,0 +1,30 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const log = console.log.bind(console); + window.eval = new Proxy(window.eval, { // jshint ignore: line + apply: function(target, thisArg, args) { + log(`Document tried to eval... ${args[0]}\n`); + } + }); +})(); diff --git a/src/web_accessible_resources/nofab.js b/src/web_accessible_resources/nofab.js new file mode 100644 index 0000000..9e50e0b --- /dev/null +++ b/src/web_accessible_resources/nofab.js @@ -0,0 +1,67 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + const Fab = function() {}; + Fab.prototype.check = noopfn; + Fab.prototype.clearEvent = noopfn; + Fab.prototype.emitEvent = noopfn; + Fab.prototype.on = function(a, b) { + if ( !a ) { b(); } + return this; + }; + Fab.prototype.onDetected = function() { + return this; + }; + Fab.prototype.onNotDetected = function(a) { + a(); + return this; + }; + Fab.prototype.setOption = noopfn; + Fab.prototype.options = { + set: noopfn, + get: noopfn, + }; + const fab = new Fab(); + const getSetFab = { + get: function() { return Fab; }, + set: function() {} + }; + const getsetfab = { + get: function() { return fab; }, + set: function() {} + }; + if ( window.hasOwnProperty('FuckAdBlock') ) { window.FuckAdBlock = Fab; } + else { Object.defineProperty(window, 'FuckAdBlock', getSetFab); } + if ( window.hasOwnProperty('BlockAdBlock') ) { window.BlockAdBlock = Fab; } + else { Object.defineProperty(window, 'BlockAdBlock', getSetFab); } + if ( window.hasOwnProperty('SniffAdBlock') ) { window.SniffAdBlock = Fab; } + else { Object.defineProperty(window, 'SniffAdBlock', getSetFab); } + if ( window.hasOwnProperty('fuckAdBlock') ) { window.fuckAdBlock = fab; } + else { Object.defineProperty(window, 'fuckAdBlock', getsetfab); } + if ( window.hasOwnProperty('blockAdBlock') ) { window.blockAdBlock = fab; } + else { Object.defineProperty(window, 'blockAdBlock', getsetfab); } + if ( window.hasOwnProperty('sniffAdBlock') ) { window.sniffAdBlock = fab; } + else { Object.defineProperty(window, 'sniffAdBlock', getsetfab); } +})(); diff --git a/src/web_accessible_resources/noop-0.1s.mp3 b/src/web_accessible_resources/noop-0.1s.mp3 new file mode 100644 index 0000000..147d71b Binary files /dev/null and b/src/web_accessible_resources/noop-0.1s.mp3 differ diff --git a/src/web_accessible_resources/noop-0.5s.mp3 b/src/web_accessible_resources/noop-0.5s.mp3 new file mode 100644 index 0000000..b82866b Binary files /dev/null and b/src/web_accessible_resources/noop-0.5s.mp3 differ diff --git a/src/web_accessible_resources/noop-1s.mp4 b/src/web_accessible_resources/noop-1s.mp4 new file mode 100644 index 0000000..5689d4a Binary files /dev/null and b/src/web_accessible_resources/noop-1s.mp4 differ diff --git a/src/web_accessible_resources/noop-vmap1.0.xml b/src/web_accessible_resources/noop-vmap1.0.xml new file mode 100644 index 0000000..acd6fb8 --- /dev/null +++ b/src/web_accessible_resources/noop-vmap1.0.xml @@ -0,0 +1 @@ + diff --git a/src/web_accessible_resources/noop.css b/src/web_accessible_resources/noop.css new file mode 100644 index 0000000..79a9626 --- /dev/null +++ b/src/web_accessible_resources/noop.css @@ -0,0 +1 @@ +/* */ diff --git a/src/web_accessible_resources/noop.html b/src/web_accessible_resources/noop.html new file mode 100644 index 0000000..8aaae14 --- /dev/null +++ b/src/web_accessible_resources/noop.html @@ -0,0 +1,5 @@ + + + + + diff --git a/src/web_accessible_resources/noop.js b/src/web_accessible_resources/noop.js new file mode 100644 index 0000000..b977b08 --- /dev/null +++ b/src/web_accessible_resources/noop.js @@ -0,0 +1,3 @@ +(function() { + 'use strict'; +})(); diff --git a/src/web_accessible_resources/noop.json b/src/web_accessible_resources/noop.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/src/web_accessible_resources/noop.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/src/web_accessible_resources/noop.txt b/src/web_accessible_resources/noop.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/web_accessible_resources/noop.txt @@ -0,0 +1 @@ + diff --git a/src/web_accessible_resources/outbrain-widget.js b/src/web_accessible_resources/outbrain-widget.js new file mode 100644 index 0000000..10ba605 --- /dev/null +++ b/src/web_accessible_resources/outbrain-widget.js @@ -0,0 +1,72 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const noopfn = function() { + }; + const obr = {}; + const methods = [ + 'callClick', + 'callLoadMore', + 'callRecs', + 'callUserZapping', + 'callWhatIs', + 'cancelRecommendation', + 'cancelRecs', + 'closeCard', + 'closeModal', + 'closeTbx', + 'errorInjectionHandler', + 'getCountOfRecs', + 'getStat', + 'imageError', + 'manualVideoClicked', + 'onOdbReturn', + 'onVideoClick', + 'pagerLoad', + 'recClicked', + 'refreshSpecificWidget', + 'renderSpaWidgets', + 'refreshWidget', + 'reloadWidget', + 'researchWidget', + 'returnedError', + 'returnedHtmlData', + 'returnedIrdData', + 'returnedJsonData', + 'scrollLoad', + 'showDescription', + 'showRecInIframe', + 'userZappingMessage', + 'zappingFormAction' + ]; + obr.extern = { + video: { + getVideoRecs: noopfn, + videoClicked: noopfn + } + }; + methods.forEach(function(a) { + obr.extern[a] = noopfn; + }); + window.OBR = window.OBR || obr; +})(); diff --git a/src/web_accessible_resources/popads-dummy.js b/src/web_accessible_resources/popads-dummy.js new file mode 100644 index 0000000..0ca0b1e --- /dev/null +++ b/src/web_accessible_resources/popads-dummy.js @@ -0,0 +1,30 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + delete window.PopAds; + delete window.popns; + Object.defineProperties(window, { + PopAds: { value: {} }, + popns: { value: {} } + }); +})(); diff --git a/src/web_accessible_resources/popads.js b/src/web_accessible_resources/popads.js new file mode 100644 index 0000000..df86e97 --- /dev/null +++ b/src/web_accessible_resources/popads.js @@ -0,0 +1,40 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + const magic = String.fromCharCode(Date.now() % 26 + 97) + + Math.floor(Math.random() * 982451653 + 982451653).toString(36); + const oe = window.onerror; + window.onerror = function(msg, src, line, col, error) { + if ( typeof msg === 'string' && msg.indexOf(magic) !== -1 ) { return true; } + if ( oe instanceof Function ) { + return oe(msg, src, line, col, error); + } + }.bind(); + const throwMagic = function() { throw new ReferenceError(magic); }; + delete window.PopAds; + delete window.popns; + Object.defineProperties(window, { + PopAds: { set: throwMagic }, + popns: { set: throwMagic } + }); +})(); diff --git a/src/web_accessible_resources/prebid-ads.js b/src/web_accessible_resources/prebid-ads.js new file mode 100644 index 0000000..f3b2dc6 --- /dev/null +++ b/src/web_accessible_resources/prebid-ads.js @@ -0,0 +1,26 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + 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 +*/ + +(function() { + 'use strict'; + window.canRunAds = true; + window.isAdBlockActive = false; +})(); diff --git a/src/web_accessible_resources/scorecardresearch_beacon.js b/src/web_accessible_resources/scorecardresearch_beacon.js new file mode 100644 index 0000000..5ca7203 --- /dev/null +++ b/src/web_accessible_resources/scorecardresearch_beacon.js @@ -0,0 +1,31 @@ +/******************************************************************************* + + 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 +*/ + +(function() { + 'use strict'; + window.COMSCORE = { + purge: function() { + window._comscore = []; + }, + beacon: function() { + } + }; +})(); diff --git a/src/whitelist.html b/src/whitelist.html new file mode 100644 index 0000000..02d31d8 --- /dev/null +++ b/src/whitelist.html @@ -0,0 +1,63 @@ + + + + + +uBlock — Whitelist + + + + + + + + + + + + + + + +
    +
    + +

    info-circle +

    +

    + + +    + + +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3