├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── beta.php ├── browserconfig.xml ├── css ├── base │ ├── base.css │ ├── fonts.css │ └── variables.css ├── components │ ├── comp.css │ ├── dialog.css │ ├── header.css │ ├── notification.css │ └── pw-po.css ├── index.css └── layouts │ ├── logs.css │ └── talk.css ├── fonts ├── roboto-v20-latin-300.eot ├── roboto-v20-latin-300.svg ├── roboto-v20-latin-300.ttf ├── roboto-v20-latin-300.woff ├── roboto-v20-latin-300.woff2 ├── roboto-v20-latin-300italic.eot ├── roboto-v20-latin-300italic.svg ├── roboto-v20-latin-300italic.ttf ├── roboto-v20-latin-300italic.woff ├── roboto-v20-latin-300italic.woff2 ├── roboto-v20-latin-500.eot ├── roboto-v20-latin-500.svg ├── roboto-v20-latin-500.ttf ├── roboto-v20-latin-500.woff ├── roboto-v20-latin-500.woff2 ├── roboto-v20-latin-500italic.eot ├── roboto-v20-latin-500italic.svg ├── roboto-v20-latin-500italic.ttf ├── roboto-v20-latin-500italic.woff ├── roboto-v20-latin-500italic.woff2 ├── roboto-v20-latin-700.eot ├── roboto-v20-latin-700.svg ├── roboto-v20-latin-700.ttf ├── roboto-v20-latin-700.woff ├── roboto-v20-latin-700.woff2 ├── roboto-v20-latin-700italic.eot ├── roboto-v20-latin-700italic.svg ├── roboto-v20-latin-700italic.ttf ├── roboto-v20-latin-700italic.woff ├── roboto-v20-latin-700italic.woff2 ├── roboto-v20-latin-900.eot ├── roboto-v20-latin-900.svg ├── roboto-v20-latin-900.ttf ├── roboto-v20-latin-900.woff ├── roboto-v20-latin-900.woff2 ├── roboto-v20-latin-900italic.eot ├── roboto-v20-latin-900italic.svg ├── roboto-v20-latin-900italic.ttf ├── roboto-v20-latin-900italic.woff ├── roboto-v20-latin-900italic.woff2 ├── roboto-v20-latin-italic.eot ├── roboto-v20-latin-italic.svg ├── roboto-v20-latin-italic.ttf ├── roboto-v20-latin-italic.woff ├── roboto-v20-latin-italic.woff2 ├── roboto-v20-latin-regular.eot ├── roboto-v20-latin-regular.svg ├── roboto-v20-latin-regular.ttf ├── roboto-v20-latin-regular.woff └── roboto-v20-latin-regular.woff2 ├── git-pull.php ├── git-pull2.php ├── i18n ├── ar.json ├── az.json ├── bar.json ├── bn.json ├── ca.json ├── ce.json ├── ceb.json ├── cs.json ├── da.json ├── de.json ├── diq.json ├── el.json ├── en.json ├── es.json ├── fi.json ├── fr.json ├── gu.json ├── he.json ├── hi.json ├── hu.json ├── id.json ├── is.json ├── it.json ├── ja.json ├── kn.json ├── ko.json ├── lb.json ├── lt.json ├── mk.json ├── nl.json ├── pl.json ├── pt-br.json ├── qqq.json ├── ro.json ├── ru.json ├── scn.json ├── sdh.json ├── skr-arab.json ├── sl.json ├── sms.json ├── sv.json ├── tr.json ├── uk.json ├── uz.json ├── vi.json ├── zh-hans.json ├── zh-hant.json └── zh-hk.json ├── img ├── about-filled.svg ├── arrow-left-filled.svg ├── arrow-up-filled.svg ├── back-filled.svg ├── back.svg ├── bell-filled.svg ├── box-filled.svg ├── check-mark.svg ├── clear-bars-filled.svg ├── confirm-undo.svg ├── copy-filled.svg ├── cross-filled.svg ├── cross.svg ├── custom-rollback-filled.svg ├── delete-filled.svg ├── doc-filled.svg ├── down-filled.svg ├── drawer-filled.svg ├── drawer.svg ├── edit-filled.svg ├── edit-page.svg ├── eye-filled.svg ├── favicons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon-114x114.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-144x144.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-57x57.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-72x72.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── mstile-150x150.png │ └── safari-pinned-tab.svg ├── filter-bar-filled.svg ├── filter-filled.svg ├── forward-filled.svg ├── h-dots-filled.svg ├── home-filled.svg ├── link.svg ├── logout.svg ├── message-filled.svg ├── new-tab.svg ├── open-newtab-filled.svg ├── pencil-filled.svg ├── people-filled.svg ├── people.svg ├── plus-filled.svg ├── power-filled.svg ├── reload-filled.svg ├── report-filled.svg ├── rollback-filled.svg ├── save-filled.svg ├── save.svg ├── search-filled.svg ├── send-filled.svg ├── send.svg ├── settings-filled.svg ├── settings.svg ├── swviewer-droping-anim.svg ├── swviewer-filled.svg ├── swviewer-loading-anim.svg ├── swviewer-logo-raw.svg ├── tag-filled.svg ├── tag.svg ├── thumbs-up-filled.svg ├── undo.svg ├── v-dots-filled.svg └── warning-filled.svg ├── index-maintenance.html ├── index.php ├── js ├── frame │ └── frameKeys.js ├── index-noncritical.js ├── modules │ ├── about.js │ ├── bakeEl.js │ ├── bakeEl.min.js │ ├── dialog.js │ ├── localisation-sand.js │ ├── logs.js │ ├── notification.js │ ├── po.js │ ├── presets.js │ ├── pw.js │ ├── swipe.js │ └── talk.js ├── pwacompat.js └── swv.js ├── manifest.webmanifest ├── offline.html ├── php ├── authTalk.php ├── control.php ├── doEdit.php ├── getConfig.php ├── getFilt.php ├── getGlobals.php ├── getOfflineUsers.php ├── getSessionVars.php ├── gsr.php ├── includes │ └── headerOAuth.php ├── localisation.php ├── logs.php ├── notify.php ├── oauth.php ├── patrol.php ├── presets.php ├── rollback.php ├── settings.php ├── talkHistory.php ├── thank.php └── welcome-stats.php ├── service-worker.js ├── sounds ├── LICENSE.txt ├── bump.wav ├── message.mp3 └── privateMessage.mp3 ├── stats ├── getGraphs.py └── index.html └── templates ├── about.html ├── diffEnd.html ├── diffStart.html ├── editPreset.html ├── errorEnd.html ├── errorStart.html ├── newEnd.html ├── newStart.html ├── newStringEnd.html ├── newStringStart.html └── welcome.html /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2016-2022 Team SWViewer 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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 OR COPYRIGHT HOLDERS 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. 8 | 9 | Components:
10 | bump.wav: [license / author of original file](https://freesound.org/people/kwahmah_02/sounds/268825/)
11 | message.mp3: [license / author of original file](https://freesound.org/people/elmasmalo1/sounds/377017/)
12 | privateMessage.mp3: [license / author of original file](https://freesound.org/people/rhodesmas/sounds/342749/)
13 | Thumbs up font awesome.svg: [license / author of original file](https://en.wikibooks.org/wiki/File:Thumbs_up_font_awesome.svg) 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SWViewer is a user friendly webapp that is used to detect and revert vandalism, spam, and other types of unconstructive edits made at various Wikimedia projects. With simple and intuitive UI, you can monitor changes in real-time. In doing so, it provides a lot of features; such as rollback, speedy deletion, edit source. 2 | 3 | Read more at https://meta.wikimedia.org/wiki/SWViewer -------------------------------------------------------------------------------- /beta.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SWViewer | Beta 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 65 | 66 | 67 |
68 | 69 |

Beta not available

70 | Beta version is not available right now. For more information you can join our discord server or IRC channel. 71 |
72 | Image source: Unsplash 73 | 74 | -------------------------------------------------------------------------------- /browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #808d9f 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /css/base/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /*-------background-colors--------*/ 3 | --bc-primary: #191919; 4 | --bc-primary-low: #212121; 5 | --bc-primary-hover: rgba(255, 255, 255, .05); 6 | 7 | --bc-secondary: #ffffff; 8 | --bc-secondary-low: #f4f4f4; 9 | --bc-secondary-hover: rgba(0, 0, 0, .1); 10 | 11 | --bc-accent: #0063e4; 12 | --bc-accent-hover: #0056c7; 13 | 14 | --bc-positive: rgb(36, 164, 100); 15 | --bc-negative: rgb(251, 47, 47); 16 | 17 | --ic-primary: invert(0.85) sepia(1) saturate(0) hue-rotate(200deg); 18 | --ic-secondary: invert(0.30) sepia(1) saturate(0) hue-rotate(200deg); 19 | --ic-accent: invert(0.85) sepia(1) saturate(0) hue-rotate(200deg); 20 | 21 | --bc-mid: #7d7d7d2e; 22 | 23 | /*-------text-color-----------*/ 24 | --tc-primary: rgba(255, 255, 255, 1); 25 | --tc-primary-low: rgba(255, 255, 255, .8); 26 | 27 | --tc-secondary: rgba(0, 0, 0, 1); 28 | --tc-secondary-low: rgba(0, 0, 0, .7); 29 | 30 | --tc-accent: rgba(255, 255, 255, 1); 31 | 32 | --link-color: #337ab7; 33 | --tc-positive: var(--bc-positive); 34 | --tc-negative: var(--bc-negative); 35 | 36 | /*------fonts----------*/ 37 | --fs-xl: 26px; 38 | --fs-lg: 18px; 39 | --fs-md: 16px; 40 | --fs-sm: 14px; 41 | --fs-xs: 11px; 42 | 43 | --lh-xl: 1.125; 44 | --lh-lg: 1.25; 45 | --lh-md: 1.42; 46 | --lh-sm: 1.5; 47 | --lh-xs: 1.5; 48 | 49 | /*----others------*/ 50 | --drawer-width: 250px; 51 | --sidebar-width: 56px; 52 | --statusbar-height: 26px; 53 | 54 | --action-header-height: 56px; 55 | --pw-header-height: var(--action-header-height); 56 | --pw-drawer-width: 200px; 57 | --floatbar-height: 48px; 58 | --floatbar-shadow: 0 0 2px 0 rgba(125, 125, 125, .5); 59 | --side-padding: 16px; 60 | } 61 | 62 | /*######################## 63 | ---------Tab view--------- 64 | ########################*/ 65 | @media screen and (min-width: 750px) and (max-width: 1024px) { 66 | :root { 67 | --drawer-width: 180px; 68 | --pw-drawer-width: 150px; 69 | } 70 | } 71 | 72 | /*######################## 73 | --------Mobile view------- 74 | ########################*/ 75 | 76 | @media screen and (max-width: 750px) { 77 | :root { 78 | --fs-xl: 22px !important; 79 | --action-header-height: 48px; 80 | --m-queue-drawer-width: 250px; 81 | --pw-drawer-width: 200px; 82 | } 83 | } 84 | 85 | @media (prefers-color-scheme: light) { 86 | :root { 87 | --system-theme:light; 88 | } 89 | } 90 | @media (prefers-color-scheme: dark) { 91 | :root { 92 | --system-theme:dark; 93 | } 94 | } -------------------------------------------------------------------------------- /css/components/dialog.css: -------------------------------------------------------------------------------- 1 | .dialog__background { 2 | padding: var(--side-padding) 8px; 3 | position: absolute; 4 | top: 0; 5 | left: 0; 6 | z-index: 198; 7 | 8 | width: 100%; 9 | height: 100%; 10 | background-color: rgba(0, 0, 0, 0.4); 11 | overflow: hidden; 12 | overflow-y: auto; 13 | cursor: pointer; 14 | opacity: 0; 15 | transition: opacity 200ms ease-in-out; 16 | } 17 | .dialog__flex { 18 | width: 100%; 19 | min-height: 100%; 20 | display: flex; 21 | justify-content: center; 22 | align-items: center; 23 | } 24 | .dialog__base { 25 | margin: auto; 26 | padding: 24px; 27 | max-width: 450px; 28 | width: 100%; 29 | 30 | background-color: var(--bc-secondary); 31 | border-radius: 8px; 32 | box-shadow: var(--floatbar-shadow); 33 | overflow: hidden; 34 | cursor: auto; 35 | opacity: 0; 36 | transform: scale(.5); 37 | transition: opacity 200ms ease-in-out, 38 | transform 200ms ease-in-out; 39 | } 40 | .dialog__animation { 41 | opacity: 1; 42 | transform: scale(1); 43 | } 44 | .dialog__header { 45 | padding: 0 56px 16px; 46 | display: flex; 47 | justify-content: center; 48 | align-items: center; 49 | position: relative; 50 | } 51 | .dialog__header > .d-title { 52 | font-weight: 500; 53 | overflow: hidden; 54 | text-overflow: ellipsis; 55 | white-space: nowrap; 56 | } 57 | .dialog__header > .d-close { 58 | position: absolute; 59 | right: 0; 60 | top: 0; 61 | cursor: pointer; 62 | } 63 | .dialog__body { 64 | padding: 24px 0; 65 | padding-bottom: 24px; 66 | display: flex; 67 | flex-direction: column; 68 | } 69 | .dialog__emoji, 70 | .dialog__message { 71 | margin: auto; 72 | max-width: 400px; 73 | text-align: center; 74 | } 75 | .dialog__emoji { 76 | padding-bottom: 24px; 77 | font-size: 56px; 78 | } 79 | .dialog__custom:not(:first-child) { padding-top: 16px; } 80 | .dialog__buttons { 81 | display: flex; 82 | flex-direction: row-reverse; 83 | } 84 | .dialog__buttons > button { 85 | margin: 0 0 0 16px; 86 | } -------------------------------------------------------------------------------- /css/components/header.css: -------------------------------------------------------------------------------- 1 | .action-header, 2 | .action-header__sticky { 3 | width: 100%; 4 | height: var(--action-header-height); 5 | display: flex; 6 | align-items: center; 7 | position: relative; 8 | } 9 | .action-header__sticky { 10 | position: sticky; 11 | top: 0; 12 | } 13 | .action-header > div, 14 | .action-header__sticky > div { 15 | width: var(--action-header-height); 16 | height: var(--action-header-height); 17 | 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | cursor: pointer; 22 | } 23 | .action-header > span.action-header__title, 24 | .action-header__sticky > span.action-header__title { 25 | flex: 1 1; 26 | 27 | display: block; 28 | overflow: hidden; 29 | white-space: nowrap; 30 | text-overflow: ellipsis; 31 | font-weight: 500; 32 | } 33 | .action-header > span.action-header__title:first-child, 34 | .action-header__sticky > span.action-header__title:first-child { 35 | padding-left: var(--side-padding); 36 | } 37 | html[dir="rtl"] .action-header > span.action-header__title:first-child, 38 | html[dir="rtl"] .action-header__sticky > span.action-header__title:first-child { 39 | padding-right: var(--side-padding); 40 | padding-left: unset; 41 | } -------------------------------------------------------------------------------- /css/components/notification.css: -------------------------------------------------------------------------------- 1 | #notificationPanel .po__content-body { 2 | padding: 0 !important; 3 | } 4 | 5 | .noti-base { 6 | display: grid; 7 | grid-template-columns: auto 1fr auto; 8 | grid-template-rows: min-content min-content min-content; 9 | grid-template-areas: 10 | 'n-img n-title n-cross' 11 | 'n-img n-content n-content' 12 | 'n-img n-buttons n-buttons'; 13 | grid-column-gap: 16px; 14 | border-bottom: 1px solid var(--bc-secondary-low); 15 | padding: var(--side-padding); 16 | } 17 | 18 | .noti-img { 19 | grid-area: n-img; 20 | background-color: var(--bc-secondary-low); 21 | height: 32px; 22 | width: 32px; 23 | display: grid; 24 | place-items: center; 25 | border-radius: 50%; 26 | } 27 | .noti-img > img { 28 | width: 20px; 29 | height: 20px; 30 | padding: 2px; 31 | } 32 | .noti-title { 33 | grid-area: n-title; 34 | display: flex; 35 | align-items: center; 36 | min-height: 32px; 37 | } 38 | .noti-cross { 39 | grid-area: n-cross; 40 | width: 32px; 41 | height: 32px; 42 | padding: 0 8px; 43 | cursor: pointer; 44 | border-radius: 8px; 45 | } 46 | .noti-content { 47 | grid-area: n-content; 48 | } 49 | .noti-buttons { 50 | grid-area: n-buttons; 51 | display: flex; 52 | flex-wrap: wrap; 53 | margin-top: 8px; 54 | } 55 | .noti-buttons > [class^="i-btn"] { 56 | margin-right: 8px; 57 | padding: 0 12px; 58 | height: 28px; 59 | border-radius: 28px; 60 | font-size: var(--fs-sm); 61 | } -------------------------------------------------------------------------------- /css/components/pw-po.css: -------------------------------------------------------------------------------- 1 | /*------ popup-window | popup-overlay ------*/ 2 | .pw__base, 3 | .po__base { 4 | position: absolute; 5 | top: 0; 6 | right: 0; 7 | width: 100%; 8 | height: 100%; 9 | z-index: 101; 10 | 11 | background-color: var(--bc-secondary); 12 | overflow: hidden; 13 | display: grid; 14 | grid-template-columns: calc(100% - var(--pw-drawer-width)) var(--pw-drawer-width); 15 | grid-template-rows: var(--pw-header-height) calc(100% - var(--pw-header-height)); 16 | grid-template-areas: 17 | 'pw__header pw__header' 18 | 'pw__content pw__drawer'; 19 | } 20 | .po__base { 21 | display: none; 22 | position: fixed; 23 | max-width: 400px; 24 | transition: transform 200ms ease-in-out; 25 | transform: translateX(100%); 26 | grid-template-columns: 100%; 27 | grid-template-areas: 28 | 'po__header' 29 | 'po__content'; 30 | } 31 | .po__active { 32 | transform: translateX(0); 33 | box-shadow: -8px 0 16px 0 rgba(0,0,0,.2); 34 | } 35 | 36 | .pw__header, 37 | .po__header { 38 | grid-area: pw__header; 39 | z-index: 99; 40 | width: inherit; 41 | padding: 0 var(--side-padding); 42 | background-color: var(--bc-secondary); 43 | } 44 | .po__header { 45 | grid-area: po__header; 46 | padding-left: 0; 47 | border-bottom: 1px solid var(--bc-secondary-hover); 48 | } 49 | html[dir="rtl"] .po__header { 50 | padding-right: 0; 51 | padding-left: var(--side-padding); 52 | } 53 | .pw__esc, 54 | .po__esc { 55 | margin-left: var(--side-padding); 56 | border: 1.4px solid var(--tc-secondary-low); 57 | border-radius: 24px; 58 | padding: 0 16px; 59 | cursor: pointer; 60 | } 61 | html[dir="rtl"] .pw__esc, 62 | html[dir="rtl"] .po__esc { margin-left: 0; margin-right: var(--side-padding); } 63 | 64 | .pw__content, 65 | .po__content { 66 | grid-area: pw__content; 67 | 68 | display: flex; 69 | flex-direction: column; 70 | position: relative 71 | } 72 | .po__content { 73 | grid-area: po__content; 74 | } 75 | .pw__content-body, 76 | .po__content-body { 77 | flex-basis: calc(100% - var(--side-padding) - var(--floatbar-height) / 2); 78 | padding: var(--side-padding); 79 | padding-bottom: 0; 80 | overflow: hidden; 81 | overflow-y: scroll; 82 | } 83 | .po__content-body { overflow-y: auto; } 84 | .pw__content-body:only-child, 85 | .po__content-body:only-child { flex-basis: 100%; } 86 | .pw__content-body::after, 87 | .po__content-body::after { 88 | content: ""; 89 | display: block; 90 | height: calc(var(--side-padding) + var(--floatbar-height) / 2); 91 | } 92 | .pw__content > .pw__floatbar { 93 | width: calc(100% - 2 * var(--side-padding)); 94 | height: var(--floatbar-height); 95 | position: absolute; 96 | left: var(--side-padding); 97 | bottom: var(--side-padding); 98 | 99 | background-color: var(--bc-secondary); 100 | box-shadow: var(--floatbar-shadow); 101 | border-radius: 8px; 102 | 103 | display: flex; 104 | align-items: center; 105 | } 106 | .pw__content > .pw__floatbar > div { 107 | width: var(--floatbar-height); 108 | height: var(--floatbar-height); 109 | display: flex; 110 | justify-content: center; 111 | align-items: center; 112 | cursor: pointer; 113 | border-radius: 8px; 114 | 115 | position: relative; 116 | } 117 | 118 | .pw__content > .pw__floatbar > input, 119 | .pw__content > .pw__floatbar > form, 120 | .pw__content > .pw__floatbar > form > input { 121 | flex: 1 1; 122 | 123 | min-width: 0; 124 | padding: 0 var(--side-padding); 125 | height: var(--floatbar-height); 126 | border: none; 127 | display: flex; 128 | } 129 | .pw__content > .pw__floatbar > form { padding: 0; } 130 | .pw__drawer { 131 | grid-area: pw__drawer; 132 | 133 | overflow: hidden; 134 | overflow-y: auto; 135 | } 136 | .pw__drawer > .action-header__sticky { 137 | background-color: var(--bc-secondary); 138 | } 139 | .pw__drawer__content { 140 | padding: var(--side-padding); 141 | padding-top: 0; 142 | } 143 | .pw__drawer__content > a { 144 | display: block; 145 | overflow: hidden; 146 | white-space: nowrap; 147 | text-overflow: ellipsis; 148 | } 149 | 150 | 151 | @media screen and (max-width: 750px) { 152 | 153 | .pw__base { 154 | grid-template-areas: 155 | 'pw__header pw__header' 156 | 'pw__content pw__content' 157 | } 158 | .pw__header, 159 | .po__header { 160 | box-shadow: var(--floatbar-shadow); 161 | border-bottom: none; 162 | padding: 0 !important; 163 | } 164 | .pw__drawer { 165 | position: absolute; 166 | top: 0; 167 | right: 0; 168 | z-index: 101; 169 | width: var(--pw-drawer-width); 170 | height: 100%; 171 | 172 | background-color: var(--bc-secondary); 173 | transition: transform 200ms ease-in-out, 174 | box-shadow 200ms ease-in-out; 175 | transform: translateX(100%); 176 | box-shadow: none; 177 | } 178 | .pw__drawer__active { 179 | transform: translateX(0); 180 | box-shadow: -8px 0 16px 0 rgba(0,0,0,.2); 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /css/layouts/logs.css: -------------------------------------------------------------------------------- 1 | .lt-row { 2 | padding: var(--side-padding); 3 | border-bottom: 1px solid var(--bc-secondary-hover); 4 | 5 | display: grid; 6 | grid-gap: 8px; 7 | grid-template-columns: 50px 100px 80px 120px auto 170px; 8 | grid-template-areas: 9 | 'lt__sno lt__user lt__action lt__wiki lt__title lt__date'; 10 | } 11 | 12 | .lt__sno { grid-area: lt__sno; } 13 | .lt__user { grid-area: lt__user; } 14 | .lt__action { grid-area: lt__action; text-transform: lowercase; } 15 | .lt__wiki { grid-area: lt__wiki; } 16 | .lt__title { grid-area: lt__title; } 17 | .lt__date { grid-area: lt__date; text-align: right; } 18 | .lt-row > div { word-break: break-word; } 19 | 20 | .lt__user, .lt__action, .lt__wiki { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } 21 | 22 | @media screen and (max-width: 1024px) { 23 | .lt-row { 24 | grid-template-columns: 50px 100px auto; 25 | grid-template-rows: auto auto auto; 26 | grid-template-areas: 27 | 'lt__sno lt__user lt__title' 28 | 'lt__sno lt__action lt__title' 29 | 'lt__sno lt__wiki lt__date'; 30 | } 31 | .lt__date { text-align: left; } 32 | } 33 | 34 | .logBox-control { 35 | padding: var(--side-padding); 36 | display: flex; 37 | justify-content: space-between; 38 | } 39 | #actionSelector { 40 | padding: 0 var(--side-padding); 41 | height: 100%; 42 | background-color: transparent; 43 | border-radius: 0; 44 | } -------------------------------------------------------------------------------- /css/layouts/talk.css: -------------------------------------------------------------------------------- 1 | .talk-svg:only-child { display: flex !important; } 2 | .talk-svg { 3 | margin-top: 200px; 4 | display: none; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | opacity: .3; 9 | } 10 | .phrase-talk { 11 | margin-bottom: 16px; 12 | overflow: hidden; 13 | white-space: nowrap; 14 | 15 | display: grid; 16 | grid-template-columns: 0fr 0fr 1fr; 17 | grid-template-rows: auto auto; 18 | grid-gap: 0px var(--side-padding); 19 | grid-template-areas: 20 | 'phrase-cap phrase2 phrase1' 21 | 'phrase-cap phrase3 phrase3'; 22 | } 23 | .phrase-talk > * { 24 | white-space: normal; 25 | } 26 | .phrase-cap { 27 | grid-area: phrase-cap; 28 | width: 40px; 29 | height: 40px; 30 | border-radius: 50%; 31 | color: white; 32 | font-size: var(--fs-md); 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | overflow: hidden; 37 | } 38 | .phrase-line1, 39 | .phrase-line2 { 40 | white-space: nowrap; 41 | display: flex; 42 | align-items: center; 43 | } 44 | .phrase-line1 { 45 | grid-area: phrase1; 46 | } 47 | .phrase-line2 { 48 | grid-area: phrase2; 49 | cursor: pointer; 50 | } 51 | .phrase-line3 { 52 | grid-area: phrase3; 53 | } 54 | .phrase-line3 a { 55 | text-decoration: underline; 56 | } 57 | .days-ago-talk { 58 | margin: 0 0 var(--side-padding) 0; 59 | text-align: center; 60 | display: flex; 61 | align-items: center; 62 | text-transform: uppercase; 63 | } 64 | .days-ago-talk:not(:nth-child(2)) { 65 | margin-top: 24px 66 | } 67 | 68 | .days-ago-talk::after { 69 | content: ""; 70 | height: 1px; 71 | background-color: var(--bc-secondary-low); 72 | flex: 1; 73 | margin-left: 8px 74 | } 75 | 76 | /*----------usernames---------*/ 77 | .user-count-header { 78 | margin-top: 12px; 79 | margin-bottom: 8px; 80 | display: flex; 81 | align-items: center; 82 | } 83 | .user-count-header > .count-line { 84 | flex: 1; 85 | height: 1px; 86 | background: var(--bc-secondary-hover); 87 | margin-left: 8px; 88 | } 89 | .user-list > div { 90 | margin-bottom: 4px; 91 | } 92 | .user-container { 93 | display: flex; 94 | } 95 | .user-talk { 96 | display: block; 97 | text-overflow: ellipsis; 98 | overflow: hidden; 99 | white-space: nowrap; 100 | color: var(--tc-secondary); 101 | cursor: pointer; 102 | flex: 1; 103 | } 104 | .user-talk-CA { 105 | color: var(--link-color); 106 | } -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300italic.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300italic.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300italic.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-300italic.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500italic.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500italic.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500italic.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-500italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-500italic.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700italic.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700italic.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700italic.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-700italic.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900italic.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900italic.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900italic.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-900italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-900italic.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-italic.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-italic.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-italic.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-italic.woff2 -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-regular.eot -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-regular.ttf -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-regular.woff -------------------------------------------------------------------------------- /fonts/roboto-v20-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/fonts/roboto-v20-latin-regular.woff2 -------------------------------------------------------------------------------- /git-pull.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /git-pull2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /i18n/ce.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Исмаил Садуев", 5 | "Умар" 6 | ] 7 | }, 8 | "tooltip-home": "ЦӀа [esc]", 9 | "tooltip-talk": "Дийцар [t]", 10 | "tooltip-logs": "Журналаш [l]", 11 | "tooltip-logout": "ЧугӀо [u]", 12 | "tooltip-notification": "ДӀахаийтарш [n]", 13 | "tooltip-settings": "Йукъара нисдаран гӀирсаш [s]", 14 | "tooltip-m-sidebar": "АгӀонгара панель", 15 | "tooltip-m-next-difference": "РогӀера дифф", 16 | "tooltip-m-queue": "РогӀе", 17 | "tooltip-m-notification": "ДӀахаийтарш", 18 | "tooltip-more-options": "Дукха таронаш", 19 | "settings-language": "Мотт", 20 | "settings-language-region": "Регион", 21 | "settings-sound": "Аз", 22 | "settings-beta": "Бета", 23 | "settings-beta-tester": "Схьайиллина бета-верси", 24 | "presets-default-title": "Ӏадйитаран кеп", 25 | "presets-enter-placeholder": "Enter", 26 | "presets-button-create": "Кхолла", 27 | "presets-title": "ЦӀе", 28 | "presets-registered": "ДӀабазбелларш", 29 | "presets-anons": "Анонимаш", 30 | "presets-new": "Керла агӀонаш", 31 | "presets-new-desc": "АгӀонаш кхоллар латаде", 32 | "presets-only-new": "Керла агӀонаш бен", 33 | "presets-save": "Ӏалашйе", 34 | "presets-restore": "МеттахӀоттайе", 35 | "presets-delete-q": "ДӀайаккха $1 пресет?", 36 | "presets-create": "Пресет кхоллар", 37 | "presets-invalid-title": "Ца магайо цӀе", 38 | "diff-info-user": "Декъашхо:", 39 | "diff-info-title": "ЦӀе:", 40 | "diff-info-wiki": "Вики:", 41 | "diff-info-comment": "Коммент:", 42 | "diff-info-namespace": "ЦӀерийн меттиг:", 43 | "diff-mo-guc": "Глобалан къинхьегам", 44 | "diff-mo-es": "Код нисйан", 45 | "notifications-img": "ДӀахаийтарш", 46 | "notifications-title": "ДӀахаийтарш", 47 | "tooltip-po-close": "ДӀачӀагӀа [esc]", 48 | "po-img-cross": "ДӀачӀагӀа", 49 | "dialog-img-close": "ДӀачӀагӀа", 50 | "logs-no-more": "ДӀайаздарш кхий дац.", 51 | "logs-cols-n": "№", 52 | "logs-cols-user": "Декъашхо", 53 | "logs-cols-action": "Ардамаш", 54 | "logs-cols-wiki": "Вики", 55 | "logs-cols-title": "АгӀо", 56 | "logs-cols-date": "Терахь", 57 | "logs-title": "Журналаш", 58 | "tooltip-logs-refresh": "Карлайаккха", 59 | "logs-img-reload": "Карлайаккха", 60 | "logs-prev": "Хьалхара", 61 | "logs-next": "РогӀера", 62 | "tooltip-logs-search": "Лаха", 63 | "logs-img-search": "Лаха", 64 | "logs-action-rollback": "Йухайаккха", 65 | "logs-action-undo": "Йухадаккхар", 66 | "logs-action-edit": "Нисйар", 67 | "logs-action-warn": "ДӀахьедар", 68 | "logs-action-delete": "ДӀайаккха", 69 | "logs-action-report": "Блоктохар дехар", 70 | "logs-action-protect": "Ларйар дехар", 71 | "pw-img-drawer": "Йаьшка", 72 | "talk-today": "Тахана", 73 | "talk-yesterday": "Селхана", 74 | "talk-title": "Дийцар", 75 | "talk-img-cross": "ДӀачӀагӀа", 76 | "tooltip-talk-people": "Декъашхой", 77 | "talk-img-people": "Декъашхой", 78 | "talk-img-app": "SWViewer", 79 | "talk-no-messages": "Хаамаш бац", 80 | "talk-people": "Декъашхой", 81 | "talk-people-online": "Онлайн", 82 | "talk-people-offline": "Онлайнехь вац(йац)", 83 | "talk-send-placeholder": "ХӀу йаздан лаьа хьуна?", 84 | "tooltip-talk-send": "ДӀадахьийта", 85 | "talk-img-send": "ДӀадахьийта", 86 | "nc-unlogin-progress": "Арадолу...", 87 | "nc-unlogin-title": "Аравала(йала)", 88 | "nc-unlogin-q": "Хьо тешна вуй?", 89 | "settings-sound-none": "ХӀан-хӀа", 90 | "settings-sound-all": "Дерриге аьзнаш", 91 | "view-latest": "Хьажа", 92 | "autoreport-title": "Авто дехар", 93 | "report-title": "Дехар", 94 | "error-edit": "Тадаран гӀалат: $1", 95 | "custom-revert-placeholder": "Йазде бахьана.", 96 | "custom-revert-button": "Йухайаккха", 97 | "welcome-frame-edit": "Нисдарш", 98 | "welcome-frame-warn": "ДӀахьедар", 99 | "welcome-frame-del": "ДӀайаккха", 100 | "welcome-frame-protect": "Ларйар", 101 | "welcome-frame-report": "Дехар", 102 | "welcome-frame-total": "Йерриге", 103 | "new-page-frame-not-exist": "Кхоьллина йац", 104 | "new-page-frame-new": "Керла агӀо йаьсса кхоьллина", 105 | "about-frame-cookies-title": "Куки", 106 | "about-frame-licensing": "Лицензи", 107 | "about-frame-translating": "Гочдар", 108 | "about-frame-translators-list": "Гочдархойн могӀам:", 109 | "about-frame-privacy-title": "Къайлаха", 110 | "about-frame-data-username": "Декъашхочун цӀе", 111 | "about-frame-data-talk": "Чатехь хаам", 112 | "about-frame-data-access": "ТӀаьххьара чудаьлла терахь", 113 | "page-title": "Версийн башхалла", 114 | "welcome-page-title": "Маршаллин агӀо", 115 | "login-welcome": "Марша догӀийла!", 116 | "login-oauth": "OAuth гӀоьнца чудовлар", 117 | "img-message": "Хаам", 118 | "img-logos": "Журналаш", 119 | "img-logout": "Аравала(йала)", 120 | "img-notification": "ДӀахаийтарш", 121 | "img-thank": "Баркалла", 122 | "img-edit": "Нисйан", 123 | "img-options": "Дукха таронаш", 124 | "img-plus": "ТӀетоха", 125 | "img-next": "РогӀера дифф", 126 | "img-drawer": "РогӀе", 127 | "img-save": "Ӏалашйе", 128 | "cancel": "Йухайаккхар", 129 | "alright": "Кхетта", 130 | "delete": "ДӀайаккха" 131 | } 132 | -------------------------------------------------------------------------------- /i18n/da.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Saederup92", 5 | "Zakawer2" 6 | ] 7 | }, 8 | "tooltip-talk": "Diskussion [t]", 9 | "tooltip-m-queue": "Kø", 10 | "tooltip-edit-source": "Rediger kilde [r]", 11 | "settings-title": "Indstillinger", 12 | "settings-theme": "Tema", 13 | "settings-language": "Sprog", 14 | "settings-sound": "Lyd", 15 | "settings-revisions-all": "Vis alle", 16 | "settings-control-panel": "Kontrolpanel", 17 | "queue-empty-msg": "Køen er tom", 18 | "presets-default-title": "Standard", 19 | "presets-button-create": "Opret", 20 | "presets-title": "Titel", 21 | "presets-registered": "Registreret", 22 | "presets-anons": "Anonym", 23 | "presets-new": "Nye sider", 24 | "presets-only-new": "Kun nye sider", 25 | "presets-wikis-wl": "Liste over wikier som skal springes over", 26 | "presets-users-wl": "Liste over brugere som skal springes over", 27 | "presets-save": "Gem", 28 | "presets-restore": "Gendan", 29 | "presets-invalid-title": "Ugyldig titel", 30 | "diff-info-user": "Bruger:", 31 | "diff-info-title": "Titel:", 32 | "diff-info-comment": "Kommentar:", 33 | "diff-info-namespace": "Navnerum:", 34 | "diff-mo-fetching": "Henter", 35 | "diff-mo-srg": "SRG", 36 | "diff-mo-vh": "Vis historik", 37 | "diff-mo-es": "Rediger kilde", 38 | "po-img-cross": "Luk", 39 | "dialog-img-close": "Luk", 40 | "logs-cols-user": "Bruger", 41 | "logs-cols-action": "Handling", 42 | "logs-cols-wiki": "Wiki", 43 | "logs-cols-title": "Titel", 44 | "logs-cols-date": "Dato", 45 | "logs-prev": "Forrige", 46 | "logs-next": "Næste", 47 | "logs-img-search": "Søg", 48 | "logs-action-all": "Alle handlinger", 49 | "logs-action-undo": "Fortryd", 50 | "logs-action-edit": "Rediger", 51 | "logs-action-delete": "Slet", 52 | "logs-action-protect": "Beskyt", 53 | "pw-img-drawer": "Skuffe", 54 | "talk-today": "I dag", 55 | "talk-yesterday": "I går", 56 | "talk-title": "Diskussion", 57 | "talk-img-cross": "Luk", 58 | "talk-no-messages": "Ingen beskeder", 59 | "talk-send-placeholder": "Hvad har du på hjertet?", 60 | "tooltip-talk-send": "Send", 61 | "talk-img-send": "Send", 62 | "nc-unlogin-q": "Er du sikker?", 63 | "settings-sound-none": "Ingen", 64 | "settings-sound-all": "Alle lyde", 65 | "load-history": "Indlæs historik", 66 | "patrol-success-title": "Revision blev markeret som accepteret", 67 | "patrol-success-content": "Revision $1 blev markeret som accepteret", 68 | "patrol-fail-title": "Det lykkedes ikke at acceptere revision", 69 | "tooltip-patrol": "Accepter revision", 70 | "img-patrol": "Accepter revision", 71 | "error-network": "Netværksfejl", 72 | "warn-user-title": "Advar bruger", 73 | "edit-source-title": "Rediger kilde", 74 | "welcome-frame-title": "Velkommen", 75 | "welcome-frame-button": "Søg", 76 | "welcome-frame-placeholder": "Søg bruger", 77 | "welcome-frame-rollback": "Tilbagerulning", 78 | "welcome-frame-undo": "Fortryd", 79 | "welcome-frame-edit": "Redigér", 80 | "welcome-frame-del": "Slet", 81 | "welcome-frame-protect": "Beskyt", 82 | "welcome-frame-reminder": "Påmindelse", 83 | "welcome-frame-links": "Eksterne henvisninger", 84 | "welcome-frame-translation": "Oversættelsesværktøjer:", 85 | "new-page-frame-new": "Ny side er tom", 86 | "about-frame-doc": "Se [$1|dokumentationen].", 87 | "about-frame-translating": "Oversættelse", 88 | "about-frame-translators-list": "Liste over oversættere:", 89 | "about-frame-privacy-title": "Fortrolighed", 90 | "about-frame-data-username": "Brugernavn", 91 | "welcome-page-title": "Velkomstside", 92 | "login-welcome": "Velkommen!", 93 | "img-message": "Besked", 94 | "img-about": "Om", 95 | "img-settings": "Indstillinger", 96 | "img-edit": "Redigér", 97 | "img-plus": "Tilføj", 98 | "img-drawer": "Kø", 99 | "img-save": "Gem", 100 | "cancel": "Fortryd", 101 | "about": "Om", 102 | "delete": "Slet" 103 | } 104 | -------------------------------------------------------------------------------- /i18n/el.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Fotis A." 5 | ] 6 | }, 7 | "tooltip-edit-preset": "Ρυθμίσεις ουράς", 8 | "tooltip-home": "Αρχική σελίδα [esc]", 9 | "tooltip-talk": "Συζήτηση [t]", 10 | "tooltip-logs": "Αρχεία καταγραφής [l]", 11 | "tooltip-logout": "Αποσύνδεση [u]", 12 | "tooltip-notification": "Ειδοποιήσεις [n]", 13 | "tooltip-settings": "Γενικές ρυθμίσεις [s]", 14 | "tooltip-m-sidebar": "Πλαϊνή γραμμή", 15 | "tooltip-m-next-difference": "Επόμενη διαφορά", 16 | "tooltip-m-queue": "Ουρά", 17 | "tooltip-m-notification": "Ειδοποιήσεις", 18 | "tooltip-copy-link": "Αντιγραφή συνδέσμου διεύθυνσης", 19 | "tooltip-thank": "Στείλτε μια ευχαριστήρια ειδοποίηση", 20 | "tooltip-edit-source": "Επεξεργασία πηγής [e]", 21 | "tooltip-more-options": "Περισσότερες επιλογές", 22 | "tooltip-open-browser": "Άνοιγμα στο παράθυρο του προγράμματος περιήγησης [o]", 23 | "tooltip-speedy-del": "Πίνακας ετικετών [d]", 24 | "tooltip-custom-rollback": "Επαναφορά με σύνοψη [y]", 25 | "tooltip-rollback": "Γρήγορη επαναφορά [r]", 26 | "tooltip-last-diff": "Προηγούμενη διαφορά [Αριστερή αγκύλη ή p]", 27 | "tooltip-publish-changes": "Δημοσίευση αλλαγών", 28 | "settings-confirm-lang": "Για να εφαρμόσετε αλλαγές γλώσσας, πρέπει να φορτώσετε ξανά την εφαρμογή.", 29 | "settings-title": "Ρυθμίσεις", 30 | "settings-theme": "Θέμα", 31 | "settings-theme-descr": "Αλλαγή θέματος διεπαφής εργαλείου.", 32 | "settings-language": "Γλώσσα", 33 | "settings-language-descr": "Αλλαγή γλώσσας διεπαφής;", 34 | "settings-language-region": "Περιοχή", 35 | "settings-language-region-descr": "Ρυθμίστε την περιοχή ώστε να εμφανίζει αριθμούς και ημερομηνίες σε τοπική μορφή.", 36 | "settings-sound": "Ήχος", 37 | "settings-sound-descr": "Αλλάξτε τη λειτουργία ήχου για εισερχόμενες επεξεργασίες και μηνύματα στη συζήτηση.", 38 | "settings-revisions": "Πολλαπλές διαφορές", 39 | "settings-revisions-descr": "Ορίστε ειδοποίηση ή ανοίξτε όλες τις διαδοχικές αλλαγές από τον ίδιο χρήστη ταυτόχρονα.", 40 | "settings-revisions-onlylast": "Μόνο τελευταία", 41 | "settings-revisions-alert": "Ειδοποίηση κατά την επαναφορά", 42 | "settings-revisions-all": "Εμφάνιση όλων", 43 | "settings-direction": "Από κάτω προς τα πάνω", 44 | "settings-direction-descr": "Εμφάνιση αλλαγών από κάτω προς τα πάνω στην ουρά.", 45 | "settings-rh-mode": "Τοποθεσία ουράς", 46 | "settings-rh-mode-descr": "Εμφάνιση θέσης ουράς στη δεξιά πλευρά της οθόνης.", 47 | "settings-terminate-stream": "Τερματισμός ροής", 48 | "settings-terminate-stream-descr": "Τερματίστε τη ροή πρόσφατων αλλαγών όταν φτάσει το όριο της ουράς.", 49 | "settings-jumps": "Μετάβαση στην αλλαγή", 50 | "settings-jumps-descr": "Εάν είναι ενεργοποιημένη, η εστίαση SWViewer θα μεταπηδήσει απευθείας για να αλλάξει κατά το άνοιγμα της διαφοράς από την ουρά.", 51 | "settings-hotkeys": "Πλήκτρα συντόμευσης", 52 | "settings-hotkeys-descr": "Ενεργοποιήστε τα [ $1 |πλήκτρα πρόσβασης] για να χειριστείτε το SWViewer με πληκτρολόγιο.", 53 | "settings-limit": "Όριο ουράς", 54 | "settings-limit-descr": "Μέγιστος αριθμός αλλαγών που επιτρέπεται να φορτωθούν στην ουρά.", 55 | "settings-limit-placeholder": "Χωρίς όριο", 56 | "settings-control": "Εργαλεία προγραμματιστών", 57 | "settings-control-panel": "Πίνακας Ελέγχου", 58 | "settings-service": "Υπηρεσία", 59 | "settings-beta": "Δοκιμαστική έκδοση", 60 | "settings-beta-tester": "Ανοίξτε την έκδοση beta", 61 | "queue-empty-msg": "Η ουρά είναι άδεια", 62 | "presets-default-title": "Προεπιλογή", 63 | "presets-enter-placeholder": "Εισάγω", 64 | "presets-button-create": "Δημιουργία", 65 | "presets-title": "Τίτλος", 66 | "presets-registered": "Εγγεγραμμένοι", 67 | "presets-registered-desc": "Ενεργοποιήστε τις αλλαγές από εγγεγραμμένους χρήστες.", 68 | "presets-anons": "Μη εγγεγραμμένοι", 69 | "presets-anons-desc": "Ενεργοποίηση αλλαγών από μη εγγεγραμμένους χρήστες.", 70 | "presets-new": "Νέες σελίδες", 71 | "presets-new-desc": "Ενεργοποιήστε τις επεξεργασίες που είναι δημιουργίες νέων σελίδων.", 72 | "presets-only-new": "Μόνο νέες σελίδες", 73 | "presets-only-new-desc": "Εμφάνιση μόνο αλλαγών δημιουργίας νέων σελίδων.", 74 | "presets-edits-limit": "Όριο επεξεργασιών", 75 | "presets-edits-limit-desc": "Ο αριθμός των επεξεργασιών μετά τις οποίες θα παραβλεφθούν οι επεξεργασίες ενός χρήστη.", 76 | "presets-edits-limit-placeholder": "Μέγιστες επεξεργασίες", 77 | "presets-days-limit": "Όριο ημερών", 78 | "presets-days-limit-desc": "Ο αριθμός των επεξεργασιών μετά τις οποίες θα παραβλεφθούν οι επεξεργασίες ενός χρήστη.", 79 | "presets-days-limit-placeholder": "Μέγιστες ημέρες", 80 | "presets-ores-filter-desc": "Φιλτράρετε τις επεξεργασίες βάσει βαθμολογίας LiftWing και ORES.", 81 | "presets-sw": "Μικρά wiki", 82 | "presets-sw-desc": "Ενεργοποιήστε τις επεξεργασίες από μικρά wiki.", 83 | "presets-additional": "Πρόσθετοι σύνδεσμοι", 84 | "presets-additional-desc": "Ενεργοποιήστε τις αλλαγές από [ $1 |wikis] με λιγότερους από 300 ενεργούς χρήστες.", 85 | "presets-custom": "Προσαρμοσμένα wiki", 86 | "presets-custom-desc": "Προσθέστε το τοπικό-wiki σας ή τα wiki που δεν βρίσκονται σε μικρή λίστα wiki. Παράδειγμα: enwiki", 87 | "presets-langset": "Γλώσσες", 88 | "presets-langset-desc": "Ρυθμίστε τις γλώσσες για να λαμβάνετε αλλαγές σε συγκεκριμένες γλώσσες. Παράδειγμα: en", 89 | "presets-wikis-wl": "Λίστα wikis προς παράβλεψη", 90 | "presets-wikis-wl-desc": "Προσθέστε wiki για να παραλείψετε τις επεξεργασίες τους από την ουρά. Παράδειγμα: enwiki", 91 | "presets-users-wl": "Λίστα χρηστών προς παράβλεψη", 92 | "presets-users-wl-desc": "Προσθέστε χρήστες για να παραλείψετε τις αλλαγές τους από την ουρά. Παράδειγμα: JohnDoe", 93 | "presets-save": "Αποθήκευση", 94 | "presets-restore": "Επαναφορά", 95 | "presets-delete-q": "Διαγραφή προεπιλογής $1 ;", 96 | "presets-default-q": "Δεν σας συνιστούμε να διαγράψετε την προεπιλεγμένη προεπιλογή!" 97 | } 98 | -------------------------------------------------------------------------------- /i18n/fi.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Huusmik", 5 | "Joquliina", 6 | "MITO", 7 | "Nike", 8 | "Pyscowicz", 9 | "Yupik" 10 | ] 11 | }, 12 | "tooltip-home": "Etusivu [esc]", 13 | "tooltip-logs": "Lokit [l]", 14 | "tooltip-logout": "Kirjaudu ulos [u]", 15 | "tooltip-notification": "Ilmoitukset [n]", 16 | "tooltip-settings": "Yleiset asetukset [s]", 17 | "tooltip-m-sidebar": "Sivupalkki", 18 | "tooltip-m-notification": "Ilmoitukset", 19 | "tooltip-copy-link": "Kopioi linkin osoite", 20 | "tooltip-edit-source": "Muokkaa wikitekstiä", 21 | "tooltip-publish-changes": "Julkaise muutokset", 22 | "settings-title": "Asetukset", 23 | "settings-theme": "Teema", 24 | "settings-language": "Kieli", 25 | "settings-language-descr": "Vaihda käyttöliittymän kieli", 26 | "settings-language-region": "Alue", 27 | "settings-sound": "Ääni", 28 | "settings-revisions-all": "Näytä kaikki", 29 | "settings-hotkeys": "Pikanäppäimet", 30 | "settings-service": "Palvelu", 31 | "settings-beta": "Beeta", 32 | "settings-beta-tester": "Avaa beetaversio", 33 | "presets-default-title": "Oletus", 34 | "presets-button-create": "Luo", 35 | "presets-title": "Otsikko", 36 | "presets-anons": "Anonyymi", 37 | "presets-anons-desc": "Salli muutokset anonyymeiltä käyttäjiltä.", 38 | "presets-new": "Uudet sivut", 39 | "presets-save": "Tallenna", 40 | "presets-restore": "Palauta", 41 | "diff-info-user": "Käyttäjä:", 42 | "diff-info-title": "Otsikko:", 43 | "diff-info-wiki": "Wiki:", 44 | "diff-info-comment": "Kommentti:", 45 | "diff-info-namespace": "Nimiavaruus:", 46 | "diff-mo-vh": "Näytä historia", 47 | "diff-mo-es": "Muokkaa wikitekstiä", 48 | "notifications-empty": "Ei ilmoituksia", 49 | "notifications-img-clear": "Tyhjennä kaikki ilmoitukset", 50 | "notifications-img": "Ilmoitukset", 51 | "notifications-title": "Ilmoitukset", 52 | "tooltip-po-close": "Sulje [esc]", 53 | "po-img-cross": "Sulje", 54 | "dialog-img-close": "Sulje", 55 | "logs-cols-user": "Käyttäjä", 56 | "logs-title": "Lokit", 57 | "logs-prev": "Edellinen", 58 | "logs-next": "Seuraava", 59 | "logs-action-undo": "Kumoa", 60 | "talk-today": "Tänään", 61 | "talk-yesterday": "Eilen", 62 | "talk-title": "Keskustelu", 63 | "talk-img-cross": "Sulje", 64 | "talk-no-messages": "Ei viestejä", 65 | "nc-unlogin-progress": "Uloskirjautuminen käynnissä...", 66 | "nc-unlogin-title": "Kirjaudu ulos", 67 | "nc-unlogin-q": "Oletko varma?", 68 | "settings-sound-all": "Kaikki äänet", 69 | "error-network": "Verkkovirhe", 70 | "error-edit": "Muokkausvirhe: $1", 71 | "max-warn-title": "Viimeinen varoitus", 72 | "summary-title": "Yhteenveto", 73 | "tooltip-edit-form": "Sivun lähdekoodi", 74 | "tooltip-reason": "Syy", 75 | "welcome-frame-title": "Tervetuloa", 76 | "welcome-frame-button": "Hae", 77 | "welcome-frame-rollback": "Palauta", 78 | "welcome-frame-undo": "Kumoa", 79 | "welcome-frame-edit": "Muokkaa", 80 | "welcome-frame-warn": "Varoita", 81 | "welcome-frame-del": "Poista", 82 | "welcome-frame-protect": "Suojaa", 83 | "welcome-frame-links": "Ulkoiset linkit", 84 | "new-page-frame-new": "Uusi sivu on tyhjä", 85 | "about-frame-cookies-title": "Evästeet", 86 | "about-frame-licensing": "Lisensointi", 87 | "about-frame-translating": "Käännös", 88 | "about-frame-data": "Tietojen kerääminen", 89 | "about-frame-data-username": "Käyttäjänimi", 90 | "welcome-page-title": "Tervetulosivu", 91 | "login-welcome": "Tervetuloa!", 92 | "login-oauth": "OAuth-kirjautuminen", 93 | "img-message": "Viesti", 94 | "img-logout": "Kirjaudu ulos", 95 | "img-about": "Tietoja", 96 | "img-notification": "Ilmoitus", 97 | "img-settings": "Asetukset", 98 | "img-navigation": "Valikko", 99 | "img-thank": "Kiitä", 100 | "img-edit": "Muokkaa", 101 | "img-options": "Lisää valintoja", 102 | "img-plus": "Lisää", 103 | "img-copy": "Kopioi linkki", 104 | "img-browser": "Avaa uudessa välilehdessä", 105 | "img-custom-rb": "Mukautettu palautus", 106 | "img-rollback": "Palauta", 107 | "img-box": "Sivupalkki", 108 | "img-save": "Tallenna", 109 | "cancel": "Peruuta", 110 | "about": "Tietoja", 111 | "delete": "Poista" 112 | } 113 | -------------------------------------------------------------------------------- /i18n/kn.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Mahadevaiah Siddaiah", 5 | "ಮಲ್ನಾಡಾಚ್ ಕೊಂಕ್ಣೊ" 6 | ] 7 | }, 8 | "tooltip-talk": "ಚರ್ಚೆ [t]", 9 | "tooltip-logs": "ದಾಖಲೆಗಳು [l]", 10 | "tooltip-logout": "ಲಾಗೌಟ್ [u]", 11 | "tooltip-notification": "ಅಧಿಸೂಚನೆಗಳು [n]", 12 | "tooltip-m-next-difference": "ಮುಂದಿನ ವ್ಯತ್ಯಾಸ", 13 | "tooltip-m-queue": "ಸಾಲು", 14 | "tooltip-m-notification": "ಅಧಿಸೂಚನೆಗಳು", 15 | "tooltip-copy-link": "ಕೊಂಡಿ ವಿಳಾಸವನ್ನು ನಕಲು ಮಾಡು", 16 | "tooltip-edit-source": "ಮೂಲವನ್ನು ಸಂಪಾದಿಸು [e]", 17 | "tooltip-more-options": "ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳು", 18 | "tooltip-publish-changes": "ಬದಲಾವಣೆಗಳನ್ನು ಪ್ರಕಟಿಸು", 19 | "settings-title": "ವ್ಯವಸ್ಥೆಗಳು", 20 | "settings-theme": "ಥೀಮ್", 21 | "settings-language": "ಭಾಷೆ", 22 | "settings-sound": "ಧ್ವನಿ", 23 | "settings-revisions-all": "ಎಲ್ಲಾ ತೋರಿಸಿ", 24 | "settings-beta": "ಬೀಟಾ", 25 | "queue-empty-msg": "ಸಾಲು ಖಾಲಿಯಾಗಿದೆ", 26 | "presets-default-title": "ಮೂಲಸ್ಥಿತಿ", 27 | "presets-button-create": "ಸೃಷ್ಟಿಸು", 28 | "presets-title": "ಶೀರ್ಷಿಕೆ", 29 | "presets-registered": "ನೋಂದಾಯಿತ", 30 | "presets-anons": "ಅನಾಮಧೇಯ", 31 | "presets-new": "ಹೊಸ ಪುಟಗಳು", 32 | "presets-only-new": "ಹೊಸ ಪುಟಗಳು ಮಾತ್ರ", 33 | "presets-edits-limit-placeholder": "ಗರಿಷ್ಠ ಸಂಪಾದನೆಗಳು", 34 | "presets-sw": "ಸಣ್ಣ ವಿಕಿಗಳು", 35 | "presets-additional": "ಹೆಚ್ಚುವರಿ ವಿಕಿಗಳು", 36 | "presets-save": "ಉಳಿಸಿ", 37 | "presets-invalid-title": "ಅಮಾನ್ಯ ಶೀರ್ಷಿಕೆ", 38 | "diff-info-user": "ಬಳಕೆದಾರ:", 39 | "diff-info-title": "ಶೀರ್ಷಿಕೆ:", 40 | "diff-info-wiki": "ವಿಕಿ:", 41 | "diff-info-comment": "ಟಿಪ್ಪಣಿ:", 42 | "diff-info-namespace": "ನಾಮವರ್ಗ:", 43 | "diff-mo-guc": "ಜಾಗತಿಕ ಕಾಣಿಕೆಗಳು", 44 | "diff-mo-vh": "ಇತಿಹಾಸವನ್ನು ನೋಡಿ", 45 | "diff-mo-es": "ಮೂಲವನ್ನು ಸಂಪಾದಿಸು", 46 | "notifications-img": "ಅಧಿಸೂಚನೆಗಳು", 47 | "notifications-title": "ಅಧಿಸೂಚನೆಗಳು", 48 | "tooltip-po-close": "ಮುಚ್ಚಿ [esc]", 49 | "po-img-cross": "ಮುಚ್ಚಿ", 50 | "dialog-img-close": "ಮುಚ್ಚಿ", 51 | "logs-cols-user": "ಬಳಕೆದಾರ", 52 | "logs-cols-action": "ಕ್ರಿಯೆ", 53 | "logs-cols-wiki": "ವಿಕಿ", 54 | "logs-cols-title": "ಶೀರ್ಷಿಕೆ", 55 | "logs-cols-date": "ದಿನಾಂಕ", 56 | "logs-title": "ದಾಖಲೆಗಳು", 57 | "logs-prev": "ಹಿಂದಿನ", 58 | "logs-next": "ಮುಂದಿನ", 59 | "tooltip-logs-search": "ಹುಡುಕು", 60 | "logs-img-search": "ಹುಡುಕು", 61 | "logs-action-all": "ಎಲ್ಲಾ ಕ್ರಿಯೆಗಳು", 62 | "logs-action-edit": "ಸಂಪಾದಿಸಿ", 63 | "logs-action-delete": "ಅಳಿಸು", 64 | "logs-action-report": "ವರದಿ", 65 | "talk-today": "ಇಂದು", 66 | "talk-yesterday": "ನಿನ್ನೆ", 67 | "talk-title": "ಚರ್ಚೆ", 68 | "talk-img-cross": "ಮುಚ್ಚಿ", 69 | "tooltip-talk-people": "ಜನ", 70 | "talk-img-people": "ಜನ", 71 | "talk-people": "ಜನ", 72 | "talk-send-placeholder": "ನಿಮ್ಮ ಮನದಲ್ಲೇನಿದೆ?", 73 | "tooltip-talk-send": "ಕಳುಹಿಸಿ", 74 | "talk-img-send": "ಕಳುಹಿಸಿ", 75 | "nc-unlogin-error": "ಏನೋ ತಪ್ಪಾಯಿತು! ದಯವಿಟ್ಟು ನಿಮ್ಮ ಅಂತರ್ಜಾಲ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ.", 76 | "nc-unlogin-progress": "ಲಾಗೌಟ್ ಆಗುತ್ತಿದೆ...", 77 | "nc-unlogin-title": "ಲಾಗೌಟ್", 78 | "settings-sound-only-edits": "ಸಂಪಾದನೆಗಳು ಮಾತ್ರ", 79 | "error-network": "ನೆಟ್ವರ್ಕ್ ದೋಷ", 80 | "error-edit": "ಸಂಪಾದನೆ ದೋಷ: $1", 81 | "custom-revert-placeholder": "ಒಂದು ಕಾರಣವನ್ನು ಕೊಡಿ.", 82 | "custom-revert-button": "ಹಿಂದಿನಂತಾಗಿಸು", 83 | "common-summaries": "ಸಾಮಾನ್ಯ ಸಾರಾಂಶಗಳು:", 84 | "edit-source-title": "ಮೂಲವನ್ನು ಸಂಪಾದಿಸು", 85 | "summary-title": "ಸಾರಾಂಶ", 86 | "summary-placeholder": "ಸಂಕ್ಷಿಪ್ತವಾಗಿ ನಿಮ್ಮ ಬದಲಾವಣೆಗಳನ್ನು ತಿಳಿಸಿ.", 87 | "tooltip-edit-form": "ಪುಟದ ಮೂಲ ಕೋಡ್", 88 | "tooltip-reason": "ಕಾರಣ", 89 | "welcome-frame-title": "ಸುಸ್ವಾಗತ", 90 | "welcome-frame-button": "ಹುಡುಕು", 91 | "welcome-frame-edit": "ಸಂಪಾದಿಸಿ", 92 | "welcome-frame-del": "ಅಳಿಸು", 93 | "welcome-frame-total": "ಒಟ್ಟು", 94 | "new-page-frame-new": "ಹೊಸ ಪುಟ ಖಾಲಿಯಾಗಿದೆ", 95 | "about-frame-translating": "ಅನುವಾದ", 96 | "about-frame-translators-list": "ಅನುವಾದಕರ ಪಟ್ಟಿ:", 97 | "about-frame-privacy-title": "ಗೋಪ್ಯತೆ", 98 | "about-frame-data-username": "ಬಳಕೆದಾರರ ಹೆಸರು", 99 | "page-title": "ವ್ಯತ್ಯಾಸ", 100 | "login-welcome": "ಸುಸ್ವಾಗತ!", 101 | "img-message": "ಸಂದೇಶ", 102 | "img-logos": "ದಾಖಲೆಗಳು", 103 | "img-logout": "ಲಾಗೌಟ್", 104 | "img-about": "ಕುರಿತು", 105 | "img-notification": "ಅಧಿಸೂಚನೆ", 106 | "img-settings": "ವ್ಯವಸ್ಥೆಗಳು", 107 | "img-navigation": "ಸಂಚರಣೆ", 108 | "img-edit": "ಸಂಪಾದಿಸಿ", 109 | "img-options": "ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳು", 110 | "img-plus": "ಸೇರಿಸು", 111 | "img-next": "ಮುಂದಿನ ವ್ಯತ್ಯಾಸ", 112 | "img-drawer": "ಸಾಲು", 113 | "img-bell": "ಅಧಿಸೂಚನೆಯ ಗಂಟೆ", 114 | "img-browser": "ಹೊಸ ಟ್ಯಾಬ್‌ನಲ್ಲಿ ತೆರೆ", 115 | "img-save": "ಉಳಿಸಿ", 116 | "cancel": "ರದ್ದುಮಾಡಿ", 117 | "about": "ಕುರಿತು", 118 | "delete": "ಅಳಿಸು" 119 | } 120 | -------------------------------------------------------------------------------- /i18n/scn.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Ajeje Brazorf", 5 | "GianAntonucci", 6 | "Gmelfi" 7 | ] 8 | }, 9 | "tooltip-home": "Pàggina principali [esc]", 10 | "tooltip-talk": "Discussioni [t]", 11 | "tooltip-logs": "Riggistri [l]", 12 | "tooltip-logout": "Nesci [u]", 13 | "tooltip-notification": "Nutìfichi [n]", 14 | "tooltip-settings": "Mpustazzioni ginirali [s]", 15 | "tooltip-m-notification": "Nutìfichi", 16 | "tooltip-edit-source": "Cancia wikitestu [e]", 17 | "tooltip-more-options": "Àutri opzioni", 18 | "settings-title": "Mpustazzioni", 19 | "settings-language": "Lingua", 20 | "settings-language-region": "Riggiuni", 21 | "settings-revisions-onlylast": "Sulu l'ùrtimu", 22 | "settings-revisions-all": "Ammustra tutti", 23 | "presets-button-create": "Crea", 24 | "presets-title": "Tìtulu", 25 | "presets-anons": "Anònimu", 26 | "presets-new": "Pàggini novi", 27 | "presets-only-new": "Solo li pàggini novi", 28 | "presets-ns": "Filtra li namespace", 29 | "presets-ores-filter": "Filtru ORES", 30 | "presets-sw": "Wiki nichi", 31 | "presets-save": "Sarva", 32 | "presets-invalid-title": "Tìtulu nun vàlidu", 33 | "diff-info-user": "Utenti:", 34 | "diff-info-title": "Tìtulu:", 35 | "diff-info-wiki": "Wiki:", 36 | "diff-info-comment": "Oggettu:", 37 | "diff-info-namespace": "Namespace:", 38 | "diff-mo-rfh": "WM:RFH", 39 | "diff-mo-srm": "SRM", 40 | "diff-mo-srg": "SRG", 41 | "diff-mo-gsr": "GSR", 42 | "diff-mo-ca": "Central auth", 43 | "diff-mo-vh": "Talìa la crunuluggìa", 44 | "diff-mo-es": "Cancia surgenti", 45 | "notifications-img": "Nutìfichi", 46 | "notifications-title": "Nutìfichi", 47 | "tooltip-po-close": "Chiudi [esc]", 48 | "po-img-cross": "Chiudi", 49 | "dialog-img-close": "Chiudi", 50 | "logs-cols-user": "Utenti", 51 | "logs-cols-action": "Azzioni", 52 | "logs-cols-wiki": "Wiki", 53 | "logs-cols-title": "Tìtulu", 54 | "logs-cols-date": "Data", 55 | "logs-title": "Riggistri", 56 | "logs-action-all": "Tutti li azzioni", 57 | "logs-action-undo": "Annulla", 58 | "logs-action-edit": "Cancia", 59 | "logs-action-delete": "Cancella", 60 | "logs-action-protect": "Pruteggi", 61 | "talk-today": "Oji", 62 | "talk-yesterday": "Ajeri", 63 | "talk-title": "Discussioni", 64 | "talk-img-cross": "Chiudi", 65 | "tooltip-talk-people": "Pirsuni", 66 | "talk-img-people": "Pirsuni", 67 | "talk-img-app": "SWViewer", 68 | "talk-no-messages": "Nuḍḍu missaggiu", 69 | "talk-people": "Pirsuni", 70 | "nc-unlogin-title": "Nesci", 71 | "nc-unlogin-q": "Sî sicuru?", 72 | "settings-sound-none": "Nuḍḍu", 73 | "settings-sound-only-edits": "Sulu li canci", 74 | "error-edit": "Erruri ntû canciamentu: $1", 75 | "edit-source-title": "Cancia surgenti", 76 | "tooltip-reason": "Mutivu", 77 | "welcome-frame-title": "Bimminutu", 78 | "welcome-frame-undo": "Annulla", 79 | "welcome-frame-edit": "Cancia", 80 | "welcome-frame-del": "Cancella", 81 | "welcome-frame-protect": "Pruteggi", 82 | "welcome-frame-total": "Tutali", 83 | "welcome-frame-links": "Liami di fora", 84 | "new-page-frame-not-exist": "Nun esisti", 85 | "new-page-frame-new": "La pàggina nova è vacanti", 86 | "about-frame-doc": "Talìa la [$1|ducumintazzioni].", 87 | "about-frame-cookies-title": "Cookie", 88 | "about-frame-translating": "Traduzzioni", 89 | "about-frame-translators-list": "Elencu dî traduttura:", 90 | "about-frame-data-username": "Nomu utenti", 91 | "page-title": "Diff", 92 | "welcome-page-title": "Pàggina di bimminutu", 93 | "login-welcome": "Bimminutu!", 94 | "img-message": "Missaggiu", 95 | "img-logos": "Riggistri", 96 | "img-logout": "Nesci", 97 | "img-about": "Nfurmazzioni", 98 | "img-notification": "Nutìfichi", 99 | "img-settings": "Mpustazzioni", 100 | "img-edit": "Cancia", 101 | "img-options": "Àutri opzioni", 102 | "img-plus": "Agghiunci", 103 | "img-save": "Sarva", 104 | "cancel": "Annulla", 105 | "about": "Nfurmazzioni", 106 | "delete": "Cancella" 107 | } 108 | -------------------------------------------------------------------------------- /i18n/sdh.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "TerranBoy" 5 | ] 6 | }, 7 | "tooltip-more-options": "هەڵوژاننەگان فێشتر", 8 | "settings-title": "ڕیکخستنەگان", 9 | "settings-theme": "تێم", 10 | "settings-language": "زوان", 11 | "settings-language-region": "ناوچە", 12 | "settings-sound": "دەنگ", 13 | "settings-control": "ئامرازەیل گەشەپێدەرەیل", 14 | "settings-service": "خزمەت", 15 | "settings-beta": "بێتا", 16 | "presets-default-title": "بنچینەیی", 17 | "presets-button-create": "دروسکردن", 18 | "presets-title": "سەرناو", 19 | "presets-registered": "توومارکریاێ", 20 | "presets-anons": "نەناسریاێ", 21 | "presets-new": "پەڕەیل نوو", 22 | "presets-ns": "پاڵیار فەزاناو", 23 | "presets-sw": "ویکیەیل بۊچگ", 24 | "presets-save": "پاشەکەفت", 25 | "presets-restore": "هەڵگەردانن", 26 | "presets-invalid-title": "سەرناو نادروس", 27 | "diff-info-user": "وەکاربەر:", 28 | "diff-info-title": "سەرناو:", 29 | "diff-info-wiki": "ویکی:", 30 | "diff-info-namespace": "فەزاناو:", 31 | "diff-mo-vh": "دیین دیرووک", 32 | "diff-mo-thank": "سپاس", 33 | "diff-mo-es": "دەسکاریکردن سەرچاوە", 34 | "po-img-cross": "بەسان", 35 | "dialog-img-close": "بەسان", 36 | "logs-cols-user": "وەکاربەر", 37 | "logs-cols-action": "کردار", 38 | "logs-cols-wiki": "ویکی", 39 | "logs-cols-title": "سەرناو", 40 | "logs-cols-date": "ڕێکەفت", 41 | "logs-title": "لۆگەیل", 42 | "tooltip-logs-refresh": "نووکردن", 43 | "logs-img-reload": "دوارە بارکردن", 44 | "logs-search-placeholder": "مینەێ وەکاربەر یا ویکی کردن.", 45 | "tooltip-logs-filter": "پاڵیارەگان کردار", 46 | "tooltip-logs-search": "مینە", 47 | "logs-img-search": "مینە", 48 | "logs-action-all": "گشت کردارەگان", 49 | "logs-action-undo": "پۊچەوکردن", 50 | "logs-action-edit": "دەسکاری", 51 | "logs-action-delete": "سڕینەوە", 52 | "logs-action-report": "گوزارشت", 53 | "logs-action-protect": "پیەرێزانن", 54 | "talk-today": "ئمڕوو", 55 | "talk-yesterday": "دۊەکە", 56 | "talk-img-cross": "بەسان", 57 | "tooltip-talk-people": "مەردم", 58 | "talk-img-people": "مەردم", 59 | "talk-people": "مەردم", 60 | "talk-people-online": "ئۆفلاین", 61 | "talk-people-offline": "ئۆنلاین", 62 | "talk-send-placeholder": "چە ها لە فکرت؟", 63 | "tooltip-talk-send": "کلکردن", 64 | "talk-img-send": "کلکردن", 65 | "nc-unlogin-q": "ئایا دڵنیاید؟", 66 | "settings-sound-msg-a-mentions": "پەیامەیل و ئاماژەیل", 67 | "settings-sound-only-mentions": "تەنیا ئاماژەیل", 68 | "settings-sound-edits": "دەسکاریەیل و ئاماژەیل", 69 | "settings-sound-only-edits": "تەنیا دەسکاریەیل", 70 | "load-history": "بارکردن دیرووک", 71 | "report-title": "گوزارشت", 72 | "edit-source-title": "دەسکاری سەرچاوە", 73 | "summary-title": "خوڵاسە", 74 | "tooltip-edit-form": "کۆد سەرچاوەێ ئەی پەڕەیە", 75 | "tooltip-reason": "هووکار", 76 | "welcome-frame-title": "خوەش هاتی", 77 | "welcome-frame-button": "مینە", 78 | "welcome-frame-placeholder": "مینەێ وەکاربەر کردن", 79 | "welcome-frame-undo": "پۊچەوکردن", 80 | "welcome-frame-edit": "دەسکاری", 81 | "welcome-frame-del": "سڕینەوە", 82 | "welcome-frame-protect": "پیەرێزانن", 83 | "welcome-frame-report": "گوزارشت", 84 | "welcome-frame-total": "سەرجەم", 85 | "welcome-frame-translation": "ئامرازەیل هەڵگەردانن:", 86 | "about-frame-cookies-title": "کووکیەگان", 87 | "about-frame-translating": "هەڵگەردانن", 88 | "about-frame-translators-list": "پێرست هەڵگەردنەرەگان:", 89 | "about-frame-data-username": "ناو وەکاربەر", 90 | "page-title": "جیاوازی", 91 | "welcome-page-title": "پەڕەێ خوەشهاتن", 92 | "login-welcome": "خوەش هاتی!", 93 | "img-message": "پەێام", 94 | "img-about": "لەبارە", 95 | "img-settings": "ڕیکخستنەگان", 96 | "img-navigation": "ڕێنیشاندەری", 97 | "img-thank": "سپاس", 98 | "img-edit": "دەسکاری", 99 | "img-options": "هەڵوژاننەگان فێشتر", 100 | "img-plus": "ئزافەکردن", 101 | "img-drawer": "سەف", 102 | "img-save": "پاشەکەفت", 103 | "cancel": "هەڵوەشاننەوە", 104 | "about": "لەبارە", 105 | "delete": "سڕینەوە" 106 | } 107 | -------------------------------------------------------------------------------- /i18n/skr-arab.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Saraiki" 5 | ] 6 | }, 7 | "tooltip-home": "گھر [esc]", 8 | "tooltip-notification": "اطلاع نامے [n]", 9 | "tooltip-settings": "عمومی ترتیباں [s]", 10 | "tooltip-m-sidebar": "پاسا پٹی", 11 | "tooltip-m-next-difference": "اڳلا فرق", 12 | "tooltip-m-queue": "قطار", 13 | "tooltip-m-notification": "اطلاع نامے", 14 | "settings-title": "ترتیباں", 15 | "settings-theme": "تھیم", 16 | "settings-language": "زبان", 17 | "settings-language-region": "علاقہ", 18 | "settings-sound": "اواز", 19 | "settings-revisions-all": "سب ݙکھاؤ", 20 | "settings-service": "خدمات", 21 | "settings-beta": "آزمائشی", 22 | "presets-default-title": "پہلے کنوں طے تھیا ہویا", 23 | "presets-enter-placeholder": "اینٹر", 24 | "presets-button-create": "بݨاؤ", 25 | "presets-title": "عنوان", 26 | "presets-registered": "رجسٹرڈ", 27 | "presets-anons": "گمنام", 28 | "presets-new": "نویں ورقے", 29 | "presets-save": "بچاؤ", 30 | "presets-restore": "بحال کرو", 31 | "diff-info-user": "ورتݨ آلا:", 32 | "diff-info-title": "عنوان:", 33 | "diff-info-wiki": "وکی:", 34 | "diff-info-comment": "تبصرہ:", 35 | "diff-info-namespace": "ناں جاہ:", 36 | "diff-mo-vh": "تاریخچہ ݙیکھو", 37 | "diff-mo-thank": "شکریہ", 38 | "diff-mo-es": "ماخذ وچ لکھو", 39 | "notifications-img": "اطلاع نامے", 40 | "notifications-title": "اطلاع نامے", 41 | "po-img-cross": "بند کرو", 42 | "dialog-img-close": "بند کرو", 43 | "logs-cols-user": "ورتݨ آلا", 44 | "logs-cols-action": "عمل", 45 | "logs-cols-wiki": "وکی", 46 | "logs-cols-title": "عنوان", 47 | "logs-cols-date": "تریخ", 48 | "logs-title": "لاگز", 49 | "tooltip-logs-refresh": "تازہ کرو", 50 | "logs-img-reload": "ولدا لوڈ کرو", 51 | "logs-prev": "پچھلا", 52 | "logs-next": "اڳلا", 53 | "tooltip-logs-search": "ڳولو", 54 | "logs-img-search": "ڳولو", 55 | "logs-action-all": "سارے کم", 56 | "logs-action-rollback": "پچھاں واپس کرو", 57 | "logs-action-undo": "واپس", 58 | "logs-action-edit": "لکھو", 59 | "logs-action-warn": "خبردار", 60 | "logs-action-delete": "مٹاؤ", 61 | "logs-action-report": "رپورٹ", 62 | "logs-action-protect": "حفاظت کرو", 63 | "talk-today": "اڄ", 64 | "talk-yesterday": "کل", 65 | "talk-title": "ڳالھ مہاڑ", 66 | "talk-img-cross": "بند کرو", 67 | "tooltip-talk-people": "لوک", 68 | "talk-img-people": "لوک", 69 | "talk-no-messages": "کوئی سنیہا کائنی", 70 | "talk-people": "لوک", 71 | "talk-people-online": "آن لائن", 72 | "talk-people-offline": "آف لائن", 73 | "tooltip-talk-send": "بھیڄو", 74 | "talk-img-send": "بھیڄو", 75 | "nc-unlogin-title": "لاگ آؤٹ", 76 | "nc-unlogin-q": "بھلا تہاکوں پک ہے؟", 77 | "settings-sound-none": "کوئی وی کائنی", 78 | "custom-revert-button": "واپس", 79 | "tooltip-reason": "سبب", 80 | "welcome-frame-title": "ست بسم اللہ", 81 | "welcome-frame-button": "ڳولو", 82 | "welcome-frame-rollback": "پچھاں واپس کرو", 83 | "welcome-frame-undo": "واپس", 84 | "welcome-frame-edit": "لکھو", 85 | "welcome-frame-warn": "خبردار", 86 | "welcome-frame-del": "مٹاؤ", 87 | "welcome-frame-protect": "حفاظت کرو", 88 | "welcome-frame-report": "رپورٹ", 89 | "welcome-frame-total": "مجموعہ", 90 | "welcome-frame-reminder": "یاد دہانی", 91 | "about-frame-privacy-title": "رازداری", 92 | "about-frame-data-username": "ورتݨ ناں", 93 | "page-title": "فرق", 94 | "welcome-page-title": "ست بسم اللہ ورقہ", 95 | "login-welcome": "ست بسم اللہ!", 96 | "img-message": "سنیہا", 97 | "img-logos": "لاگز", 98 | "img-logout": "لاگ آؤٹ", 99 | "img-about": "تعارف", 100 | "img-notification": "اطلاع نامہ", 101 | "img-settings": "ترتیباں", 102 | "img-navigation": "نیوی ڳیشݨ", 103 | "img-thank": "شکریہ", 104 | "img-edit": "لکھو", 105 | "img-options": "ٻئے اختیار", 106 | "img-plus": "شامل کرو", 107 | "img-next": "اڳلا فرق", 108 | "img-drawer": "قطار", 109 | "img-copy": "لنک نقل کرو", 110 | "img-browser": "نویں ٹیب وچ کھولو", 111 | "img-rollback": "پچھاں واپس کرو", 112 | "img-back": "پچھلا فرق", 113 | "img-box": "پاسا پٹی", 114 | "img-save": "بچاؤ", 115 | "cancel": "منسوخ", 116 | "about": "تعارف", 117 | "delete": "مٹاؤ" 118 | } 119 | -------------------------------------------------------------------------------- /i18n/sms.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Yupik" 5 | ] 6 | }, 7 | "tooltip-logout": "Ǩeeʹrjtõõđ åålǥas [u]", 8 | "tooltip-copy-link": "Kopiââʹst liiŋk addrõõzz", 9 | "tooltip-edit-source": "Muuʹtt wikiteeʹkst [e]", 10 | "tooltip-publish-changes": "Õlmstââʹtt muttsid", 11 | "settings-title": "Asetõõzz", 12 | "settings-language": "Ǩiõll", 13 | "settings-sound": "Jiõnn", 14 | "settings-revisions-all": "Čuäʹjet puk", 15 | "presets-button-create": "Raaj", 16 | "presets-registered": "Rekisterõsttum", 17 | "presets-anons": "Nõõmteʹmes õõʹnni", 18 | "presets-new": "Ođđ seeid", 19 | "presets-only-new": "Tåʹlǩ ođđ seeid", 20 | "presets-ores-filter": "ORES-siʹllʼjeei", 21 | "presets-save": "Ruõkk", 22 | "presets-restore": "Maaccât asetõõzzid", 23 | "diff-info-user": "Õõʹnni:", 24 | "diff-info-title": "Nõmm:", 25 | "diff-info-wiki": "Wiki:", 26 | "diff-info-comment": "Kommeʹntt:", 27 | "diff-mo-guc": "Riâžldõkveiddsõs muttâz", 28 | "diff-mo-vh": "Čuäʹjet historia", 29 | "diff-mo-thank": "Späʹssbõõžž", 30 | "diff-mo-es": "Muuʹtt wikiteeʹkst", 31 | "logs-cols-user": "Õõʹnni", 32 | "logs-cols-wiki": "Wiki", 33 | "logs-cols-title": "Nõmm", 34 | "logs-cols-date": "Peiʹvvmieʹrr", 35 | "tooltip-logs-refresh": "Peiʹvved", 36 | "logs-search-placeholder": "Ooʒʒ õõʹnni leʹbe wiki.", 37 | "tooltip-logs-search": "Ooʒʒ", 38 | "logs-img-search": "Ooccmõš", 39 | "logs-action-undo": "Kååʹmet", 40 | "logs-action-edit": "Muuʹtt", 41 | "logs-action-delete": "Jaukkâd", 42 | "logs-action-protect": "Suõjjâd", 43 | "talk-today": "Täʹbbe", 44 | "talk-yesterday": "Jåhtta", 45 | "talk-title": "Saǥstõõllâmseidd", 46 | "talk-img-app": "SWViewer", 47 | "talk-no-messages": "Jie leäkku saaǥǥ", 48 | "talk-people": "Oummu", 49 | "tooltip-talk-send": "Vuõlttâd saaǥǥ", 50 | "talk-img-send": "Vuõlttâd", 51 | "nc-unlogin-title": "Ǩeeʹrjtõõđ åålǥas", 52 | "error-loading-title": "Laaddmõš ij oʹnnstam.", 53 | "edit-fail-title": "Mottmõš ij oʹnnstam!", 54 | "view-latest": "Čuäʹjet ođđsumus versio", 55 | "rollback-fail-title": "Kååʹmtummuš ij oʹnnstam!", 56 | "load-history": "Laadd historia", 57 | "thank-fail-title": "Späʹssbõõššmõš ij oʹnnstam!", 58 | "custom-revert-button": "Kååʹmet", 59 | "edit-source-title": "Muuʹtt wikiteeʹkst", 60 | "summary-title": "Õʹhtteǩeässmõš", 61 | "tooltip-edit-form": "Seeid käivvkoodd", 62 | "tooltip-reason": "Mäinn", 63 | "welcome-frame-title": "Tiõrvpueʹttem", 64 | "welcome-frame-button": "Ooʒʒ", 65 | "welcome-frame-placeholder": "Ooʒʒ õõʹnni", 66 | "welcome-frame-undo": "Kååʹmet", 67 | "welcome-frame-edit": "Muuʹtt", 68 | "welcome-frame-del": "Jaukkâd", 69 | "welcome-frame-protect": "Suõjjâd", 70 | "welcome-frame-total": "Õhttsa", 71 | "new-page-frame-new": "Ođđ seidd lij kuâras", 72 | "about-frame-cookies-title": "Jeäʹvstõõzz", 73 | "about-frame-translating": "Jåårǥlâttmõš", 74 | "about-frame-wmprivacy": "WMF teâttsuejjčiõʹlǧǧõs", 75 | "about-frame-data": "Teâđai noorrmõš", 76 | "about-frame-data-username": "Õõʹnninõmm", 77 | "login-welcome": "Tiõrvpueʹttem!", 78 | "login-oauth": "Ǩeeʹrjtõõđ sizz OAuthin", 79 | "img-logout": "Ǩeeʹrjtõõđ åålǥas", 80 | "img-about": "Lââʹssteâđ", 81 | "img-settings": "Asetõõzz", 82 | "img-edit": "Muuʹtt", 83 | "img-plus": "Lââʹzzet", 84 | "img-copy": "Kopiââʹst liiŋk", 85 | "img-browser": "Ääʹved ođđ kõskklõʹstte", 86 | "img-save": "Ruõkk", 87 | "cancel": "Jõõsk", 88 | "about": "Lââʹssteâđ", 89 | "delete": "Jaukkâd" 90 | } 91 | -------------------------------------------------------------------------------- /i18n/uz.json: -------------------------------------------------------------------------------- 1 | { 2 | "@metadata": { 3 | "authors": [ 4 | "Jamshiduralovofficial", 5 | "Malikxan" 6 | ] 7 | }, 8 | "tooltip-home": "Bosh sahifa [esc]", 9 | "tooltip-talk": "Munozara [t]", 10 | "tooltip-logs": "Kirish [I]", 11 | "tooltip-logout": "Chiqish [u]", 12 | "tooltip-notification": "Bildirishnomalar [n]", 13 | "tooltip-settings": "Umumiy sozlamalar [s]", 14 | "tooltip-m-notification": "Bildirishnomalar", 15 | "tooltip-copy-link": "Havola manzilidan nusxa olish", 16 | "tooltip-edit-source": "Manbasini tahrirlash [e]", 17 | "tooltip-more-options": "Koʻproq opsiyalar", 18 | "tooltip-open-browser": "Brauzer oynasida ochish [o]", 19 | "tooltip-speedy-del": "Tag panel [d]", 20 | "tooltip-custom-rollback": "Qisqa izoh bilan eski holiga qaytarish [y]", 21 | "tooltip-publish-changes": "Oʻzgarishlarni nashr qilish", 22 | "settings-title": "Sozlamalar", 23 | "settings-theme": "Mavzu", 24 | "settings-theme-descr": "Asbob interfeys mavzusini oʻzgartirish", 25 | "settings-language": "Til", 26 | "settings-language-descr": "Asbob interfeys tilini oʻzgartirish", 27 | "settings-revisions-all": "Barchasini koʻrish", 28 | "settings-limit-placeholder": "Limit yoʻq", 29 | "settings-control": "Dev asboblar", 30 | "settings-control-panel": "Kontrol panel", 31 | "settings-beta": "Beta", 32 | "settings-beta-tester": "Beta versiyani ochish", 33 | "queue-empty-msg": "Navbat bo'sh", 34 | "presets-enter-placeholder": "Bosish", 35 | "presets-button-create": "Yaratish", 36 | "presets-title": "Sarlavha", 37 | "presets-registered": "Roʻyxatdan oʻtgan", 38 | "presets-anons": "Anonimlar", 39 | "presets-new": "Yangi sahifalar", 40 | "presets-only-new": "Faqat yangi sahifalar", 41 | "presets-edits-limit": "Tahrirlar limiti", 42 | "presets-edits-limit-placeholder": "Maksimum tahrirlar", 43 | "presets-days-limit": "Kunlik limit", 44 | "presets-ns": "Nomfazo filteri", 45 | "presets-sw": "Kichik vikilar", 46 | "presets-sw-desc": "Kichik vikilardan tahrirlarni yoqish", 47 | "presets-save": "Saqlash", 48 | "diff-info-user": "Foydalanuvchi:", 49 | "diff-info-title": "Sarlavha:", 50 | "diff-info-wiki": "Viki:", 51 | "diff-info-comment": "Izoh:", 52 | "diff-info-namespace": "Nomfazo:", 53 | "diff-mo-guc": "Global hissasi", 54 | "notifications-empty": "Bildirishnomalar yoʻq", 55 | "notifications-img": "Bildirishnomalar", 56 | "notifications-title": "Bildirishnomalar", 57 | "tooltip-po-close": "Yopish [esc]", 58 | "po-img-cross": "Yopish", 59 | "dialog-img-close": "Yopish", 60 | "logs-cols-user": "Foydalanuvchi", 61 | "logs-cols-action": "Harakat", 62 | "logs-cols-wiki": "Viki", 63 | "logs-cols-title": "Sarlavha", 64 | "logs-cols-date": "Sana", 65 | "logs-title": "Qaydlar", 66 | "logs-img-reload": "Qayta yuklash", 67 | "logs-prev": "Avvalgisi", 68 | "logs-next": "Keyingisi", 69 | "tooltip-logs-search": "Qidirish", 70 | "logs-img-search": "Qidirish", 71 | "logs-action-all": "Barcha harakatlar", 72 | "logs-action-rollback": "Eski holiga qaytarish", 73 | "logs-action-undo": "Bekor qilish", 74 | "logs-action-edit": "Tahrir", 75 | "logs-action-warn": "Ogohlantirish", 76 | "logs-action-protect": "Himoyalash", 77 | "talk-today": "Bugun", 78 | "talk-yesterday": "Kecha", 79 | "talk-title": "Munozara", 80 | "talk-img-cross": "Yopish", 81 | "tooltip-talk-people": "Odam", 82 | "talk-img-people": "Odam", 83 | "talk-img-app": "SWViewer", 84 | "talk-no-messages": "Xabarlar yoʻq", 85 | "talk-people": "Odam", 86 | "talk-send-placeholder": "Nima haqida oʻylayabsiz?", 87 | "talk-img-send": "Yuborish", 88 | "nc-unlogin-title": "Chiqish", 89 | "autoreport-content": "$1 haqida bir necha bor ogohlantirildi. Siz ularni Admin Bildirishnomalariga xabar qilmoqchimisiz?", 90 | "already-done": "Bunday o'zgarishlar allaqachon qilingan." 91 | } 92 | -------------------------------------------------------------------------------- /img/about-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /img/arrow-left-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /img/arrow-up-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /img/back-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | -------------------------------------------------------------------------------- /img/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /img/bell-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/box-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/check-mark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /img/clear-bars-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/confirm-undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /img/copy-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/cross-filled.svg: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/cross.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /img/custom-rollback-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/delete-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/doc-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /img/down-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /img/drawer-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/drawer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/edit-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/edit-page.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/eye-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /img/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /img/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /img/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /img/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /img/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /img/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/img/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /img/filter-bar-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 9 | 11 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/filter-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/forward-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /img/h-dots-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/home-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/message-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /img/new-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/open-newtab-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/pencil-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/people-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /img/people.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/plus-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /img/power-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/reload-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/report-filled.svg: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /img/rollback-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /img/save-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/save.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /img/search-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/send-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /img/send.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/settings-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /img/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /img/swviewer-droping-anim.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/swviewer-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/swviewer-loading-anim.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/swviewer-logo-raw.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 16 | 17 | -------------------------------------------------------------------------------- /img/tag-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/tag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/thumbs-up-filled.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /img/v-dots-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/warning-filled.svg: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /index-maintenance.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SWViewer | Maintenance 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 65 | 66 | 67 |
68 | 69 |

Under maintenance

70 | SWViewer is under maintenance. For more information you can join our discord server or IRC channel. 71 |
72 | Image source: Unsplash 73 | 74 | -------------------------------------------------------------------------------- /js/frame/frameKeys.js: -------------------------------------------------------------------------------- 1 | document.onkeydown = function(e) { 2 | if (!e) 3 | e = window.event; 4 | var keyCode = e.which || e.keyCode || e.key; 5 | parent.keyDownFunctOutside(keyCode); 6 | } 7 | 8 | function querySelectorAllLive(element, selector) { 9 | var result = Array.prototype.slice.call(element.querySelectorAll(selector)); 10 | var observer = new MutationObserver(function(mutations) { 11 | mutations.forEach(function(mutation) { 12 | [].forEach.call(mutation.addedNodes, function(node) { 13 | if (node.nodeType === Node.ELEMENT_NODE && node.matches(selector)) { 14 | result.push(node); 15 | } 16 | }); 17 | }); 18 | }); 19 | observer.observe(element, { childList: true, subtree: true }); 20 | return result; 21 | } 22 | 23 | var prevScroll = 0; 24 | var dHeight = undefined; 25 | var isDescHidden = false; 26 | 27 | const hideDescView = (m) => window.parent.postMessage(m, window.origin); 28 | 29 | function setDHeight (e) { 30 | if (e.origin !== 'https://swviewer.toolforge.org') return; 31 | dHeight = e.data; 32 | document.getElementById('diffTable').style.paddingTop = (dHeight + 'px'); 33 | document.getElementById('diffTable').style.paddingBottom = (160 + 'px'); 34 | } 35 | window.addEventListener('message', setDHeight, false); 36 | hideDescView(undefined); 37 | 38 | // jumps 39 | if (parent.jumps === 1 && parent.diffTextRaw !== "") { 40 | var m = parent.diffTextRaw.match(/^.*?(\ prevScroll && 64 | document.documentElement.scrollTop > dHeight) { 65 | if (!isDescHidden) { 66 | hideDescView(true); 67 | isDescHidden = true; 68 | } 69 | } else if (isDescHidden) { 70 | hideDescView(false); 71 | isDescHidden = false; 72 | } 73 | prevScroll = document.documentElement.scrollTop; 74 | }); -------------------------------------------------------------------------------- /js/modules/about.js: -------------------------------------------------------------------------------- 1 | const addAbout = (id) => { 2 | fetch('https://swviewer.toolforge.org/templates/about.html') 3 | .then(res => res.text()) 4 | .then(text => { 5 | let parser = new DOMParser(); 6 | let about = parser.parseFromString(text, 'text/html'); 7 | 8 | var elementsLang = about.getElementsByClassName("custom-lang"); 9 | for (el in elementsLang) { 10 | if (elementsLang.hasOwnProperty(el)) { 11 | var attrs = elementsLang[el].attributes; 12 | for (l in attrs) { 13 | if (attrs.hasOwnProperty(l)) { 14 | if (typeof attrs[l].value !== "undefined") 15 | if (useLang.hasOwnProperty(attrs[l].value.replace("[", "").replace("]", ""))) 16 | elementsLang[el].setAttribute(attrs[l].name, useLang[attrs[l].value.replace("[", "").replace("]", "")]); 17 | } 18 | } 19 | if (typeof elementsLang[el].value !== "undefined") 20 | if (useLang.hasOwnProperty(elementsLang[el].value.replace("[", "").replace("]", ""))) 21 | elementsLang[el].value = useLang[elementsLang[el].value.replace("[", "").replace("]", "")]; 22 | if (typeof elementsLang[el].textContent !== "undefined") 23 | if (useLang.hasOwnProperty(elementsLang[el].textContent.replace("[", "").replace("]", ""))) 24 | elementsLang[el].textContent = useLang[elementsLang[el].textContent.replace("[", "").replace("]", "")]; 25 | } 26 | } 27 | 28 | if (languageIndex !== "en") { 29 | about.getElementById("tw2").textContent = about.getElementById("tw2").textContent.replace("$1", useLang["@metadata"]["langName"]); 30 | 31 | about.getElementById("tw").style.display = "block"; 32 | for (translator in useLang["@metadata"]["authors"]) { 33 | if (useLang["@metadata"]["authors"].hasOwnProperty(translator)) { 34 | var lit = document.createElement('li'); 35 | lit.appendChild(document.createTextNode(useLang["@metadata"]["authors"][translator])); 36 | about.getElementById('tl').appendChild(lit); 37 | } 38 | } 39 | } else about.getElementById("tw2").textContent = useLang["about-frame-translators-tw-base"]; 40 | 41 | 42 | 43 | sandwichLocalisation(about, dirLang, about.getElementById("tw2").textContent, about.getElementById('tw2'), "link", 4, "inline", "T", "https://translatewiki.net/wiki/Translating:SWViewer"); 44 | sandwichLocalisation(about, dirLang, useLang['about-frame-app'], about.getElementById('appname'), "name", 3, "inline", "N", false); 45 | sandwichLocalisation(about, dirLang, useLang['about-frame-doc'], about.getElementById('appdoc'), "$1", 4, "inline", "D", "https://meta.wikimedia.org/wiki/Special:MyLanguage/SWViewer"); 46 | sandwichLocalisation(about, dirLang, useLang['about-frame-q'], about.getElementById('appq'), "$1", 4, "inline", "Q", "https://meta.wikimedia.org/wiki/Talk:SWViewer"); 47 | about.getElementById("localisedElN2").style.fontWeight = 'bold'; 48 | about.getElementById("localisedElQ1").style.marginLeft = '3px'; 49 | about.getElementById('traffic').style.marginLeft = '3px'; 50 | 51 | document.getElementById(id).append(about.body); 52 | }) 53 | .catch(e => console.log(e)); 54 | }; 55 | 56 | const createAboutPO = p => { 57 | if (document.getElementById('about') === null) { 58 | p.append(createPO({ 59 | id: 'about', 60 | header: { title: useLang["about"] }, 61 | content: { 62 | child: bakeEl({ type: 'div', att: { id: 'abox', class: 'fs-md' } }) 63 | } 64 | })); 65 | addAbout('abox'); 66 | } 67 | }; 68 | 69 | createAboutPO(document.getElementById('angularapp') || document.body); -------------------------------------------------------------------------------- /js/modules/bakeEl.js: -------------------------------------------------------------------------------- 1 | const bakeEl = (e) => { 2 | if (e.type === undefined) return console.error('Must provide type to bakeEl.') 3 | let el = document.createElement(e.type); 4 | if (typeof e.att === 'object') Object.keys(e.att).forEach((k) => { if (typeof e.att[k] === 'string') el.setAttribute(k, e.att[k]) }); 5 | if (typeof e.child === 'object' && e.child instanceof Node && e.child instanceof HTMLElement) el.appendChild(e.child); 6 | else if (typeof e.child === 'string') el.appendChild(document.createTextNode(e.child)); 7 | else if (Array.isArray(e.child)) { 8 | e.child.forEach((i) => { 9 | if (typeof i === 'object' && i instanceof Node && i instanceof HTMLElement) el.appendChild(i); 10 | else if (typeof i === 'string') el.appendChild(document.createTextNode(i)); 11 | }); 12 | } 13 | return el; 14 | } -------------------------------------------------------------------------------- /js/modules/bakeEl.min.js: -------------------------------------------------------------------------------- 1 | const bakeEl=e=>{if(void 0===e.type)return console.error("Must provide type to bakeEl.");let el=document.createElement(e.type);return"object"==typeof e.att&&Object.keys(e.att).forEach(k=>{"string"==typeof e.att[k]&&el.setAttribute(k,e.att[k])}),"object"==typeof e.child&&e.child instanceof Node&&e.child instanceof HTMLElement?el.appendChild(e.child):"string"==typeof e.child?el.appendChild(document.createTextNode(e.child)):Array.isArray(e.child)&&e.child.forEach(i=>{"object"==typeof i&&i instanceof Node&&i instanceof HTMLElement?el.appendChild(i):"string"==typeof i&&el.appendChild(document.createTextNode(i))}),el}; -------------------------------------------------------------------------------- /js/modules/localisation-sand.js: -------------------------------------------------------------------------------- 1 | function sandwichLocalisation(baseContent, dirLocal, localMessage, targetEl, patternType, parsedLen, styleEl, uniqId, linkLocalisation, baseAdd = false) { 2 | var parsedMessage; var baseContent = baseContent; 3 | if (patternType === 'link') 4 | parsedMessage = (dirLocal === 'ltr') ? localMessage.match(/^(.*?)\[\$link\|(.*?)\](.*)$/) : localMessage.match(/^(.*?)\[\$\s?link\s?\|\s?(.*?)\](.*)$/); 5 | else { 6 | if (patternType === 'name') 7 | parsedMessage = (dirLocal === 'ltr') ? localMessage.match(/^(.*?)\$1(.*)/) : localMessage.match(/^(.*?)\$\s?1(.*)/); 8 | else 9 | parsedMessage = (dirLocal === 'ltr') ? localMessage.match(/^(.*?)\[\$1\|(.*?)\](.*)$/) : localMessage.match(/^(.*?)\[\$\s?1\s?\|\s?(.*?)\](.*)$/); 10 | } 11 | if (parsedMessage !== null && parsedMessage.length === parsedLen) { 12 | targetEl.textContent = ''; 13 | var preLocalisedEl1 = baseContent.createElement('div'); 14 | var preLocalisedEl2 = (linkLocalisation === false) ? baseContent.createElement('div') : baseContent.createElement('a'); 15 | var preLocalisedEl3 = baseContent.createElement('div'); 16 | preLocalisedEl1.id = 'localisedEl' + uniqId + '1'; 17 | preLocalisedEl2.id = 'localisedEl' + uniqId + '2'; 18 | preLocalisedEl3.id = 'localisedEl' + uniqId + '3'; 19 | preLocalisedEl1.style.display = preLocalisedEl2.style.display = preLocalisedEl3.style.display = styleEl; 20 | if (linkLocalisation !== false) { 21 | preLocalisedEl2.href = linkLocalisation; 22 | preLocalisedEl2.rel = 'noopener noreferrer'; 23 | preLocalisedEl2.target = '_blank'; 24 | } 25 | 26 | targetEl.appendChild(preLocalisedEl1); targetEl.appendChild(preLocalisedEl2); targetEl.appendChild(preLocalisedEl3); 27 | if (baseAdd !== false) 28 | baseContent = baseAdd; 29 | baseContent.getElementById('localisedEl' + uniqId + '1').textContent = parsedMessage[1]; 30 | if (parsedLen === 3) { 31 | baseContent.getElementById('localisedEl' + uniqId + '2').textContent = 'SWViewer'; 32 | baseContent.getElementById('localisedEl' + uniqId + '3').textContent = parsedMessage[2]; 33 | } else { 34 | baseContent.getElementById('localisedEl' + uniqId + '2').textContent = parsedMessage[2]; 35 | baseContent.getElementById('localisedEl' + uniqId + '3').textContent = parsedMessage[3]; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /js/modules/po.js: -------------------------------------------------------------------------------- 1 | const createPO = (po) => { 2 | return bakeEl({ 3 | type: "div", 4 | att: { id: po.id, class: "po__base" }, 5 | child: [ 6 | bakeEl({ 7 | type: 'div', 8 | att: { class: 'po__header action-header' }, 9 | child: (header => { 10 | let hChilds = [bakeEl({ type: 'span', child: header.title, att: { class: 'action-header__title fs-lg' } })] 11 | if (header.buttons) header.buttons.forEach((btn) => hChilds.push(bakeEl({ 12 | type: 'div', att: { id: btn.id, class: btn.class + " secondary-hover", onclick: btn.onClick, 'aria-label': btn.toolTip, 'i-tooltip': `bottom-${(dirLang === 'rtl')? 'left': 'right'}` }, 13 | child: bakeEl({ type: 'img', att: { class: "touch-ic secondary-icon " + btn.img.class, src: btn.img.src, alt: btn.img.alt } }) 14 | }))); 15 | hChilds.push(bakeEl({ type: 'div', att: { class: 'mobile-only secondary-hover', onclick: 'closePO()', 'aria-label': useLang["tooltip-po-close"], 'i-tooltip': `bottom-${(dirLang === 'rtl')? 'left': 'right'}` }, 16 | child: bakeEl({ type: 'img', att: { class: 'touch-ic secondary-icon', src: './img/cross-filled.svg', alt: useLang["po-img-cross"] } }) 17 | })) 18 | hChilds.push(bakeEl({ type: 'span', child: 'esc', att: { class: 'desktop-only po__esc secondary-hover fs-md', onclick: 'closePO();' } })); 19 | return hChilds; 20 | })(po.header) 21 | }), 22 | bakeEl({ 23 | type: 'div', 24 | att: { class: 'po__content' }, 25 | child: bakeEl({ 26 | type: 'div', 27 | att: { class: 'po__content-body secondary-scroll' }, 28 | child: po.content.child 29 | }) 30 | }) 31 | ] 32 | }); 33 | }; -------------------------------------------------------------------------------- /js/modules/pw.js: -------------------------------------------------------------------------------- 1 | const createPW = (pw) => { 2 | var noDrawerStyle = ""; 3 | if (pw.drawer === undefined) noDrawerStyle = "grid-template-areas: 'pw__header pw__header' 'pw__content pw__content';"; 4 | 5 | return bakeEl({ 6 | type: "div", att: { id: pw.id, class: "pw__base", style: "display: none;" + noDrawerStyle}, 7 | child: ((pw) => { 8 | // Childrens of pw 9 | let pwChilds = [ 10 | bakeEl({ 11 | type: 'div', att: { class: "pw__header action-header" }, 12 | child: ((header) => { 13 | // Childrens of header 14 | let hChilds = [ 15 | bakeEl({ type: 'div', child: bakeEl({ type: 'img', att: { class: "touch-ic secondary-icon", src: './img/drawer-filled.svg', alt: useLang["pw-img-drawer"] } }), att: { class: 'mobile-only secondary-hover', onclick: 'openSidebar();', 'aria-label': 'Sidebar', 'i-tooltip': `bottom${(dirLang === 'rtl')? 'right': 'left'}` } }), 16 | bakeEl({ type: 'span', child: header.title, att: {class: 'action-header__title fs-xl'} }) 17 | ]; 18 | header.buttons.forEach((btn) => hChilds.push(bakeEl({ 19 | type: 'div', att: { id: btn.id, class: btn.class + " secondary-hover", onclick: btn.onClick, 'aria-label': btn.toolTip, 'i-tooltip': `bottom-${(dirLang === 'rtl')? 'left': 'right'}` }, 20 | child: bakeEl({ type: 'img', att: { class: "touch-ic secondary-icon " + btn.img.class, src: btn.img.src, alt: btn.img.alt } }) 21 | }))); 22 | hChilds.push(bakeEl({ type: 'span', child: 'esc', att: { class: 'desktop-only pw__esc secondary-hover fs-md', onclick: 'closePW();' } })); 23 | return hChilds; 24 | })(pw.header) 25 | }), 26 | bakeEl({ 27 | type: 'div', att: { class: 'pw__content' }, 28 | child: ((content) => { 29 | // Childrens of content 30 | let cChilds = [ bakeEl({ type: 'div', child: content.child, att: { id: content.id, class: 'pw__content-body secondary-scroll', style: content.style } }) ]; 31 | if (content.floatbar !== undefined) { 32 | cChilds.push(bakeEl({ 33 | type: 'div', att: { class: 'pw__floatbar'}, 34 | child: ((floatbar) => { 35 | // Childrens of floatbar 36 | let fChilds = [ 37 | bakeEl({ 38 | type: 'form', att: { id: floatbar.id, onSubmit: floatbar.onSubmit }, 39 | child: bakeEl({ type: 'input', att: { id: floatbar.input.id, class: 'secondary-placeholder fs-md', autocomplete: 'off', onfocus: floatbar.input.onFocus, 'max-length': floatbar.input.maxLength, placeholder: floatbar.input.placeholder } }) 40 | }) 41 | ]; 42 | floatbar.buttons.forEach((btn) => { 43 | fChilds.push(bakeEl({ type: 'span', att: { 'vr-line': '' } })); 44 | fChilds.push(bakeEl({ 45 | type: 'div', att: { id: btn.id, class: 'secondary-hover', style: btn.style, onclick: btn.onClick, 'aria-label': btn.toolTip, 'i-tooltip': `top-${(dirLang === 'rtl')? 'left': 'right'}`}, 46 | child: ((btn) => { 47 | if (btn.child !== undefined) return btn.child; 48 | if (btn.img !== undefined) return bakeEl({ type: 'img', att: { class: 'touch-ic secondary-icon ' + btn.img.class, src: btn.img.src, alt: btn.img.alt } }); 49 | })(btn) 50 | })); 51 | }) 52 | return fChilds; 53 | })(content.floatbar) 54 | })); 55 | } 56 | return cChilds; 57 | })(pw.content) 58 | }) 59 | ] 60 | //Create Drawer 61 | if (pw.drawer !== undefined) { 62 | pwChilds.push(bakeEl({ type: 'div', child: pw.drawer.child, att: { id: pw.drawer.id, class: 'pw__drawer secondary-scroll' } })); 63 | pwChilds.push(bakeEl({ type: 'div', att: { id: pw.overlay.id, class: 'pw__overlay', onclick: pw.overlay.onClick } })); 64 | } 65 | return pwChilds; 66 | })(pw) 67 | }); 68 | }; 69 | -------------------------------------------------------------------------------- /js/modules/swipe.js: -------------------------------------------------------------------------------- 1 | const Guesture = { 2 | active: null, 3 | types: ["rightSwipe", "leftSwipe", "bottomSwipe", "topSwipe"], 4 | onSwipe: function (target, type, callback, isLive) { 5 | if (Guesture.types.find(guesture => guesture === type) === undefined) { 6 | console.error(`Guesture type "${type}" is not valid!`); 7 | return false; 8 | } 9 | 10 | const minDist = 40; 11 | const touch = { 12 | s: { x: null, y: null }, 13 | m: { x: null, y: null, } 14 | }; 15 | const delta = { x: null, y: null }; 16 | const DIR = { isH: null, isRB: null }; 17 | 18 | const calcSwipe = (cx, cy, isEnd) => { 19 | if (!isEnd && cx !== null && cy !== null) { 20 | touch.m.x = cx; 21 | touch.m.y = cy; 22 | } 23 | if (touch.m.x === null || touch.m.y === null || touch.s.x === null || touch.s.y === null) return; 24 | 25 | delta.x = touch.m.x - touch.s.x; 26 | delta.y = touch.m.y - touch.s.y; 27 | 28 | if (Guesture.active === null && Math.abs(delta.x) < minDist && Math.abs(delta.y) < minDist) return; 29 | 30 | if (DIR.isH === null) { 31 | DIR.isH = (Math.abs(delta.x) > Math.abs(delta.y))? true: false; 32 | DIR.isRB = (DIR.isH)? ((delta.x >= 0)? true: false): ((delta.y >= 0)? true: false); 33 | } 34 | 35 | if (DIR.isH === true && DIR.isRB === true && type === "rightSwipe") callbacker("rightSwipe", (!isEnd)? delta.x: undefined); 36 | else if (DIR.isH === true && DIR.isRB === false && type === "leftSwipe") callbacker("leftSwipe", (!isEnd)? delta.x: undefined); 37 | else if (DIR.isH === false && DIR.isRB === true && type === "bottomSwipe") callbacker("bottomSwipe", (!isEnd)? delta.y: undefined); 38 | else if (DIR.isH === false && DIR.isRB === false && type === "topSwipe") callbacker("topSwipe", (!isEnd)? delta.y: undefined); 39 | 40 | function callbacker(gType, m) { 41 | if (Guesture.active !== null && Guesture.active !== gType) return; 42 | 43 | Guesture.active = gType; 44 | callback(m); 45 | } 46 | } 47 | if (target.constructor === Array) target.forEach(t => touchSetup(t)); 48 | else touchSetup(target); 49 | function touchSetup(t) { 50 | t.addEventListener('touchstart', e => { 51 | const coords = e.touches[0]; 52 | touch.s.x = Math.floor(coords.clientX); 53 | touch.s.y = Math.floor(coords.clientY); 54 | }, false); 55 | t.addEventListener('touchmove', e => { 56 | const coords = e.touches[0]; 57 | if (isLive) { 58 | calcSwipe(Math.floor(coords.clientX), Math.floor(coords.clientY), false); 59 | return; 60 | } 61 | touch.m.x = Math.floor(coords.clientX); 62 | touch.m.y = Math.floor(coords.clientY); 63 | }); 64 | t.addEventListener('touchend', e => { 65 | calcSwipe(null, null, true); 66 | touch.s.x = null; touch.s.y = null; 67 | touch.m.x = null; touch.m.y = null; 68 | delta.x = null; delta.y = null; 69 | DIR.isH = null; DIR.isRB = null; 70 | Guesture.active = null; 71 | }); 72 | } 73 | return true; 74 | } 75 | } -------------------------------------------------------------------------------- /manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "dir" : "ltr", 3 | "lang" : "English", 4 | "name" : "SWViewer", 5 | "short_name" : "SWViewer", 6 | "scope" : "/", 7 | "display" : "standalone", 8 | "start_url" : "https://swviewer.toolforge.org/", 9 | "theme_color" : "#212121", 10 | "description" : "App for viewing queue of edits on small wikis for SWMT", 11 | "background_color" : "#ffffff", 12 | "icons" : [ 13 | { 14 | "src": "https://swviewer.toolforge.org/img/favicons/android-chrome-512x512.png", 15 | "sizes": "512x512" 16 | }, 17 | { 18 | "src": "https://swviewer.toolforge.org/img/favicons/apple-touch-icon.png", 19 | "sizes": "180x180" 20 | }, 21 | { 22 | "src": "https://swviewer.toolforge.org/img/favicons/favicon-32x32.png", 23 | "sizes": "32x32" 24 | }, 25 | { 26 | "src": "https://swviewer.toolforge.org/img/favicons/favicon-16x16.png", 27 | "sizes": "16x16" 28 | }] 29 | } -------------------------------------------------------------------------------- /offline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SWViewer | Offline 6 | 7 | 36 | 37 | 38 | 39 |

SWViewer requires an active internet connection to function.

40 | 41 | 42 | 43 | 54 | 55 | -------------------------------------------------------------------------------- /php/authTalk.php: -------------------------------------------------------------------------------- 1 | "Error. Dev. code: 1"]); 6 | exit(); 7 | } 8 | $serverToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["serverTokenTalk"]; 9 | if ($_POST['serverToken'] !== $serverToken) { 10 | echo json_encode(["auth" => "Error. Dev. code: 2"]); 11 | exit(); 12 | } 13 | 14 | $ts_pw = posix_getpwuid(posix_getuid()); 15 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 16 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 17 | unset($ts_mycnf, $ts_pw, $serverToken); 18 | 19 | $q = $db->prepare('SELECT name FROM user WHERE token = :token AND name = :userName'); 20 | $q->execute(array(':token' => $_POST['userToken'], ':userName' => $_POST['username'])); 21 | echo ($q->rowCount() > 0) ? json_encode(["auth" => "true"]) : json_encode(["auth" => "false"]); 22 | $db = null; 23 | ?> -------------------------------------------------------------------------------- /php/getConfig.php: -------------------------------------------------------------------------------- 1 | prepare('SELECT id FROM verify'); 19 | $q->execute(); 20 | $result = $q->fetch(); 21 | $rev = $result["id"]; 22 | $db = null; 23 | 24 | $url = "https://meta.wikimedia.org/w/index.php?title=SWViewer/config.json&oldid=" . $rev . "&action=raw"; 25 | echo file_get_contents($url); 26 | ?> -------------------------------------------------------------------------------- /php/getFilt.php: -------------------------------------------------------------------------------- 1 | "error", "info" => "Invalid request"]); 7 | session_write_close(); 8 | exit(); 9 | } 10 | if (isset($_GET['token_proxy'])) { 11 | $serverToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["serverTokenTalk"]; 12 | if ($serverToken !== $_GET["token_proxy"]) { 13 | echo json_encode(["result" => "error", "info" => "Invalid request", "code" => 2]); 14 | exit(); 15 | } 16 | } 17 | 18 | $username = $_GET['username']; 19 | $ts_pw = posix_getpwuid(posix_getuid()); 20 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 21 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 22 | unset($ts_mycnf, $ts_pw); 23 | 24 | if (check($_GET["preset_name"])) { 25 | $q = $db->prepare('SELECT * FROM presets WHERE name = :userName AND preset = :preset_name'); 26 | $q->execute(array(':userName' => $username, ':preset_name' => $_GET["preset_name"])); 27 | if ($q->rowCount() > 0) { 28 | $result = $q->fetchAll(); 29 | $raw_result = ["blprojects" => $result[0]['blprojects'], "wikilangs" => $result[0]['wikilangs'], "swmt" => $result[0]['swmt'], "onlyanons" => $result[0]['anons'], "users" => $result[0]['users'], "wlusers" => $result[0]['wlusers'], "wlprojects" => $result[0]['wlprojects'], "namespaces" => $result[0]['namespaces'], "registered" => $result[0]['registered'], "new" => $result[0]['new'], "onlynew" => $result[0]['onlynew'], "editcount" => $result[0]['editscount'], "regdays" => $result[0]['regdays'], "oresFilter" => $result[0]['oresFilter']]; 30 | $q = $db->prepare('SELECT isGlobal, isGlobalAccess, flaggedRevs, local_wikis FROM user WHERE name = :userName'); 31 | $q->execute(array(':userName' => $username)); 32 | $result2 = $q->fetchAll(); 33 | $raw_result["isGlobal"] = $result2[0]['isGlobal']; 34 | $raw_result["isGlobalModeAccess"] = $result2[0]['isGlobalAccess']; 35 | $raw_result["flaggedRevs"] = $result2[0]['flaggedRevs']; 36 | $raw_result["local_wikis"] = $result2[0]['local_wikis']; 37 | echo json_encode($raw_result); 38 | } else 39 | echo json_encode(["result" => "error", "info" => "Not found"]); 40 | } 41 | 42 | $db = null; 43 | 44 | function check($check) { 45 | return (isset($check) && $check !== null && $check !== "") ? true : false; 46 | } 47 | -------------------------------------------------------------------------------- /php/getGlobals.php: -------------------------------------------------------------------------------- 1 | 401, 'info' => 'No username or token']); 11 | http_response_code(401); 12 | session_write_close(); 13 | exit(0); 14 | } 15 | session_write_close(); 16 | if (isset($_GET['token_proxy']) || isset($_GET['ext_token'])) { 17 | $serverToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["serverTokenTalk"]; 18 | $externalToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["externaltoken"]; 19 | if ((isset($_GET['token_proxy']) && $serverToken !== $_GET["token_proxy"]) || (isset($_GET['ext_token']) && $externalToken !== $_GET["ext_token"])) { 20 | echo json_encode(['status' => 401, 'info' => 'Wrong token']); 21 | http_response_code(401); 22 | exit(); 23 | } 24 | } 25 | 26 | $usersList = []; 27 | 28 | getUsers("all"); 29 | getUsers("global-ipblock-exempt"); 30 | getUsers("oathauth-tester"); 31 | getCommonsUsers(); 32 | 33 | if (isset($_GET["user"]) && $_GET["user"] === "Рейму") { 34 | echo implode("|", $usersList); // quick option special for MBH 35 | } else { 36 | $explain = "commons-sysop|commons-filemover|commons-image-reviewer|global-ipblock-exempt|oathauth-tester|apihighlimits-requestor|captcha-exempt|wmf-researcher|wmf-ops-monitoring|sysadmin|recursive-export|vrt-permissions|new-wikis-importer|global-interface-editor|global-flow-create|global-deleter|global-bot|staff|steward|global-sysop|global-rollbacker|abusefilter-helper|founder|ombuds"; 37 | echo json_encode(['meta' => ['count' => count($usersList), 'explain' => $explain], 'users' => $usersList]); 38 | } 39 | 40 | function getUsers($groups) 41 | { 42 | $options = array('https' => array('method' => "POST", "User-Agent: SWViewer/1.3 (https://swviewer.toolforge.org; swviewer@tools.wmflabs.org) PHP / getGlobals.php")); 43 | $context = stream_context_create($options); 44 | 45 | if ($groups == "all") 46 | $groups = "apihighlimits-requestor|captcha-exempt|wmf-researcher|wmf-ops-monitoring|sysadmin|recursive-export|vrt-permissions|new-wikis-importer|global-interface-editor|global-flow-create|global-deleter|global-bot|staff|steward|global-sysop|global-rollbacker|abusefilter-helper|founder|ombuds"; 47 | $check = true; 48 | $agufrom = ""; 49 | $cont = ""; 50 | 51 | while ($check === true) { 52 | $url = "https://meta.wikimedia.org/w/api.php?action=query&format=json&list=globalallusers&formatversion=2&utf8=1&agugroup=" . $groups . "&agulimit=50" . $agufrom . $cont; 53 | $content = file_get_contents($url, false, $context); 54 | $json = json_decode($content, true); 55 | if (!isset($json["continue"]) || !isset($json["continue"]["agufrom"]) || !isset($json["continue"]["continue"])) 56 | $check = false; 57 | else { 58 | $agufrom = "&agufrom=" . urlencode($json["continue"]["agufrom"]); 59 | $cont = "&continue=" . $json["continue"]["continue"]; 60 | } 61 | foreach ($json["query"]["globalallusers"] as $user) { 62 | if (!in_array($user['name'], $GLOBALS['usersList'])) 63 | array_push($GLOBALS['usersList'], $user['name']); 64 | } 65 | } 66 | } 67 | 68 | function getCommonsUsers() 69 | { 70 | $options = array('https' => array('method' => "POST", "User-Agent: SWViewer/1.3 (https://swviewer.toolforge.org; swviewer@tools.wmflabs.org) PHP / getGlobals.php")); 71 | $context = stream_context_create($options); 72 | 73 | $groups = "sysop|filemover|image-reviewer"; 74 | $check = true; 75 | $aufrom = ""; 76 | $cont = ""; 77 | 78 | while ($check === true) { 79 | $url = "https://commons.wikimedia.org/w/api.php?action=query&format=json&list=allusers&formatversion=2&utf8=1&augroup=" . $groups . "&aulimit=50" . $aufrom . $cont; 80 | $content = file_get_contents($url, false, $context); 81 | $json = json_decode($content, true); 82 | if (!isset($json["continue"]) || !isset($json["continue"]["aufrom"]) || !isset($json["continue"]["continue"])) 83 | $check = false; 84 | else { 85 | $aufrom = "&aufrom=" . urlencode($json["continue"]["aufrom"]); 86 | $cont = "&continue=" . $json["continue"]["continue"]; 87 | } 88 | foreach ($json["query"]["allusers"] as $user) { 89 | if (!in_array($user['name'], $GLOBALS['usersList'])) 90 | array_push($GLOBALS['usersList'], $user['name']); 91 | } 92 | } 93 | } 94 | 95 | 96 | 97 | ?> 98 | -------------------------------------------------------------------------------- /php/getOfflineUsers.php: -------------------------------------------------------------------------------- 1 | "error", "info" => "Invalid request"]); 8 | session_write_close(); 9 | exit(); 10 | } 11 | session_write_close(); 12 | 13 | $serverToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["serverTokenTalk"]; 14 | $ts_pw = posix_getpwuid(posix_getuid()); 15 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 16 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 17 | unset($ts_mycnf, $ts_pw); 18 | 19 | $q = $db->prepare('SELECT name FROM user WHERE lastopen >= NOW() - INTERVAL 4 DAY ORDER BY lastopen ASC'); 20 | $q->execute(); 21 | $rows = $q->fetchAll(PDO::FETCH_ASSOC); 22 | 23 | $result[] = null; 24 | $count = count($rows) - 1; 25 | if ($count > -1) { 26 | $indexArray = 0; 27 | while ($indexArray <= $count) { 28 | $result[$indexArray] = $rows[$indexArray]["name"]; 29 | $indexArray++; 30 | } 31 | } 32 | echo json_encode($result); 33 | 34 | $db = null; 35 | ?> -------------------------------------------------------------------------------- /php/getSessionVars.php: -------------------------------------------------------------------------------- 1 | "Invalid request"]); 8 | session_write_close(); 9 | exit(); 10 | } 11 | 12 | $user = $_SESSION['userName']; 13 | $talktoken = $_SESSION['talkToken']; 14 | $isGlobal = ($_SESSION['mode'] === "global") ? true : false; 15 | $isGlobalModeAccess = false; 16 | if (isset($_SESSION['accessGlobal'])) 17 | if ($_SESSION['accessGlobal'] == "true" || ) 18 | $isGlobalModeAccess = true; 19 | $local_wikis = ""; 20 | if (isset($_SESSION['projects'])) 21 | if ($_SESSION['projects'] !== null) 22 | $local_wikis = $_SESSION['projects']; 23 | $userRole = "none"; 24 | if (isset($_SESSION['userRole'])) 25 | if ($_SESSION['userRole'] !== null) 26 | $userRole = $_SESSION['userRole']; 27 | 28 | session_write_close(); 29 | echo json_encode(["user" => $user, "talktoken" => $talktoken, "isGlobal" => $isGlobal, "userRole" => $userRole, "isGlobalModeAccess" => $isGlobalModeAccess, "local_wikis" => $local_wikis]); 30 | ?> 31 | -------------------------------------------------------------------------------- /php/gsr.php: -------------------------------------------------------------------------------- 1 | "error", "info" => "Invalid request"]); 5 | session_write_close(); 6 | exit(); 7 | } 8 | $userName = $_SESSION['userName']; 9 | session_write_close(); 10 | 11 | $wiki = $_POST["wiki"]; 12 | $project = $_POST["project"]; 13 | $title = $_POST["title"]; 14 | $reason = ""; 15 | if (isset($_POST["reason"]) && $_POST["reason"] !== "none") 16 | $reason = ": " . $_POST["reason"]; 17 | $text = "\n" . "* Please delete " . "{{plain link|url=" . $project . "/wiki/" . str_replace("?", "%3F", str_replace(" ", "_", $title)) . "|name=" . $wiki . ":" . str_replace("_", " ", $title) . "}}" . $reason . ". ~~~~"; 18 | $page = "Global sysops/Requests"; 19 | $summary = "Requesting deletion"; 20 | $apiUrl = "https://meta.wikimedia.org/w/api.php"; 21 | $findText = $project . "/wiki/" . str_replace(" ", "_", $title); 22 | 23 | $res_content = @file_get_contents(str_replace("/api.php", "/index.php", $apiUrl) . "?action=raw&title=" . urlencode($page)); 24 | if (substr_count($res_content, $findText)) { 25 | echo json_encode(["result" => "error", "info" => "Already reported"]); 26 | exit(); 27 | } 28 | 29 | 30 | $params = ['action' => 'query', 'meta' => 'tokens', 'type' => 'csrf', 'format' => 'json']; 31 | $token = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params))->query->tokens->csrftoken; 32 | 33 | $params = ['action' => 'edit', 'title' => $page, 'appendtext' => $text, 'recreate' => '0', 'nocreate' => '1', 'watchlist' => 'nochange', 'summary' => $summary, 'token' => $token, 'utf8' => 1, 'format' => 'json']; 34 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 35 | 36 | if (isset($res->edit->title)) { 37 | if (isset($res->edit->nochange)) { 38 | echo json_encode(["code" => "alreadydone", "result" => "This edit has already made by someone."]); 39 | exit(); 40 | } 41 | } 42 | $ts_pw = posix_getpwuid(posix_getuid()); 43 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 44 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 45 | unset($ts_mycnf, $ts_pw); 46 | $q = $db->prepare('INSERT INTO logs (user, type, wiki, title, diff) VALUES (:user, :type, :wiki, :title, :diff)'); 47 | $q->execute(array(':user' => $userName, ':type' => 'report', ':wiki' => 'metawiki', ':title' => 'GSR', ':diff' => str_replace("/api.php", "/index.php?", $apiUrl) . 'oldid=' . strval($res->edit->oldrevid) . '&diff=' . strval($res->edit->newrevid) . '/')); 48 | 49 | $q = $db->prepare('UPDATE stats SET report=report + 1 WHERE user=:username'); 50 | $q->execute(array(':username' => $userName)); 51 | $db = null; 52 | 53 | $response = ["result" => "sucess"]; 54 | echo json_encode($response); 55 | ?> 56 | -------------------------------------------------------------------------------- /php/includes/headerOAuth.php: -------------------------------------------------------------------------------- 1 | setConsumer( new Consumer( $config['consumer_key'], $config['consumer_secret'] ) ); 19 | $conf->setUserAgent( $config['agent'] ); 20 | $client = new Client( $conf ); 21 | $accessToken = new Token( $_SESSION['tokenKey'], $_SESSION['tokenSecret'] ); -------------------------------------------------------------------------------- /php/logs.php: -------------------------------------------------------------------------------- 1 | "error", "info" => "Invalid request"]); 7 | session_write_close(); 8 | exit(); 9 | } 10 | session_write_close(); 11 | 12 | $_POST = json_decode(file_get_contents('php://input'), true); 13 | $searchPhrase = $_POST['sp'] . '%'; 14 | $userPhrase = $searchPhrase; 15 | $wikiPhrase = $searchPhrase; 16 | $searchType = $_POST['st'] . '%'; 17 | $limit = $_POST['li']; 18 | $offset = $_POST['of']; 19 | if ((!is_numeric($limit) && !is_null($limit) && !isset($limit))) 20 | exit(); 21 | 22 | $separatorPos = strpos($searchPhrase, '@'); 23 | 24 | if ($separatorPos !== false) { 25 | $userPhrase = substr($searchPhrase, 0, $separatorPos); 26 | $wikiPhrase = substr($searchPhrase, $separatorPos + 1); 27 | } 28 | 29 | $ts_pw = posix_getpwuid(posix_getuid()); 30 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 31 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 32 | unset($ts_mycnf, $ts_pw); 33 | 34 | $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 35 | if ($separatorPos === false) $q = $db->prepare('SELECT * FROM logs WHERE (user LIKE :searchUser OR wiki LIKE :searchWiki) AND (type LIKE :searchType) ORDER BY date DESC LIMIT :limit OFFSET :offset'); 36 | else $q = $db->prepare('SELECT * FROM logs WHERE (user LIKE :searchUser AND wiki LIKE :searchWiki) AND (type LIKE :searchType) ORDER BY date DESC LIMIT :limit OFFSET :offset'); 37 | $q->bindParam(':searchUser', $userPhrase, PDO::PARAM_STR); 38 | $q->bindParam(':searchWiki', $wikiPhrase, PDO::PARAM_STR); 39 | $q->bindParam(':searchType', $searchType, PDO::PARAM_STR); 40 | $q->bindParam(':limit', $limit, PDO::PARAM_INT); 41 | $q->bindParam(':offset', $offset, PDO::PARAM_INT); 42 | $q->execute(); 43 | $logs = $q->fetchAll(); 44 | echo json_encode($logs); 45 | ?> -------------------------------------------------------------------------------- /php/notify.php: -------------------------------------------------------------------------------- 1 | 'query', 'format' => 'json', 'uselang' => 'ru', 'meta' => 'notifications', 'notcrosswikisummary' => 1, 'notfilter' => "!read", 'utf8' => '1', 'notlimit' => '50']; 15 | $wikis = []; 16 | $response = []; 17 | 18 | $result = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 19 | 20 | foreach($result->query->notifications->list as $list) { 21 | if ($list->timestamp->utcunix > $timestamp) { 22 | if ($list->type !== "foreign") { 23 | $r = getNotify($list, $apiUrl, "metawiki"); 24 | if ($r) array_push($response, $r); 25 | } 26 | else { 27 | $key = key($list->sources); 28 | if (!in_array($key, $wikis)) { 29 | array_push($wikis, $key); 30 | $apiUrl = $list->sources->$key->url; 31 | $result2 = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 32 | foreach($result2->query->notifications->list as $list2) { 33 | if ($list2->timestamp->utcunix > $timestamp) 34 | if ($list2->type !== "foreign") { 35 | $r = getNotify($list2, $apiUrl, $key); 36 | if ($r) array_push($response, $r); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | if (sizeof($response) > 0) 45 | echo json_encode($response); 46 | 47 | function getNotify($content, $api, $wiki) { 48 | if ($content->type === "edit-user-talk") 49 | return ["type" => "TP", "wiki" => $wiki, "agent" => $content->agent->name, "url" => str_replace("/w/api.php", "/wiki/", $api) . urlencode(str_replace(" ", "_", $content->title->full))]; 50 | if ($content->type === "mention") 51 | return ["type" => "mention", "wiki" => $wiki, "agent" => $content->agent->name, "url" => str_replace("/w/api.php", "/wiki/", $api) . urlencode(str_replace(" ", "_", $content->title->full))]; 52 | if ($content->type === "reverted") 53 | return ["type" => "revert", "wiki" => $wiki, "agent" => $content->agent->name, "url" => $api . "index.php?title=" . urlencode(str_replace(" ", "_", $content->title->full))]; 54 | if ($content->type === "edit-thank") 55 | return ["type" => "thank", "wiki" => $wiki, "agent" => $content->agent->name, "url" => $api . "index.php?title=" . urlencode(str_replace(" ", "_", $content->title->full))]; 56 | return null; 57 | } -------------------------------------------------------------------------------- /php/patrol.php: -------------------------------------------------------------------------------- 1 | "Invalid request data.", "info" => "Invalid request"]); 6 | session_write_close(); 7 | exit(); 8 | } 9 | session_write_close(); 10 | 11 | $apiUrl = "https://" . $_POST["project"] . "/w/api.php"; 12 | $rev = $_POST["rev"]; 13 | 14 | $params = ['action' => 'query', 'meta' => 'tokens', 'type' => 'csrf', 'format' => 'json']; 15 | $token = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 16 | $token = $token->query->tokens->csrftoken; 17 | 18 | $params = ["action" => "review", "format" => "json", "revid" => $rev, "comment" => "via [[m:SWViewer|SWViewer]]", "token" => $token]; 19 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 20 | if (isset($res->review->result)) { 21 | if ($res->review->result === "Success") 22 | $response = ["result" => "success"]; 23 | else 24 | $response = ["result" => "error", "info" => $res]; 25 | } 26 | else 27 | $response = ["result" => "error", "info" => $res->error->info]; 28 | echo json_encode($response); 29 | ?> 30 | -------------------------------------------------------------------------------- /php/rollback.php: -------------------------------------------------------------------------------- 1 | "Invalid request data.", "info" => "Invalid request"]); 6 | session_write_close(); 7 | exit(); 8 | } 9 | $apiUrl = $_POST["project"]; 10 | $basetimestamp = ""; 11 | $id = ""; 12 | if ($_POST["rbmode"] === "undo") { 13 | $basetimestamp = $_POST["basetimestamp"]; 14 | $id = $_POST["id"]; 15 | } 16 | $userName = $_SESSION['userName']; 17 | $page = $_POST["page"]; 18 | $user = $_POST["user"]; 19 | $wiki = $_POST["wiki"]; 20 | $mode = $_POST["rbmode"]; 21 | session_write_close(); 22 | $summary = $res2 = $rev = null; 23 | 24 | // Get token 25 | $params = ['action' => 'query', 'meta' => 'tokens', 'format' => 'json']; 26 | $params["type"] = ($mode === "undo") ? "csrf" : "rollback"; 27 | $tokentype = $params["type"]."token"; 28 | 29 | $token_r = $client->makeOAuthCall($accessToken, $apiUrl, true, $params); 30 | $token = json_decode($token_r); 31 | if (!isset($token->query)) 32 | file_put_contents("error.txt", $userName . json_encode($token_r), FILE_APPEND); 33 | $token = $token->query->tokens->$tokentype; 34 | 35 | // Now perform rollback or undo 36 | if ($mode === "rollback") { 37 | $params = ['action' => 'rollback', 'title' => $page, 'user' => $user, 'token' => $token, 'utf8' => '1', 'format' => 'json']; 38 | if (isset($_POST["summary"])) 39 | $params["summary"] = $_POST["summary"]; 40 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 41 | } else { 42 | $params = ['action' => 'query', 'prop' => 'revisions', 'rvstartid' => $id, 'titles' => $page, 'rvprop' => 'ids|user', 'rvlimit' => 1, 'rvexcludeuser' => $user, 'utf8' => '1', 'format' => 'json']; 43 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 44 | forEach ($res->query->pages as $key => $p) { 45 | if ($key != "-1") 46 | $res2 = $p; 47 | } 48 | if ($res2 !== null) { 49 | if (!isset($res2->revisions)) { 50 | $response = ["result" => "All edits on this page by same user.", "code" => "new page"]; 51 | echo json_encode($response); 52 | exit(); 53 | } 54 | if ($res2->revisions[0]->revid != "0") 55 | $rev = $res2->revisions[0]->revid; 56 | } 57 | if ($rev !== null) { 58 | $summary = str_replace("$1", $res2->revisions[0]->user, "Restore to the last revision by [[User:$1|$1]]"); 59 | if (isset($_POST["summary"])) 60 | if ($_POST["summary"] !== "") 61 | $summary = str_replace("$1", $res2->revisions[0]->user, $_POST["summary"]); 62 | $params = ['action' => 'edit', 'title' => $page, 'undo' => $id, 'undoafter' => $rev, 'nocreate' => '1', 'watchlist' => 'nochange', 'minor' => 1, 'summary' => $summary, 'basetimestamp' => $basetimestamp, 'token' => $token, 'utf8' => '1', 'format' => 'json']; 63 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 64 | } 65 | } 66 | 67 | // Catching bad responses 68 | $typeaction = ($mode === "undo") ? "edit" : "rollback"; 69 | if (!isset($res->$typeaction->title) || isset($res->$typeaction->nochange)) { 70 | $res = json_decode(json_encode($res), True); 71 | if (isset($res[$typeaction]["nochange"])) 72 | $response = ["code" => "alreadyrolled", "result" => "Edit is already undone."]; 73 | else 74 | $response = (!isset($res["error"])) ? ["result" => "Unknow error", "code" => "Unknow error: RB2"] : ["result" => $res["error"]["info"], "code" => $res["error"]["code"]]; 75 | echo json_encode($response); 76 | exit(); 77 | } 78 | 79 | // Send result to DB and return result 80 | $ts_pw = posix_getpwuid(posix_getuid()); 81 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 82 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8", $ts_mycnf['user'], $ts_mycnf['password']); 83 | unset($ts_mycnf, $ts_pw); 84 | 85 | $q = $db->prepare('INSERT INTO logs (user, type, wiki, title, diff) VALUES (:user, :type, :wiki, :title, :diff)'); 86 | if ($mode === "rollback") { 87 | $q->execute(array(':user' => $userName, ':type' => 'rollback', ':wiki' => $wiki, ':title' => strval($res->rollback->title), ':diff' => str_replace("/api.php", "/index.php?", $apiUrl) . 'oldid=' . strval($res->rollback->old_revid) . '&diff=' . strval($res->rollback->revid) . '/')); 88 | $res = json_decode(json_encode($res), True); 89 | $q = $db->prepare('UPDATE stats SET rollback=rollback + 1 WHERE user=:username'); 90 | $q->execute(array(':username' => $userName)); 91 | echo json_encode(["result" => "Success", "summary" => $res["rollback"]["summary"], "oldrevid" => $res["rollback"]["old_revid"], "newrevid" => $res["rollback"]["revid"], "user" => $userName, "type" => "rolback"]); 92 | } else { 93 | $q->execute(array(':user' => $userName, ':type' => 'undo', ':wiki' => $wiki, ':title' => strval($res->edit->title), ':diff' => str_replace("/api.php", "/index.php?", $apiUrl) . 'oldid=' . strval($res->edit->oldrevid) . '&diff=' . strval($res->edit->newrevid) . '/')); 94 | $res = json_decode(json_encode($res), True); 95 | $q = $db->prepare('UPDATE stats SET undos=undos + 1 WHERE user=:username'); 96 | $q->execute(array(':username' => $userName)); 97 | echo json_encode(["result" => "Success", "summary" => $summary, "oldrevid" => $res["edit"]["oldrevid"], "newrevid" => $res["edit"]["newrevid"], "user" => $userName, "type" => "undo"]); 98 | } 99 | $db = null; 100 | ?> 101 | -------------------------------------------------------------------------------- /php/talkHistory.php: -------------------------------------------------------------------------------- 1 | "error", "info" => "Invalid request"]); 8 | session_write_close(); 9 | exit(); 10 | } 11 | 12 | $serverToken = parse_ini_file("/data/project/swviewer/security/bottoken.ini")["serverTokenTalk"]; 13 | $ts_pw = posix_getpwuid(posix_getuid()); 14 | $ts_mycnf = parse_ini_file("/data/project/swviewer/security/replica.my.cnf"); 15 | $db = new PDO("mysql:host=tools.labsdb;dbname=s53950__SWViewer;charset=utf8mb4", $ts_mycnf['user'], $ts_mycnf['password']); 16 | unset($ts_mycnf, $ts_pw); 17 | 18 | if (isset($_POST['serverToken'])) 19 | if ($_POST['serverToken'] == $serverToken && $_POST['action'] == "save") 20 | if (isset($_POST['text']) && isset($_POST['username'])) { 21 | $q = $db->prepare('INSERT INTO talk (name, text) VALUES (:name, :text)'); 22 | $q->execute(array(':name' => $_POST['username'], ':text' => $_POST['text'])); 23 | } 24 | unset($serverToken); 25 | 26 | if ($_POST['action'] == "get" && isset($_SESSION['tokenKey']) && isset($_SESSION['tokenSecret']) && isset($_SESSION['userName'])) { 27 | $q = $db->prepare('SELECT * FROM talk WHERE msgtime > NOW() - INTERVAL 5 DAY ORDER BY msgtime ASC'); 28 | $q->execute(); 29 | $res[] = null; 30 | $rows = $q->fetchAll(PDO::FETCH_ASSOC); 31 | foreach ($rows as $row) { 32 | if (date('Ymd') == date('Ymd', strtotime($row['msgtime']))) 33 | $res[0][] = $row; 34 | else if (date('Ymd', strtotime('-1 day', strtotime('now'))) == date('Ymd', strtotime($row['msgtime']))) 35 | $res[1][] = $row; 36 | else if (date('Ymd', strtotime('-2 day', strtotime('now'))) == date('Ymd', strtotime($row['msgtime']))) 37 | $res[2][] = $row; 38 | else if (date('Ymd', strtotime('-3 day', strtotime('now'))) == date('Ymd', strtotime($row['msgtime']))) 39 | $res[3][] = $row; 40 | else if (date('Ymd', strtotime('-4 day', strtotime('now'))) == date('Ymd', strtotime($row['msgtime']))) 41 | $res[4][] = $row; 42 | } 43 | echo json_encode($res); 44 | } 45 | 46 | $db = null; 47 | session_write_close(); 48 | ?> -------------------------------------------------------------------------------- /php/thank.php: -------------------------------------------------------------------------------- 1 | "Invalid request data.", "info" => "Invalid request"]); 6 | session_write_close(); 7 | exit(); 8 | } 9 | session_write_close(); 10 | 11 | $apiUrl = "https://" . $_POST["project"] . "/w/api.php"; 12 | $rev = $_POST["rev"]; 13 | $params = ['action' => 'query', 'meta' => 'tokens', 'type' => 'csrf', 'format' => 'json']; 14 | $token = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 15 | $token = $token->query->tokens->csrftoken; 16 | $params = ['action' => 'thank', 'rev' => $rev, 'source' => 'swviewer', 'token' => $token, 'utf8' => '1', 'format' => 'json']; 17 | $res = json_decode($client->makeOAuthCall($accessToken, $apiUrl, true, $params)); 18 | if (isset($res->result->success)) 19 | $responce = ["result" => "success", "user" => $res->result->recipient]; 20 | else 21 | $responce = ["result" => "error", "info" => $res->error->info]; 22 | echo json_encode($responce); 23 | ?> 24 | 25 | -------------------------------------------------------------------------------- /php/welcome-stats.php: -------------------------------------------------------------------------------- 1 | query('SELECT count(*) AS total FROM user'); 22 | // $result = $q->fetchAll(); 23 | // $total_users = $result[0]["total"]; 24 | 25 | if ($searchPhrase !== '') { 26 | $q = $db->prepare('SELECT sum(del) AS del, sum(rollback) AS rollback, sum(warn) AS warn, sum(edits) AS edits, sum(undos) AS undos, sum(protect) AS protect, sum(report) AS report FROM stats WHERE user = :userName'); 27 | $q->execute(array(':userName' => $searchPhrase)); 28 | $user_stats = $q->fetch(PDO::FETCH_ASSOC); 29 | echo json_encode($user_stats); 30 | } else { 31 | $q = $db->query('SELECT sum(del) AS del, sum(rollback) AS rollback, sum(warn) AS warn, sum(edits) AS edits, sum(undos) AS undos, sum(protect) AS protect, sum(report) AS report FROM stats'); 32 | $users_stats = $q->fetch(PDO::FETCH_ASSOC); 33 | echo json_encode($users_stats); 34 | } 35 | ?> -------------------------------------------------------------------------------- /service-worker.js: -------------------------------------------------------------------------------- 1 | const FILES_TO_CACHE = [ 2 | 'offline.html', 3 | 'css/base/variables.css', 4 | 'css/base/fonts.css', 5 | 'css/base/base.css', 6 | 'css/components/comp.css', 7 | 'css/components/dialog.css', 8 | 'css/components/header.css', 9 | 'css/components/pw-po.css', 10 | 'css/layouts/logs.css', 11 | 'css/layouts/talk.css', 12 | 'css/index.css', 13 | 'js/swv.js', 14 | 'js/index-noncritical.js', 15 | 'js/modules/bakeEl.min.js', 16 | 'js/frame/frameKeys.js' 17 | ]; 18 | 19 | const CACHE_NAME = 'SWV-cache'; 20 | 21 | self.addEventListener('install', (event) => { 22 | event.waitUntil( 23 | caches.open(CACHE_NAME).then((cache) => { 24 | console.log('[ServiceWorker] Pre-caching offline page.'); 25 | return cache.addAll(FILES_TO_CACHE); 26 | }) 27 | ); 28 | }); 29 | 30 | self.addEventListener('activate', (event) => { 31 | event.waitUntil( 32 | caches.keys().then((keyList) => { 33 | return Promise.all(keyList.map((key) => { 34 | if (key !== CACHE_NAME) { 35 | console.log('[ServiceWorker] Removing old cache', key); 36 | return caches.delete(key); 37 | } 38 | })); 39 | }) 40 | ) 41 | }); 42 | 43 | self.addEventListener('fetch', (event) => { 44 | if (event.request.destination !== "document" || event.request.mode !== 'navigate') { 45 | return; 46 | } 47 | event.respondWith( 48 | fetch(event.request).catch(() => { 49 | return caches.open(CACHE_NAME) 50 | .then((cache) => { 51 | return cache.match('offline.html'); 52 | }); 53 | }) 54 | ); 55 | }); -------------------------------------------------------------------------------- /sounds/LICENSE.txt: -------------------------------------------------------------------------------- 1 | bump.mp3, license and author of origial file: https://freesound.org/people/Porphyr/sounds/208435/ 2 | message.mp3, license and author of original file: https://freesound.org/people/elmasmalo1/sounds/377017/ 3 | privateMessage.mp3, license and author of original file: https://freesound.org/people/rhodesmas/sounds/342749/ 4 | -------------------------------------------------------------------------------- /sounds/bump.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/sounds/bump.wav -------------------------------------------------------------------------------- /sounds/message.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/sounds/message.mp3 -------------------------------------------------------------------------------- /sounds/privateMessage.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SWViewer/tool-swviewer/9a7eb3dfba64ca64d5c39b877e60575316e18832/sounds/privateMessage.mp3 -------------------------------------------------------------------------------- /stats/getGraphs.py: -------------------------------------------------------------------------------- 1 | # coding: utf8 2 | 3 | import sys 4 | import os 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | os.chdir(script_dir) 7 | sys.path.append('ext_libs') 8 | import matplotlib 9 | matplotlib.use("Agg") 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import toolforge 13 | 14 | conn = toolforge.toolsdb("s53950__SWViewer") 15 | 16 | def get_values(query): 17 | with conn.cursor() as cur: 18 | cur.execute(query) 19 | result = cur.fetchall() 20 | return result 21 | 22 | values = get_values("SELECT count(*) as cnt, date(date) as timestamp FROM logs WHERE date(date) >= date(now()) - INTERVAL 10 day AND date(date) <> CURDATE() GROUP BY date(date) ORDER BY timestamp ASC;") 23 | val1 = [] 24 | val2 = []; 25 | for el in values: 26 | val1.append(el[0]) 27 | val2.append(el[1].strftime("%d-%m-%Y")) 28 | 29 | fig_size = plt.rcParams["figure.figsize"] 30 | fig_size[0] = 8 31 | fig_size[1] = 8 32 | plt.rcParams["figure.figsize"] = fig_size 33 | plt.xlabel("Days") 34 | plt.ylabel("Actions") 35 | plt.grid() 36 | plt.title("Actions per day (last 10 days)") 37 | xn = range(len(val2)) 38 | plt.plot(xn, val1, "r--") 39 | plt.xticks(xn, val2) 40 | plt.gcf().autofmt_xdate() 41 | plt.savefig("actions-count-10.png") 42 | plt.close() 43 | 44 | 45 | values = get_values("SELECT count(*) as cnt, type FROM logs WHERE date(date) >= date(now()) - INTERVAL 10 day AND date(date) <> CURDATE() GROUP BY type;") 46 | val1 = [] 47 | val2 = []; 48 | for el in values: 49 | val1.append(el[0]) 50 | val2.append(el[1]) 51 | 52 | def getIndexType(t, arr1, arr2): 53 | try: 54 | t_raw = arr2.index(t) 55 | except ValueError: 56 | t_raw = -1 57 | if t_raw == -1: 58 | return 0 59 | else: 60 | return arr1[t_raw] 61 | 62 | plt.title("Actions by type (last 10 days)") 63 | val_type = [getIndexType('rollback', val1, val2), getIndexType('undo', val1, val2), getIndexType('delete', val1, val2), getIndexType('edit', val1, val2), getIndexType('warn', val1, val2), getIndexType('report', val1, val2), getIndexType('protect', val1, val2)] 64 | y = np.array(val_type) 65 | 66 | xn = range(len(["Rollbacks", "Undo", "Delete", "Edits", "Warns", "Reports", "Protects"])) 67 | plt.bar(xn, y, color=["#c8b40e", "#db24b0", "#672dd2", "#2dd280", "#d92c26", "#e3791c", "#1cb3e3"]) 68 | plt.xticks(xn, ["Rollbacks", "Undo", "Delete", "Edits", "Warns", "Reports", "Protects"]) 69 | for index, value in enumerate(val_type): 70 | plt.text(index, value, str(value), ha="center") 71 | plt.savefig("actions-type-10.png") 72 | plt.close() 73 | 74 | 75 | 76 | 77 | values = get_values("SELECT count(*) as cnt, user FROM logs WHERE date(date) >= date(now()) - INTERVAL 10 day AND date(date) <> CURDATE() GROUP BY user ORDER BY cnt DESC LIMIT 10;") 78 | val1 = [] 79 | val2 = []; 80 | for el in values: 81 | val1.append(el[0]) 82 | val2.append(el[1]) 83 | 84 | 85 | plt.title("Actions by users (last 10 days)") 86 | y = np.array(val1) 87 | xn = range(len(val2)) 88 | plt.bar(xn, y, color=["#c8b40e", "#db24b0", "#672dd2", "#2dd280", "#d92c26"]) 89 | plt.xticks(xn, val2, rotation=45) 90 | for index, value in enumerate(val1): 91 | plt.text(index, value, str(value), ha="center") 92 | plt.savefig("actions-users-10.png") 93 | plt.close() 94 | 95 | 96 | values = get_values("SELECT count(*) as cnt, wiki FROM logs WHERE date(date) >= date(now()) - INTERVAL 10 day AND date(date) <> CURDATE() GROUP BY wiki ORDER BY cnt DESC;") 97 | val1 = [] 98 | val2 = []; 99 | i = 0 100 | total = 0 101 | for el in values: 102 | i = i + 1 103 | if i <= 9: 104 | val1.append(el[0]) 105 | val2.append(el[1]) 106 | else: 107 | total = total + el[0] 108 | 109 | val1.append(total) 110 | val2.append("Others") 111 | 112 | plt.title("Actions by wikis (last 10 days)") 113 | y = np.array(val1) 114 | xn = range(len(val2)) 115 | plt.bar(xn, y, color=["#c8b40e", "#db24b0", "#672dd2", "#2dd280", "#d92c26"]) 116 | plt.xticks(xn, val2, rotation=45) 117 | for index, value in enumerate(val1): 118 | plt.text(index, value, str(value), ha="center") 119 | plt.savefig("actions-wikis-10.png") 120 | plt.close() 121 | 122 | 123 | -------------------------------------------------------------------------------- /stats/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SWViewer | Stats 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 37 | -------------------------------------------------------------------------------- /templates/about.html: -------------------------------------------------------------------------------- 1 | [about-frame-app] [about-frame-doc] [about-frame-q] [about-frame-traffic]
2 | 3 |

[about-frame-privacy-title]

4 | [about-frame-disc]
5 |
[about-frame-disc-1]
6 |
[about-frame-disc-2]
7 | • [about-frame-wmcstou][about-frame-wmprivacy]

8 | [about-frame-data]
9 | [about-frame-data-desc] 10 | 18 | 1 [about-frame-data-ref-1]
19 | 2 [about-frame-data-ref-2]
20 | 3 [about-frame-data-ref-3] 21 | 22 |

[about-frame-cookies-title]

23 | [about-frame-cookies-desc] 24 | 25 |

[about-frame-licensing]

26 | Copyright © Team SWViewer, 2016-2023; MIT License
27 |

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

28 | 29 |

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

30 | 31 |

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 OR COPYRIGHT HOLDERS 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.

32 | 33 | bump.wav: [about-frame-attrib]
34 | message.mp3: [about-frame-attrib]
35 | privateMessage.mp3: [about-frame-attrib]
36 | Thumbs up font awesome.svg: [about-frame-attrib]
37 | Check Mark (89605) - The Noun Project.svg: [about-frame-attrib]
38 | 39 |

[about-frame-translating]

40 | [about-frame-translators-tw] 41 | 45 | -------------------------------------------------------------------------------- /templates/diffEnd.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /templates/diffStart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /templates/errorEnd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /templates/errorStart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 30 | 31 | 32 |
-------------------------------------------------------------------------------- /templates/newEnd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /templates/newStart.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /templates/newStringEnd.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/newStringStart.html: -------------------------------------------------------------------------------- 1 |
[new-page-frame-not-exist][new-page-frame-new]
 + --------------------------------------------------------------------------------