Bläddra i källkod

Merge branch 'Anarios:main' into main

Kendall Pinto 3 år sedan
förälder
incheckning
1821cde934

+ 1 - 1
Extensions/combined/_locales/gr/messages.json

@@ -15,7 +15,7 @@
     "message": "Ιστοσελίδα"
   },
   "linkFAQ": {
-    "message": "Γρήγορες Ερωτήσιες & Απαντήσεις"
+    "message": "Γρήγορες Ερωτήσεις & Απαντήσεις"
   },
   "linkDonate": {
     "message": "Στηρίξτε"

+ 62 - 0
Extensions/combined/_locales/ja/messages.json

@@ -0,0 +1,62 @@
+{
+  "extensionName": {
+    "message": "Return YouTube Dislike"
+  },
+  "extensionNameBeta": {
+    "message": "Return YouTube Dislike Beta"
+  },
+  "extensionDesc": {
+    "message": "低評価を表示する機能を復元"
+  },
+  "textDeveloper": {
+    "message": "by Dmitry Selivanov & コミュニティ"
+  },
+  "linkWebsite": {
+    "message": "Webサイト"
+  },
+  "linkFAQ": {
+    "message": "FAQ"
+  },
+  "linkDonate": {
+    "message": "寄付"
+  },
+  "linkHelp": {
+    "message": "ヘルプ"
+  },
+  "legendSettings": {
+    "message": "設定"
+  },
+  "textSettings": {
+    "message": "高評価/低評価を表示しない"
+  },
+  "textLikesDisabled": {
+    "message": "投稿者により無効化"
+  },
+  "textSettingsHover": {
+    "message": "評価数のカウントを停止します。"
+  },
+  "textTempUnavailable": {
+    "message": "一時的に利用不可"
+  },
+  "textUpdate": {
+    "message": "アップデート:"
+  },
+  "version30installed": {
+    "message": "バージョン 3.0.0.1 がインストールされました。"
+  },
+  "whatsnew": {
+    "message": "新機能"
+  },
+  "shortsSupport": {
+    "message": "YouTubeショートのサポート"
+  },
+  "customColors": {
+    "message": "低評価ボタンとバーの色のカスタマイズ"
+  },
+  "customNumberFormats": {
+    "message": "評価数の表示形式のカスタマイズ"
+  },
+  "considerDonating": {
+    "message": "この拡張機能を存続させることができるのは、皆様からの寄付だけです。"
+  }
+}

+ 59 - 0
Extensions/combined/_locales/tr/messages.json

@@ -0,0 +1,59 @@
+{
+    "extensionName": {
+        "message": "Return YouTube Dislike"
+    },
+    "extensionDesc": {
+        "message": "Beğenmeme yeteneğini geri getir"
+    },
+    "textDeveloper": {
+        "message": "Dmitry Selivanov ve Topluluk tarafından oluşturuldu"
+    },
+    "linkWebsite": {
+        "message": "Web sitesi"
+    },
+    "linkFAQ": {
+        "message": "SSS"
+    },
+    "linkDonate": {
+        "message": "Bağış Yap"
+    },
+    "linkHelp": {
+        "message": "Yardım"
+    },
+    "legendSettings": {
+        "message": "Ayarlar"
+    },
+    "textSettings": {
+        "message": "Beğenme/Beğenmeme talebini devre dışı bırak"
+    },
+    "textLikesDisabled": {
+        "message": "Sahibi tarafından devre dışı bırakıldı"
+    },
+    "textSettingsHover": {
+        "message": "Beğendiklerinizi ve beğenmediklerinizi saymayı durdurur."
+    },
+    "textTempUnavailable": {
+        "message": "Geçici olarak devre dışı"
+    },
+    "textUpdate": {
+        "message": "güncelle"
+    },
+    "version30installed": {
+        "message": "3.0.0.1 versiyonu yüklendi"
+    },
+    "whatsnew": {
+        "message": "Neler yeni"
+    },
+    "shortsSupport": {
+        "message": "YouTube Shorts Desteği"
+    },
+    "customColors": {
+        "message": "Beğenmeme çubuğu ve butonlar için özel renkler"
+    },
+    "customNumberFormats": {
+        "message": "Özel sayı formatları"
+    },
+    "considerDonating": {
+        "message": "Uzantının sürdürülmesini sağlayan tek şey bağışlarınızdır, lütfen projeyi desteklemeyi düşünün."
+    }
+}

+ 104 - 65
Extensions/combined/changelog/3/changelog_3.0.html

@@ -1,70 +1,109 @@
 <!DOCTYPE html>
 <html>
-<head>
-  <meta content="text/html; charset=utf-8"/>
-  <title title="__MSG_extensionName__">__MSG_extensionName__</title>
-  <link rel="stylesheet" href="/changelog/changelog.css"/>
-  <link rel="preconnect" href="https://fonts.googleapis.com"/>
-  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
-  <link
-    href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap"
-    rel="stylesheet"
-  />
-</head>
-<body>
-<div class="container">
-  <svg width="48" viewBox="0 0 24 24">
-    <path
-      d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z"
-      fill="red"
+  <head>
+    <meta content="text/html; charset=utf-8" />
+    <title title="__MSG_extensionName__">__MSG_extensionName__</title>
+    <link rel="stylesheet" href="/changelog/changelog.css" />
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap"
+      rel="stylesheet"
     />
-    <path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff"/>
-  </svg>
-
-  <h1 style="margin-bottom: 0" title="__MSG_extensionName__">
-    __MSG_extensionName__
-  </h1>
-  <p style="color: var(--lightGrey); margin-top:0" title="__MSG_textDeveloper__">
-    __MSG_textDeveloper__
-  </p>
-  <h2>__MSG_version30installed__</h2>
-  <h2>__MSG_whatsnew__:</h2>
-
-
-  <div style="margin-bottom: 5rem">
-    <ul style="margin-bottom: 5rem">
-      <li>__MSG_shortsSupport__</li>
-      <li>__MSG_customColors__</li>
-      <img style="display: block; margin-bottom: 2rem" src="/changelog/images/colorize_example.jpg"/>
-      <img src="/changelog/images/colorize.jpg"/>
-      <li>__MSG_customNumberFormats__</li>
-      <img src="/changelog/images/number_format.jpg"/>
-    </ul>
-
-    <p>__MSG_considerDonating__</p>
-    <center>
-      <button id="link_website" title="__MSG_linkWebsite__">
-        __MSG_linkWebsite__
-      </button>
-      <button
-        style="margin-top: 0.3em; background: #ff0000"
-        id="link_donate"
-        title="__MSG_linkDonate__"
+  </head>
+  <body>
+    <div class="container">
+      <!-- Header -->
+      <div
+        style="
+          display: flex;
+          align-items: start;
+          position: sticky;
+          top: 4rem;
+          align-self: flex-start;
+        "
       >
-        __MSG_linkDonate__
-      </button>
-      <button id="link_discord">Discord</button>
-      <br/>
-      <button style="margin-top: 0.3rem" id="link_faq" title="__MSG_linkFAQ__">
-        __MSG_linkFAQ__
-      </button>
-      <button id="link_github">GitHub</button>
-      <button style="margin-top: 0.3em" id="link_help" title="__MSG_linkHelp__">
-        __MSG_linkHelp__
-      </button>
-    </center>
-  </div>
-</div>
-</body>
-<script src="/changelog/changelog.js"></script>
+        <!-- Logo -->
+        <svg width="69" viewBox="0 0 24 24">
+          <path
+            d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z"
+            fill="#ff2222"
+          />
+          <path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff" />
+        </svg>
+        <!-- Text -->
+        <div style="display: flex; flex-direction: column; margin-left: 2rem">
+          <h1 style="margin: 0" title="__MSG_extensionName__">
+            __MSG_extensionName__
+          </h1>
+          <p
+            style="color: var(--lightGrey); margin-top: 0.5rem"
+            title="__MSG_textDeveloper__"
+          >
+            __MSG_textDeveloper__
+          </p>
+          <!-- Donation -->
+          <p
+            style="
+              max-width: 42ch;
+              margin-top: 1rem;
+              line-height: 1.75rem;
+              color: var(--lightGrey);
+            "
+          >
+            __MSG_considerDonating__
+          </p>
+          <div>
+            <button id="link_website" title="__MSG_linkWebsite__">
+              __MSG_linkWebsite__
+            </button>
+            <button
+              style="margin-top: 0.3em; background: #ff0000"
+              id="link_donate"
+              title="__MSG_linkDonate__"
+            >
+              __MSG_linkDonate__
+            </button>
+            <button id="link_discord">Discord</button>
+            <br />
+            <button
+              style="margin-top: 0.3rem"
+              id="link_faq"
+              title="__MSG_linkFAQ__"
+            >
+              __MSG_linkFAQ__
+            </button>
+            <button id="link_github">GitHub</button>
+            <button
+              style="margin-top: 0.3em"
+              id="link_help"
+              title="__MSG_linkHelp__"
+            >
+              __MSG_linkHelp__
+            </button>
+          </div>
+        </div>
+      </div>
+
+      <!-- Changelog -->
+      <div style="padding: 0 2rem; line-height: 2rem; color: var(--lightGrey)">
+        <h1 style="margin: 0; color: var(--tertiary)">__MSG_whatsnew__:</h1>
+        <h2 style="margin: 0.5rem 0">
+          <i style="color: var(--primary)">* __MSG_version30installed__ *</i>
+        </h2>
+        <ul style="padding: 0 1rem">
+          <li>__MSG_shortsSupport__</li>
+          <li>__MSG_customNumberFormats__</li>
+          <img src="/changelog/images/number_format.jpg" />
+          <li>__MSG_customColors__</li>
+          <img
+            style="display: block"
+            src="/changelog/images/colorize_example.jpg"
+          />
+          <img src="/changelog/images/colorize.jpg" />
+        </ul>
+      </div>
+    </div>
+  </body>
+  <script src="/changelog/changelog.js"></script>
 </html>

+ 9 - 166
Extensions/combined/changelog/changelog.css

@@ -1,6 +1,6 @@
 /* Variables */
 :root {
-  --primary: #cc2929;
+  --primary: #ff4444;
   --accent: #581111;
 
   --background: #111;
@@ -16,13 +16,15 @@ body {
   background-color: var(--background);
   color: var(--white);
   min-width: 300px;
-  padding: 0.5em;
+  margin: 0;
   font-family: "Roboto", Arial, Helvetica, sans-serif;
   font-size: 16px;
 }
 
-h1 {
-
+img {
+  border-radius: 1rem;
+  box-shadow: 0 0 2rem 0 black;
+  margin: 1rem -1rem;
 }
 
 button {
@@ -42,168 +44,9 @@ button {
 button:hover {
   background: #444;
 }
-
-#ext-version {
-  padding: 0.25rem 0.5rem;
-}
-
-#ext-update {
-  cursor: pointer;
-  color: var(--white);
-  text-decoration: none;
-  background: var(--primary);
-  border-radius: 0.25rem;
-}
-#ext-update:hover {
-  text-decoration: underline;
-}
-
-#ext {
-  padding: 0.25rem 0;
-  z-index: 69;
-  position: fixed;
-  background: var(--secondary);
-  margin: 0;
-  bottom: 1.15rem;
-  right: 1.15rem;
-  border-radius: 0.25rem;
-}
-
-.switch:before {
-  content: attr(data-hover);
-  visibility: hidden;
-  width: 250px;
-  background-color: var(--secondary);
-  border-radius: 0.5rem;
-  padding: 0.5rem;
-
-  position: absolute;
-  z-index: 1;
-  left: 0;
-  top: 160%;
-}
-
-.switch:hover:before {
-  visibility: visible;
-}
-
-#advancedToggle {
-  position: fixed;
-  background: none;
-  box-shadow: none;
-  color: var(--lightGrey);
-  top: 26px;
-  right: 26px;
-  padding: 2px;
-  z-index: 69;
-  height: 2rem;
-  width: 2rem;
-}
-
-#advancedToggle:hover {
-  color: var(--white);
-  transform: rotate(-90deg);
-}
-
-#advancedToggle:active {
-  transform: scale(1.5);
-}
-
-#advancedSettings {
-  opacity: 0;
-  pointer-events: none;
-  transition-duration: 0.15s;
-  transition-timing-function: ease-in-out;
-  transform: scale(1.1);
-  position: fixed;
-  background: var(--background);
-  top: 10px;
-  right: 14px;
-  width: calc(100% - 65px);
-  height: calc(100% - 58px);
-  border: 2px solid var(--secondary);
-  border-radius: 0.5rem;
-  padding: 1rem;
-}
-
-#advancedLegend {
-  color: var(--tertiary) !important;
-  /* margin: auto; */ /* Center the label */
-  /* padding: .25rem .5rem; */
-  /* border-radius: .25rem; */
-  /* border: .25rem solid var(--secondary); */
-}
-
-/*   Switches   */
-.switch {
-  position: relative;
-  display: inline-block;
-  width: 30px;
-  height: 17px;
-  margin-bottom: 1rem;
-}
-
-.switch:last-of-type {
-  margin-bottom: 0;
-}
-
-.switch input {
-  display: none;
-}
-
-.slider {
-  position: absolute;
-  cursor: pointer;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: var(--secondary);
-  transition: 0.4s;
-  border-radius: 34px;
-}
-
-.slider:before {
-  position: absolute;
-  content: "";
-  height: 13px;
-  width: 13px;
-  left: 2px;
-  bottom: 2px;
-  background: var(--lightGrey);
-  transition: 0.4s;
-  border-radius: 50%;
-}
-
-input:checked + .slider {
-  background: var(--accent);
-}
-
-input:checked + .slider:before {
-  transform: translateX(13px);
-  background: var(--primary);
-}
-
-.switchLabel {
-  margin-left: 0.5rem;
-  width: 250px !important;
-  transform: translateX(35px);
-  display: inline-block;
-}
-
-#server-status {
-  height: 72px;
-  width: 90px;
-  /* filter: invert(21%) sepia(100%) saturate(3618%) hue-rotate(102deg)
-    brightness(96%) contrast(108%); */
-}
-
 .container {
   display: flex;
-  flex-direction: column;
-  align-items: center;
-}
-
-h2 {
-  margin: 0.25rem;
+  flex-direction: row;
+  justify-content: center;
+  padding: 4rem 0;
 }

+ 101 - 0
Website/_locales/en.ts

@@ -0,0 +1,101 @@
+import { en } from 'vuetify/src/locale'
+
+export default {
+    ...en,
+    home: {
+        name: 'Home',
+        title: 'Return YouTube Dislike',
+        subtitle: 'Browser extension and an API that shows you dislikes on Youtube',
+        ukraine: 'Support Ukraine',
+        sponsors: 'Sponsors',
+    },
+    install: {
+        name: 'Install',
+        title: 'Select Your Platform',
+        subtitle: 'Available for Firefox and all Chromium browsers',
+        title2: 'Other Platforms',
+        subtitle2: 'If your browser is not yet supported, try this UserScript',
+        title3: 'Third Party Implementations',
+        subtitle3: 'No liability on our side, use at your own risk',
+    },
+    api: {
+        name: 'API',
+        title: 'Welcome to the official RYD docs!',
+        subtitle: 'To get started, select a section from the menu.',
+        rights: {
+            title: 'Usage Rights',
+            subtitle: 'Third party use of this open API is allowed with the following restrictions:',
+            bullet1: 'Attribution: ',
+            bullet1text: 'This project should be clearly attributed with either a link to this repo or a link to returnyoutubedislike.com',
+            bullet2: 'Rate Limiting',
+            bullet2text: 'There are per client rate limits in place of 100 per minute and 10,000 per day. This will return a 429 status code indicating that your application should back off',
+        },
+        url: {
+            title: 'URL Information',
+            subtitle: 'The API is accessible over the following base URL: ',
+        },
+        endpoints: {
+            title: 'Available Endpoints',
+            subtitle: 'List of available endpoints is available here: ',
+        },
+        fetching: {
+            title: 'Basic Fetching Tutorial',
+            subtitle: 'Example to get votes of a given YouTube video ID: ',
+            title2: 'Example Request: ',
+            url: 'Request URL: ',
+            method: 'Request Method: ',
+            headers: 'Headers: ',
+            response: 'Response: ',
+            error1: 'An invalid YouTube ID will return status code 404 "Not Found"',
+            error2: 'An incorrectly formatted YouTube ID will return 400 "Bad Request"'
+        },
+    },
+    help: {
+        name: 'Help',
+        title: 'Troubleshooting',
+        bullet1: 'Make sure you have latest version of extension installed, ',
+        bullet11: 'right now',
+        bullet2: 'Try removing extension and installing it again, then restarting the browser (all active windows, not just one tab)',
+        bullet3: 'Make sure that this link opens: ',
+        bullet31: 'you should see plain text: ',
+        bullet4: 'If nothing of above helps - report your problem in',
+        bullet41: 'in our',
+        bullet4a: 'Tell us your Operating System, Browser Name and Browser Version',
+        bullet4b: 'Take screenshot of page with problem (i.e. youtube video page) with console open (press ',
+        bullet4b1: ') - example screenshot below.',
+        bullet4c: 'Take screenshot of extensions page of your browser with extension installed.',
+        bullet4c1: 'To see extensions put this into address bar: ',
+        firefox: 'for Firefox',
+        chrome: 'for Chrome, Edge, Brave, Opera, Vivaldi',
+    },
+    faq: {
+        name: 'FAQ',
+        title: 'Frequently Asked Questions',
+        subtitle: 'Still have questions? Feel free to join our Discord!',
+        bullet1: 'Where does the extension get its data?',
+        bullet1text: 'A combination of archived data from before the offical YouTube dislike API shut down, and extrapolated extension user behavior.',
+        bullet2: 'Why isn\'t the dislike count updating?',
+        bullet2text: 'Right now video dislikes are cached and they aren\'t updated very frequently. It varies depending on a video\'s popularity but can take anywhere between a few hours and a few days to update.',
+        bullet3: 'How does this work?',
+        bullet3text: 'The extension collects the video ID of the video you are watching, fetches the dislike (and other fields like views, likes etc) using our API. The extension then displays the dislike count and ratio on the page. If you like or dislike a video, that is recorded and sent to the database so an accurate dislike count can be extrapolated.',
+        bullet4: 'Can I share my dislike count with you?',
+        bullet4text: 'Coming soon. We are looking into using Oauth or a different read only API with a limited scope so creators can share their dislike counts verifiability.',
+        bullet5: 'What data do you collect and how is it treated?',
+        bullet5text: 'The extension only collects data that is strictly necessary for it to function properly, such as IP address or ID of the video you\'re watching. None of your data will ever be sold to 3rd parties. If you would like to know more about how we handle security and privacy check out our <a href="https://github.com/Anarios/return-youtube-dislike/blob/main/Docs/SECURITY-FAQ.md">security FAQ</a>.',
+        bullet6: 'How does the API/Backend work?',
+        bullet6text: 'The backend is using archived data from when the youtube api was still returning the dislike count, extension users like/dislike count and extrapolation. In the near future we will be allowing content creators to submit their dislike count easily and safely and we will be adding ArchiveTeam\'s archived data (4.56 billion videos) into our current database. You can also view a video on the topic.',
+        bullet7: 'Why does the dislike count show \'DISLIKES DISABLED\'?',
+        bullet7text: 'Sometimes a recently uploaded video might show \'DISLIKES DISABLED\' even if the creator hasn\'t disabled it, this is due to how we are detecting if dislikes are disabled, it should go away in a few hours or by liking or disliking the video and refreshing the page (hopefully).',
+    },
+    donate: {
+        name: 'Donate',
+        subtitle: 'You can support our efforts to keep the internet free with a donation!',
+    },
+    links: {
+        name: 'Links',
+        title: 'Project Links',
+        subtitle: 'Links to the project and its developers',
+        contact: 'Contact Me',
+        translators: 'Translators',
+    },
+}

+ 101 - 0
Website/_locales/es.ts

@@ -0,0 +1,101 @@
+import { es } from 'vuetify/src/locale'
+// By Alejandro Gayol
+export default {
+    ...es,
+    home: {
+        name: 'Inicio',
+        title: 'Regresar los Dislikes de YouTube',
+        subtitle: 'Una extensión de navegador y una API que te muestra los dislikes en YouTube',
+        ukraine: 'Apoya a Ucrania',
+        sponsors: 'Patrocinadores',
+    },
+    install: {
+        name: 'Instalar',
+        title: 'Elige tu plataforma',
+        subtitle: 'Disponible para Firefox y todos los navegadores Chromium',
+        title2: 'Otras plataformas',
+        subtitle2: 'Si tu navegador aún no es compatible, usa este UserScript',
+        title3: 'Implementaciones de terceros',
+        subtitle3: 'No nos hacemos responsables, úsalas bajo tu propio riesgo',
+    },
+    api: {
+        name: 'API',
+        title: '¡Bienvenido a la documentación oficial de RYD!',
+        subtitle: 'Para empezar, elige una sección del menú.',
+        rights: {
+            title: 'Derechos de uso',
+            subtitle: 'El uso de terceros de esta API abierta se permite bajo las siguientes restricciones: ',
+            bullet1: 'Atribución: ',
+            bullet1text: 'El proyecto debe estar claramente atribuido con un link a esta página o a returnyoutubedislike.com',
+            bullet2: 'Límites de velocidad',
+            bullet2text: 'Hay límites de velocidad por cliente de 100 por minuto y 10.000 por día. Esto regresará un código de estado 409 indicando que tu aplicación debe bajar la velocidad.',
+        },
+        url: {
+            title: 'Información de URL',
+            subtitle: 'Esta API es accesible sobre la siguiente URL base: ',
+        },
+        endpoints: {
+            title: 'Endpoints disponibles',
+            subtitle: 'La lista de los endpoints disponibles está disponible aquí: ',
+        },
+        fetching: {
+            title: 'Tutorial de consulta básica',
+            subtitle: 'Ejemplo para obtener los votos del ID de un vídeo de YouTube: ',
+            title2: 'Consulta de ejemplo: ',
+            url: 'URL de la consulta: ',
+            method: 'Método de la consulta: ',
+            headers: 'Encabezados: ',
+            response: 'Respuesta: ',
+            error1: 'Un ID de YouTube inválido responderá con el código de estado 404 "Not Found"',
+            error2: 'Un ID de YouTube con mal formato responderá con 400 "Bad Request"'
+        },
+    },
+    help: {
+        name: 'Ayuda',
+        title: 'Solución de problemas',
+        bullet1: 'Asegúrate de que tienes la última versión de la extensión instalada, ',
+        bullet11: 'ahora mismo',
+        bullet2: 'Prueba a eliminar la extensión e instalarla de nuevo, después reinicia el navegador (todas las ventanas activas, no solo una pestaña)',
+        bullet3: 'Asegúrate de qué este link se abre: ',
+        bullet31: 'deberías ver este texto: ',
+        bullet4: 'Si nada de esto funciona, reporta tú problema en',
+        bullet41: 'en nuestro',
+        bullet4a: 'Dínos tu sistema operativo, nombre del navegador y versión del navegador',
+        bullet4b: 'Toma una captura de pantalla de la página con el problema (cómo una página de un vídeo de YouTube) con la consola abierta (pulsa ',
+        bullet4b1: ') - captura de pantalla de ejemplo abajo.',
+        bullet4c: 'Toma una captura de la página de extensiones de tu navegador con la extensión instalada.',
+        bullet4c1: 'Para ver las extensiones pon esto en la barra de dirección: ',
+        firefox: 'para Firefox',
+        chrome: 'para Chrome, Edge, Brave, Opera, Vivaldi',
+    },
+    faq: {
+        name: 'FAQ',
+        title: 'Preguntas frecuentes',
+        subtitle: '¿Sígues teniendo problemas? ¡Sientete libre de unirte a nuestro Discord (en inglés)!',
+        bullet1: '¿De dónde saca sus datos la extensión?',
+        bullet1text: 'Una combinación de datos archivados antes de que la API oficial de dislikes de YouTube se apagará, y datos estimados basados en los usuarios.',
+        bullet2: '¿Por qué no se actualiza el contador de dislikes?',
+        bullet2text: 'Ahora mismo los dislikes son guardados y no se actualizan muy frecuentemente. Varia dependiendo de la popularidad de un vídeo pero puede tardar entre unas pocas horas y unos pocos días en actualizarse.',
+        bullet3: '¿Cómo funciona esto?',
+        bullet3text: 'La extensión recoge el ID del vídeo qué estas viendo, carga los dislikes (y otros campos cómo las visitas, likes, etc) usando nuestra API. Entonces, la extensión muestra los dislikes y el radio en la página. Si le das like o dislike a un vídeo, eso se guarda y se envía a la base de datos para qué un contador de dislikes más acertado pueda ser creado.',
+        bullet4: '¿Puedo compartir mi contador de dislikes con vosotros?',
+        bullet4text: 'Próximamente. Estamos investigando en usar Oauth o una API diferente de solo lectura con alcance limitado para que los creadores puedan compartir sus contadores de dislikes verificablemente.',
+        bullet5: '¿Qué datos guardais y cómo son guardados?',
+        bullet5text: 'La extensión solo guarda datos que son estrictamente necesarios para que funcione correctamente, cómo la dirección IP o el ID del vídeo que estas viendo. Tus datos nunca serán vendidos a terceros. Si te gustaría saber más sobre cómo tratamos la seguridad y la privacidad mira nuestra <a href="https://github.com/Anarios/return-youtube-dislike/blob/main/Docs/SECURITY-FAQ.md">security FAQ</a>.',
+        bullet6: '¿Cómo funciona la API/Backend?',
+        bullet6text: 'El backend usa datos archivados de cuando la API de YouTube seguía proporcionando el contador de dislikes, los votos de usuarios de la extensión y extrapolación. En un futuro cercano permitíremos a los creadores de contenido proporcionar su contador de dislikes de forma fácil y segura y añadíremos datos archivados de ArchiveTeam (4,56 billones de vídeos) en nuestra base de datos. También puedes ver un vídeo al respecto.',
+        bullet7: '¿Porque el contador de dislikes dice "DISLIKES DISABLED"?',
+        bullet7text: 'A veces, un vídeo subido recientemente puede mostrar "DISLIKES DISABLED" incluso si el creador no lo ha desactivado, esto se debe a la forma en que detectamos si los "dislikes" están desactivados, debería desaparecer en unas horas o al darle like o dislike al vídeo y actualizar la página (con suerte).',
+    },
+    donate: {
+        name: 'Donar',
+        subtitle: '¡Puedes apoyar nuestros esfuerzos de mantener el internet libre con una donación!',
+    },
+    links: {
+        name: 'Enlaces',
+        title: 'Links del proyecto',
+        subtitle: 'Links al proyecto y sus desarrolladores',
+        contact: 'Contactame',
+        translators: 'Traductores',
+    },
+}

+ 101 - 0
Website/_locales/ru.ts

@@ -0,0 +1,101 @@
+import { ru } from 'vuetify/src/locale'
+// By Nikita Krupin
+export default {
+    ...ru,
+    home: {
+        name: 'Главная',
+        title: 'Вернуть YouTube Дизлайки',
+        subtitle: 'Расширение для браузера и API, которые показывают вам дизлайки в Youtube',
+        ukraine: 'Поддержите Украину',
+        sponsors: 'Спонсоры',
+    },
+    install: {
+        name: 'Скачать',
+        title: 'Выберите Свою Платформу',
+        subtitle: 'Доступно в Firefox и во всех Chromium браузерах',
+        title2: 'Другие Платформы',
+        subtitle2: 'Если ваш браузер еще не поддерживается, попробуйте этот пользовательский скрипт',
+        title3: 'От Других Разработчиков',
+        subtitle3: 'Никакой ответственности с нашей стороны, используйте на свой страх и риск',
+    },
+    api: {
+        name: 'API',
+        title: 'Добро пожаловать в официальную документацию RYD!',
+        subtitle: 'Чтобы начать, выберите раздел в меню.',
+        rights: {
+            title: 'Права пользования',
+            subtitle: 'Использование этого открытого API третьими лицами разрешено со следующими ограничениями:',
+            bullet1: 'Aтрибуция: ',
+            bullet1text: 'Этот проект должен быть четко описан либо ссылкой на этот репозиторий, либо ссылкой на returnyoutubedislike.com',
+            bullet2: 'Ограничение Скорости',
+            bullet2text: 'Существуют ограничения на скорость для каждого клиента - 100 в минуту и 10 000 в день. Это вернет код 429, указывающий на то, что ваше приложение превысило лимит',
+        },
+        url: {
+            title: 'Информация о URL-адресе',
+            subtitle: 'API доступен по следующему базовому URL-адресу: ',
+        },
+        endpoints: {
+            title: 'Доступные Конечные точки',
+            subtitle: 'Список доступных конечных точек доступен здесь: ',
+        },
+        fetching: {
+            title: 'Базовое руководство по выборке',
+            subtitle: 'Пример получения голосов на заданный видео ID на YouTube ',
+            title2: 'Пример запроса: ',
+            url: 'URL-адрес запроса: ',
+            method: 'Способ запроса: ',
+            headers: 'Шапка: ',
+            response: 'Ответ: ',
+            error1: 'Неверный YouTube ID вернет код состояния 404 "Не найден"',
+            error2: 'Неправильно отформатированный YouTube ID вернет 400 "Неверный запрос"'
+        },
+    },
+    help: {
+        name: 'Помощь',
+        title: 'Диагностика',
+        bullet1: 'Убедитесь, что у вас установлена последняя версия расширения, ',
+        bullet11: 'прямо сейчас',
+        bullet2: 'Попробуйте удалить расширение и установить его снова, затем перезагрузите браузер (все активные окна, а не только одну вкладку).',
+        bullet3: 'Убедитесь, что эта ссылка открывается:',
+        bullet31: 'вы должны увидеть текст: ',
+        bullet4: 'Если ничего из вышеперечисленного не помогает - сообщите о своей проблеме в',
+        bullet41: 'в нашем',
+        bullet4a: 'Сообщите нам вашу операционную систему, Название браузера и версию браузера',
+        bullet4b: 'Сделайте снимок экрана страницы с проблемой (например, страницы видео на YouTube) с открытой консолью (нажмите ',
+        bullet4b1: ') - пример скриншота ниже.',
+        bullet4c: 'Сделайте снимок экрана страницы расширений вашего браузера с установленным расширением.',
+        bullet4c1: 'Чтобы увидеть расширения, введите это в адресную строку: ',
+        firefox: 'для Firefox',
+        chrome: 'для Chrome, Edge, Brave, Opera, Vivaldi',
+    },
+    faq: {
+        name: 'FAQ',
+        title: 'Частые Вопросы',
+        subtitle: 'Все еще есть вопросы? Не стесняйтесь заглянуть в наш Дискорд!',
+        bullet1: 'Откуда расширение получает данные?',
+        bullet1text: 'Комбинация архивных данных, полученных до закрытия официального YouTube дизлайк API, и экстраполяция поведения пользователей расширения.',
+        bullet2: 'Почему количество дизлайков не обновляется?',
+        bullet2text: 'На данный момент видео дизлайки кэшируются, и обновляются не очень часто. Это зависит от популярности видео, но обновление может занять от нескольких часов до нескольких дней.',
+        bullet3: 'Как это работает?',
+        bullet3text: 'Расширение берет ID видео которое вы смотрите, извлекает количество дизлайков (и другие поля, такие как просмотры, лайки и т.д.) используя наш API. Затем расширение отображает количество дизлайков на странице. Если если вы лайкаете или дизлайкаете видео, это записывается и отправляется в базу данных, чтобы можно было экстраполировать точное количество дизлайков.',
+        bullet4: 'Могу я поделиться с вами своим количеством дизлайков?',
+        bullet4text: 'Скоро. Мы рассматриваем возможность использования Oauth или другого API, доступного только для чтения, с ограниченной областью действия, чтобы создатели могли делиться своим количеством дизлайков.',
+        bullet5: 'Какие данные вы собираете и как они обрабатываются?',
+        bullet5text: 'Расширение собирает только те данные, которые строго необходимы для его правильной работы, такие как IP-адрес или ID видео которое вы смотрите. Ваши данные никогда не будут проданы третьим лицам. Если вы хотите узнать больше о том, как мы обеспечиваем безопасность и конфиденциальность, ознакомьтесь с нашим <a href="https://github.com/Anarios/return-youtube-dislike/blob/main/Docs/SECURITY-FAQ.md">FAQ по безопасности</a>.',
+        bullet6: 'Как работает API/серверная часть?',
+        bullet6text: 'Серверная часть использует архивные данные с тех пор, когда YouTube API все еще возвращал количество дизлайков, количество лайков/дизлайков пользователей расширения и экстраполяцию. В ближайшем будущем мы позволим создателям контента легко и безопасно отправлять количество своих дизлайков, и мы добавим архивные данные ArchiveTeam (4,56 миллиарда видео) в нашу текущую базу данных. Вы также можете просмотреть видео на эту тему.',
+        bullet7: 'Почему дизлайки показывают \'DISLIKES DISABLED\'?',
+        bullet7text: 'Иногда недавно загруженное видео может показывать "DISLIKES DISABLED", это связано с тем как мы определяем отключены ли дизлайки, должно исчезнуть через несколько часов или после лайка или дизлайка видео и обновления страницы (надеюсь).',
+    },
+    donate: {
+        name: 'Пожертвовать',
+        subtitle: 'Вы можете поддержать наши усилия по обеспечению бесплатного Интернета пожертвованием!',
+    },
+    links: {
+        name: 'Ссылки',
+        title: 'Ссылки Проекта',
+        subtitle: 'Ссылки на проект и его разработчиков',
+        contact: 'Связаться',
+        translators: 'Переводчики',
+    },
+}

+ 101 - 0
Website/_locales/tr.ts

@@ -0,0 +1,101 @@
+import { tr } from 'vuetify/src/locale'
+// By Batuhan Kara
+export default {
+    ...tr,
+    home: {
+        name: 'Ana Sayfa',
+        title: 'YouTube Beğenmeme Sayısını Gör',
+        subtitle: 'YouTube\'da beğenmeme sayılarını gösteren tarayıcı uzantısı ve API',
+        ukraine: 'Ukrayna\'ya Destek Ol',
+        sponsors: 'Sponsorlar',
+    },
+    install: {
+        name: 'Yükle',
+        title: 'Platformunuzu Seçin',
+        subtitle: 'Firefox ve bütün Chromium tarayıcılarda kullanılabilir',
+        title2: 'Diğer Platformlar',
+        subtitle2: 'Tarayıcınız henüz desteklenmiyorsa, UserScript yöntemini deneyin',
+        title3: 'Üçüncü Parti Uygulamaları',
+        subtitle3: 'Riski tamamen size aittir, bizim tarafımızda sorumluluk kabul edilmemektedir',
+    },
+    api: {
+        name: 'API',
+        title: 'Resmi RYD belgelerine hoş geldiniz!',
+        subtitle: 'Başlamak için, menüden bir bölüm seçin.',
+        rights: {
+            title: 'Kullanım Hakları',
+            subtitle: 'Herkese açık API\'nin üçüncü parti kişilerin kullanımında aşağıdaki kısıtlamalara izin verir: ',
+            bullet1: 'Atıf: ',
+            bullet1text: 'TBu proje bu depo(repo)\'ya bir bağlantı ile ya da returnyoutubedislike.com\'a bağlantı olarak açıkça ilişkilendirilmelidir',
+            bullet2: 'Oranı Sınırlama',
+            bullet2text: 'Dakikada 100 ve günde 10.000 müşteri başına oranı sınırlama vardır. Uygulamınızın geri çekmesi gerektiğini belirten bir 429 durum kodu döndürür.',
+        },
+        url: {
+            title: 'URL Bilgisi',
+            subtitle: 'API\'ye bu URL üzerinden ulaşılabilir: ',
+        },
+        endpoints: {
+            title: 'Kullanılabilir Endpoint\'ler',
+            subtitle: 'Kullanılabilir endpointlerin listesi burada mevcuttur: ',
+        },
+        fetching: {
+            title: 'Temel Fetching Öğretici',
+            subtitle: 'Belirli bir YouTube ID kimliğinin oylarını almak için örnek: ',
+            title2: 'Örnek İstek: ',
+            url: 'İstek URL: ',
+            method: 'İstek Yöntemi: ',
+            headers: 'Başlık: ',
+            response: 'Sonuç: ',
+            error1: 'Geçersiz bir YouTube ID kimliği 404 "Bulunamadı" olarak döner.',
+            error2: 'Yanlış biçimlendirilmeş bir YouTube ID kimliği 400 "Geçersiz İstek" olarak döner.'
+        },
+    },
+    help: {
+        name: 'Yardım',
+        title: 'Sorunu Giderin',
+        bullet1: 'Uzantının en son sürümünün kurulu olduğundan emin olun, şu anki sürüm ',
+        bullet11: '',
+        bullet2: 'Uzantıyı kaldırp yeniden yüklemeyi deneyin, sonra tarayıcınızı yeniden başlatın(tüm aktif sekmeler, sadece tek sekme değil).',
+        bullet3: 'Bu bağlantıyı açtığınızdan emin olun: ',
+        bullet31: 'şöyle düz metin göreceksiniz: ',
+        bullet4: 'Yukarıdakiler yardımcı olmadıysa, ',
+        bullet41: ' kanalında raporu bildirin',
+        bullet4a: 'Bize İşletim sistemini, tarayıcı adını ve tarayıcı sürümünü söyleyin',
+        bullet4b: 'Konsol açıkken (F12',
+        bullet4b1: '\'ye basın) sorunu yaşadığınız sayfanın ekran görüntüsünü alın (yani YouTube izleme sayfası) - Ekran görüntüsü örneği aşağıdadır.',
+        bullet4c: 'Uzantı yüklüyken tarayıcınızın uzantılar sayfasının ekran görüntüsünü alın.',
+        bullet4c1: 'Uzantıları görmek için bunu adres çubuğuna kopyalayın: ',
+        firefox: 'Firefox için',
+        chrome: 'Chrome, Edge, Brave, Opera ve Vivaldi için',
+    },
+    faq: {
+        name: 'SSS',
+        title: 'Sıkça Sorulan Sorular',
+        subtitle: 'Hala sorularınız mı var? Discordumuza katılmaktan çekinmeyin!',
+        bullet1: 'Uzantı verilerini nereden alıyor?',
+        bullet1text: 'Resmi YouTube beğenmeme sayısı API\'si kapatılmadan önceki arşivlenmiş verilerden ve uzantının kullanıcının davranışlarıyla tahmin eder.',
+        bullet2: 'Beğenmeme sayısı neden güncellenmiyor?',
+        bullet2text: 'Şu anda beğenmeme durumları önbelleğe alınır ve çok sık güncellenmez. Bir videonun popülerliğine göre değişir ancak güncellenmesi birkaç saat ile birkaç gün arasında sürebilir.',
+        bullet3: 'Nasıl Çalışır?',
+        bullet3text: 'Uzantı izlediğiniz videonun kimliğini toplar, API\'mizi kullanarak beğenmediğinizi (ve görüntülenme, beğeni vb.) getirir. Uzantı daha sonra sayfada beğenmeme sayısını ve oranını görüntüler. Bir videoyu beğenirseniz veya beğenmezseniz kaydedilir ve veri tabanına gönderilir, böylece doğru beğenmeme sayısını tahmin edebilir.',
+        bullet4: 'Beğenmeme sayımı sizinle paylaşabilirmiyim?',
+        bullet4text: 'Çok yakında. İçerik üreticilerin beğenmeme sayıları doğrulanabilirliğini paylaşabilmeleri için Oauth ya da sınırlı kapsamda farklı salt okunur API kullanmayı düşünüyoruz.',
+        bullet5: 'Hangi verileri topluyorsunuz ve bunlar nasıl işleniyor?',
+        bullet5text: 'Uzantı yalnızca izlediğiniz videonun IP adresi veya videonun ID\'si gibi düzgün çalışması için, kesinlikle gerekli olan verileri toplar. Verileriniz asla 3. şahıslara satılmayacaktır. Güvenliği ve gizliliği nasıl ele aldığımız hakkında daha fazla bilgi için <a href="https://github.com/Anarios/return-youtube-dislike/blob/main/Docs/SECURITY-FAQ.md">security FAQ</a> adresine gidin.',
+        bullet6: 'API/Arka uç(Backend) nasıl çalışıyor?',
+        bullet6text: 'Arka uç(backend) YouTube API\'nin beğenmeme sayısını ve uzantı kullanıcılarının beğenme/beğenmeme sayısı sonuçların genişletilmesinin döndürmeye devam ettiği zamana ait arşivlenmiş verileri kullanır. Yakın zamanda içerik üreticilerin beğenmeme sayısını kolay ve güvenli bir şekilde göndermelerine izin vereceğiz ve ArchiveTeam\'in arşivlenmiş verilerini (4.56 milyar video) veritabanımıza ekleyeceğiz. Konu ile ilgili videoyu izleyebilirsiniz.',
+        bullet7: 'Beğenmeme sayısı neden \'DISLIKES DISABLED\' olarak gözüküyor',
+        bullet7text: 'Bazen yakın zamanda yüklenen bir videoda, içerik üreticisi onu devre dışı bırakmamış olsa bile \'DISLIKES DISABLED\' olarak gözükebilir. Bunun nedeni, beğenmeme sayısını devre dışı bırakıp bırakmadığını tespit etmemizdir. Birkaç saat içinde videoyu beğenerek ya da beğenmeyerek veya sayfayı yenileyerek(umarım) kaybolması gerekir.',
+    },
+    donate: {
+        name: 'Bağış yap',
+        subtitle: 'İnterneti özgür bırakma çabalarımızla bize bir bağışla destekleyebilirsiniz!',
+    },
+    links: {
+        name: 'Bağlantılar',
+        title: 'Projeler için Bağlantılar',
+        subtitle: 'Proje ve geliştiriciler için bağlantılar',
+        contact: 'Bana Ulaş',
+        translators: 'Çevirenler',
+    },
+}

+ 0 - 4
Website/assets/variables.scss

@@ -1,4 +0,0 @@
-// Ref: https://github.com/nuxt-community/vuetify-module#customvariables
-//
-// The variables you want to modify
-// $font-size-root: 20px;

+ 122 - 25
Website/layouts/default.vue

@@ -1,10 +1,14 @@
 <template>
   <v-app dark>
     <!-- height = 4rem, margin-y = 1rem -->
-    <v-app-bar app text class="topBar fly-in-from-top my-4 mx-auto">
+    <v-app-bar
+      app
+      class="topBar glass elevation-0 fly-in-from-top my-4 mx-auto"
+    >
+      <!-- Translator desktop -->
       <v-tabs centered center-active color="primary" router show-arrows>
         <v-tab v-for="link in links" :key="link.path" :to="link.path">
-          {{ link.name }}
+          {{ $vuetify.lang.t(`$vuetify.${link.name}.name`) }}
         </v-tab>
       </v-tabs>
     </v-app-bar>
@@ -12,7 +16,7 @@
     <!-- abstract background -->
     <v-img
       src="/ui/abstract.svg"
-      style="position: absolute; left: 0; right: 0; width: 100vw; height: 100vh"
+      style="position: fixed; left: 0; right: 0; width: 100vw; height: 100vh"
     />
 
     <v-main style="padding-top: 4rem !important">
@@ -25,6 +29,34 @@
       </center>
     </v-main>
 
+    <!-- Translator mobile -->
+    <v-menu
+      top
+      left
+      offset-y
+      rounded="lg"
+      nudge-top="16"
+      class="d-flex flex-column"
+      transition="slide-y-reverse-transition"
+    >
+      <template v-slot:activator="{ on, attrs }">
+        <v-btn text fab class="glass" id="translator" v-bind="attrs" v-on="on">
+          <v-icon>mdi-translate</v-icon>
+        </v-btn>
+      </template>
+      <v-list class="py-0">
+        <v-list-item
+          v-for="(lang, index) in langs"
+          :key="index"
+          link
+          :class="$vuetify.lang.current === lang.locale ? 'primary--text' : ''"
+          @click="changeLocale(lang.locale)"
+        >
+          <v-list-item-title v-text="lang.name"></v-list-item-title>
+        </v-list-item>
+      </v-list>
+    </v-menu>
+
     <!--   Debugger Notification   -->
     <v-snackbar
       v-model="alert.show"
@@ -58,22 +90,39 @@
 export default {
   data: () => ({
     links: [
-      { name: "Home", path: "/" },
-      { name: "Install", path: "/install" },
-      { name: "API", path: "/docs" },
-      { name: "Help", path: "/help" },
-      { name: "FAQ", path: "/faq" },
-      { name: "Donate", path: "/donate" },
-      { name: "Links", path: "/links" },
+      { name: "home", path: "/" },
+      { name: "install", path: "/install" },
+      { name: "api", path: "/docs" },
+      { name: "help", path: "/help" },
+      { name: "faq", path: "/faq" },
+      { name: "donate", path: "/donate" },
+      { name: "links", path: "/links" },
+    ],
+    langs: [
+      { name: "English", locale: "en" },
+      { name: "Español", locale: "es" },
+      { name: "Türkçe", locale: "tr" },
+      { name: "Русский", locale: "ru" },
+      // { name: "Français", locale: "fr" },
+      // { name: "Deutsch", locale: "de" },
+      // ...
     ],
     alert: {
       show: false,
       html: "",
     },
   }),
+  created() {
+    // fetch locale preference or browser default
+    if (process.client && navigator.language) {
+      if (!("locale" in localStorage))
+        this.$vuetify.lang.current = navigator.language.slice(0, 2);
+      else this.$vuetify.lang.current = localStorage.locale;
+    }
+  },
   mounted() {
     setTimeout(() => {
-      // Chrome < 70 or FF < 60
+      // Chrome < 70 or FF < 60 unsupported warning popup
       if (
         (this.$ua._parsed.name == "Chrome" &&
           parseInt(this.$ua._parsed.version.split(".")[0]) < 70) ||
@@ -85,14 +134,17 @@ export default {
         </b> is not supported. Consider upgrading to the latest version.`;
         this.alert.show = true;
       }
-
-      // Win7
-      if (window.navigator.userAgent.indexOf("Windows NT 6.1") > -1) {
-        this.alert.html = `<b style="background: #222; border-radius: .5rem; padding: .25rem .5rem; margin: 0 .25rem;">Windows 7</b> is not supported. Consider upgrading Windows, or installing Linux.`;
-        this.alert.show = true;
-      }
     }, 1000);
   },
+  methods: {
+    changeLocale(locale) {
+      // reset to browser default if selection matches browser default
+      if (locale == navigator.language.slice(0, 2)) localStorage.clear();
+      // else save preference
+      else localStorage.locale = locale;
+      this.$vuetify.lang.current = locale;
+    },
+  },
 };
 </script>
 
@@ -147,18 +199,32 @@ body {
   margin: 0.25em;
 }
 
+.title-text {
+  font-size: 3rem;
+}
 .topBar {
   padding: 0 3rem;
   width: fit-content !important;
-  backdrop-filter: blur(16px) saturate(180%);
-  -webkit-backdrop-filter: blur(16px) saturate(180%);
-  background: rgba(42, 42, 42, 0.75) !important;
   border-radius: 1rem !important;
-  /* border: 1px solid #222; */
-  overflow: hidden;
+  /* overflow: hidden; */
 }
-.title-text {
-  font-size: 3rem;
+.glass {
+  backdrop-filter: blur(16px) saturate(200%);
+  -webkit-backdrop-filter: blur(16px) saturate(200%);
+  background: rgba(42, 42, 42, 0.75) !important;
+}
+
+/* used in docs.vue */
+.flex-wrapper {
+  display: flex;
+  flex-wrap: nowrap;
+}
+
+#translator {
+  border-radius: 1rem !important;
+  position: fixed;
+  bottom: 2rem;
+  right: 1rem;
 }
 
 @media (max-width: 768px) {
@@ -172,6 +238,38 @@ body {
     ) !important; /* (2rem = mx-4) 1rem on left, 1rem on right */
     padding: 0;
   }
+  .flex-wrapper {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  #translator {
+    bottom: 1rem;
+  }
+}
+
+/* used in docs.vue, help.vue and faq.vue */
+.width-constraint {
+  max-width: auto;
+  margin: 0 auto;
+}
+@media (min-width: 960px) {
+  /* tablet */
+  .width-constraint {
+    width: 75vw;
+  }
+}
+@media (min-width: 1264px) {
+  /* desktop */
+  .width-constraint {
+    width: 60vw;
+  }
+}
+
+@media (min-width: 1904) {
+  /* 4k/ultrawide */
+  .width-constraint {
+    width: 42vw;
+  }
 }
 
 /* animations and all that */
@@ -185,7 +283,6 @@ body {
 .swoop-right-leave-active {
   transition-duration: 0.1s;
   transition-property: opacity, transform;
-  overflow: hidden;
 }
 
 .swoop-left-enter,

+ 11 - 9
Website/nuxt.config.js

@@ -1,5 +1,10 @@
-import colors from "vuetify/es5/util/colors";
-
+import en from "./_locales/en";
+import es from "./_locales/es";
+import tr from "./_locales/tr";
+import ru from "./_locales/ru";
+// import fr from "./_locales/fr";
+// import de from "./_locales/de";
+// ...
 export default {
   // Global page headers: https://go.nuxtjs.dev/config-head
   head: {
@@ -42,18 +47,15 @@ export default {
 
   // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
   vuetify: {
-    customVariables: ["~/assets/variables.scss"],
+    lang: {
+      locales: { en, es, tr, ru /*, fr, de, ...*/ },
+      current: "en",
+    },
     theme: {
       dark: true,
       themes: {
         dark: {
           primary: "#ff4444",
-          accent: colors.grey.darken3,
-          secondary: colors.amber.darken3,
-          info: colors.teal.lighten1,
-          warning: colors.amber.base,
-          error: colors.deepOrange.accent4,
-          success: colors.green.accent3,
         },
       },
     },

+ 37 - 38
Website/pages/docs.vue

@@ -1,48 +1,47 @@
 <template>
-  <div class="row wrap justify-center full-width mx-auto" style="width: 80vw">
-    <!--   Left Section // "Sections" Card   -->
-    <v-card
-      class="col-xs-12 mx-2 elevation-0"
+  <!-- min-height overrides vertical centering from the parent default.vue layout -->
+  <div
+    class="width-constraint flex-wrapper"
+    style="min-height: calc(100vh - 10rem); position: relative"
+  >
+    <!-- docs navigation  -->
+    <v-list
+      class="py-0 mr-3"
       style="
         background: transparent;
-        height: max-content;
         position: sticky;
-        top: 5.5rem;
-        max-width: 500px;
+        top: 6rem;
+        align-self: flex-start;
       "
     >
-      <!-- <v-card-title style="padding-bottom: 0 !important; color: #aaa">
-        Sections
-      </v-card-title> -->
-      <v-list style="background: transparent">
-        <!--   Dynamically Generate Links From Below   -->
-        <v-list-item
-          v-for="(item, i) in links"
-          :key="i"
-          :to="item.to"
-          router
-          class="mt-4"
-          color="primary"
-          style="overflow: hidden; border-radius: 0.75rem"
-        >
-          <v-list-item-title style="text-align: right">
-            <v-list-item-title v-text="item.text" />
-          </v-list-item-title>
-          <v-list-item-icon>
-            <v-icon v-text="item.icon" />
-          </v-list-item-icon>
-        </v-list-item>
-      </v-list>
-    </v-card>
+      <v-list-item
+        v-for="(link, i) in links"
+        :key="i"
+        :to="link.to"
+        router
+        class="mb-4"
+        color="primary"
+        style="overflow: hidden !important; border-radius: 0.75rem"
+      >
+        <v-list-item-title style="text-align: right">
+          <v-list-item-title
+            v-text="$vuetify.lang.t(`$vuetify.api.${link.name}.title`)"
+          />
+        </v-list-item-title>
+        <v-list-item-icon>
+          <v-icon v-text="link.icon" />
+        </v-list-item-icon>
+      </v-list-item>
+    </v-list>
 
-    <!--   Child Pages // Card   -->
+    <!-- docs content -->
     <v-card
-      class="col-xs-12 col-md-6 text-left mx-2 my-6 pa-8"
+      class="text-left glass pa-6"
       style="
+        flex-grow: 2;
         height: max-content;
-        background-color: #222;
+        max-width: 90vw !important;
         border-radius: 0.75rem;
-        width: 90%;
       "
     >
       <NuxtChild />
@@ -66,22 +65,22 @@ export default {
       //---   Links To Generate Above    ---//
       links: [
         {
-          text: "Usage Rights",
+          name: "rights",
           icon: "mdi-book-open-variant",
           to: "/docs/usage-rights",
         },
         {
-          text: "URL Information",
+          name: "url",
           icon: "mdi-web",
           to: "/docs/url",
         },
         {
-          text: "Available Endpoints",
+          name: "endpoints",
           icon: "mdi-transit-connection-variant",
           to: "/docs/endpoints",
         },
         {
-          text: "Basic Fetching Tutorial",
+          name: "fetching",
           icon: "mdi-school",
           to: "/docs/fetching",
         },

+ 8 - 4
Website/pages/docs/endpoints.vue

@@ -1,8 +1,12 @@
 <template>
-  <div style="line-height: 3rem">
-    <h1 class="primary--text">Available Endpoints</h1>
-    List of available endpoints is available here:<br />
-    <a :href="endpointUrl" target="_blank" v-text="endpointUrl" />
+  <div style="line-height: 2rem">
+    <h2 class="primary--text">
+      {{ $vuetify.lang.t("$vuetify.api.endpoints.title") }}
+    </h2>
+    <div class="mt-4">
+      {{ $vuetify.lang.t("$vuetify.api.endpoints.subtitle") }}
+      <a :href="endpointUrl" target="_blank" v-text="endpointUrl" />
+    </div>
   </div>
 </template>
 

+ 36 - 33
Website/pages/docs/fetching.vue

@@ -1,39 +1,47 @@
 <template>
-  <div style="line-height: 3rem">
-    <h1 class="primary--text">Basic Fetching Tutorial</h1>
+  <div style="line-height: 2rem">
+    <h2 class="primary--text">
+      {{ $vuetify.lang.t("$vuetify.api.fetching.title") }}
+    </h2>
 
-    <span>Example to get votes of a given YouTube video ID:</span>
-    <a href="https://youtube.com/watch?v=kxOuG8jMIgI" target="_blank"
-      >kxOuG8jMIgI</a
-    >
+    <div class="ma-2">
+      {{ $vuetify.lang.t("$vuetify.api.fetching.subtitle") }}
 
-    <h2>Example Request:</h2>
-    <span>Request URL:</span>
-    <a
-      :href="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
-      target="_blank"
-      v-text="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
-    />
-    <br />
-    <span>
-      Request Method:
+      <a href="https://youtube.com/watch?v=kxOuG8jMIgI" target="_blank">
+        kxOuG8jMIgI
+      </a>
+    </div>
+
+    <h3 class="mt-6">{{ $vuetify.lang.t("$vuetify.api.fetching.title2") }}</h3>
+    <div class="ma-2">
+      {{ $vuetify.lang.t("$vuetify.api.fetching.url") }}
+      <a
+        :href="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
+        target="_blank"
+        v-text="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
+      />
+      <br />
+      {{ $vuetify.lang.t("$vuetify.api.fetching.method") }}
       <a
         href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET"
         target="_blank"
-        >HTTP/GET</a
       >
-    </span>
-    <br />
-    <span>Headers:</span>
-    <br />
-    <div class="code pa-4">
+        HTTP/GET
+      </a>
+    </div>
+    <div class="mt-4 ml-2">
+      {{ $vuetify.lang.t("$vuetify.api.fetching.headers") }}
+    </div>
+    <div class="code px-4 py-2">
       Accept: text/html,application/xhtml+xml,application/xml;q=0.9<br />
       Pragma: no-cache<br />
       Cache-Control: no-cache<br />
       Connection: keep-alive
     </div>
-    <span>Response:</span><br />
-    <div class="code pa-4">
+    <div class="mt-4 ml-2">
+      {{ $vuetify.lang.t("$vuetify.api.fetching.response") }}
+    </div>
+    <div class="code px-4 py-2">
       {
       <br />
       &nbsp;"id": "kxOuG8jMIgI",<br />
@@ -46,16 +54,11 @@
       }
     </div>
     <br />
-    <v-alert border="left" color="orange" text type="info">
-      <span>An invalid YouTube ID will return status code 404 "Not Found".</span
-      ><br />
-      <span
-        >An incorrectly formatted YouTube ID will return 400 "Bad
-        Request".</span
-      >
+    <v-alert border="left" color="orange" text type="info" class="mb-0">
+      <span>{{ $vuetify.lang.t("$vuetify.api.fetching.error1") }}</span>
+      <br />
+      <span>{{ $vuetify.lang.t("$vuetify.api.fetching.error2") }}</span>
     </v-alert>
-
-    <a :href="endpointUrl" target="_blank" v-text="endpointUrl" />
   </div>
 </template>
 

+ 3 - 5
Website/pages/docs/index.vue

@@ -1,8 +1,6 @@
 <template>
-  <div style="line-height: 3rem">
-    <h1>
-      Welcome to the <span class="primary--text">official RYD docs</span>!
-    </h1>
-    To get started, select a section from the menu.
+  <div style="line-height: 2rem">
+    <h2 class="primary--text">{{ $vuetify.lang.t("$vuetify.api.title") }}</h2>
+    <div class="mt-4">{{ $vuetify.lang.t("$vuetify.api.subtitle") }}</div>
   </div>
 </template>

+ 8 - 4
Website/pages/docs/url.vue

@@ -1,8 +1,12 @@
 <template>
-  <div style="line-height: 3rem">
-    <h1 class="primary--text">URL Information</h1>
-    The API is accessible over the following base URL:<br />
-    <a :href="apiUrl" target="_blank" v-text="apiUrl" />
+  <div style="line-height: 2rem">
+    <h2 class="primary--text">
+      {{ $vuetify.lang.t("$vuetify.api.url.title") }}
+    </h2>
+    <div class="mt-4">
+      {{ $vuetify.lang.t("$vuetify.api.url.subtitle") }}
+      <a :href="apiUrl" target="_blank" v-text="apiUrl" />
+    </div>
   </div>
 </template>
 

+ 13 - 23
Website/pages/docs/usage-rights.vue

@@ -1,30 +1,20 @@
 <template>
-  <div style="line-height: 3rem">
-    <h1 class="primary--text">Usage Rights</h1>
-    <p>
-      Third party use of this open API is allowed with the following
-      restrictions:
-    </p>
+  <div style="line-height: 2rem">
+    <h2 class="primary--text">
+      {{ $vuetify.lang.t("$vuetify.api.rights.title") }}
+    </h2>
+    <div class="my-4">
+      {{ $vuetify.lang.t("$vuetify.api.rights.subtitle") }}
+    </div>
     <ul>
-      <li>
-        <b>Attribution:</b> This project should be clearly attributed with
-        either a link to this repo or a link to returnyoutubedislike.com.
+      <li class="my-4">
+        <b>{{ $vuetify.lang.t("$vuetify.api.rights.bullet1") }}</b>
+        {{ $vuetify.lang.t("$vuetify.api.rights.bullet1text") }}
       </li>
-      <li>
-        <b>Rate Limiting:</b> There are per client rate limits in place of 100
-        per minute and 10'000 per day. This will return a 429 status code
-        indicating that your application should back off.
+      <li class="my-4">
+        <b>{{ $vuetify.lang.t("$vuetify.api.rights.bullet2") }}</b>
+        {{ $vuetify.lang.t("$vuetify.api.rights.bullet2text") }}
       </li>
     </ul>
   </div>
 </template>
-
-<style scoped>
-li {
-  margin-top: 0.5em;
-}
-
-b {
-  font-weight: 900 !important;
-}
-</style>

+ 4 - 2
Website/pages/donate.vue

@@ -1,8 +1,10 @@
 <template>
   <div>
-    <h1 class="title-text">Donate</h1>
+    <h1 class="title-text">
+      {{ $vuetify.lang.t("$vuetify.donate.name") }}
+    </h1>
     <p style="color: #999; margin-top: 0.5rem; margin-bottom: 1.5rem">
-      You can support our efforts to keep the internet free with a donation!
+      {{ $vuetify.lang.t("$vuetify.donate.subtitle") }}
     </p>
     <v-btn class="mainAltButton mb-2" :href="patreonLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-patreon</v-icon>

+ 9 - 51
Website/pages/faq.vue

@@ -1,19 +1,21 @@
 <template>
-  <div style="width: 90vw" class="mx-auto">
-    <h1 class="title-text">Frequently Asked Questions</h1>
+  <div class="width-constraint">
+    <h1 class="title-text">
+      {{ $vuetify.lang.t("$vuetify.faq.title") }}
+    </h1>
     <p style="color: #999; margin-top: 0.5rem; margin-bottom: 1.5rem">
-      Still have questions? Feel free to join our Discord!
+      {{ $vuetify.lang.t("$vuetify.faq.subtitle") }}
     </p>
 
-    <v-expansion-panels class="col-xs-12 col-sm-11 col-md-9 col-lg-8">
-      <v-expansion-panel v-for="(item, i) in items" :key="i">
+    <v-expansion-panels>
+      <v-expansion-panel v-for="i in [1, 2, 3, 4, 5, 6, 7]" :key="i">
         <v-expansion-panel-header>
-          {{ item.question }}
+          {{ $vuetify.lang.t(`$vuetify.faq.bullet${i}`) }}
         </v-expansion-panel-header>
         <v-expansion-panel-content class="text-left">
           <hr style="border-color: #444" />
           <br />
-          <span v-html="item.answer" />
+          <span v-html="$vuetify.lang.t(`$vuetify.faq.bullet${i}text`)" />
         </v-expansion-panel-content>
       </v-expansion-panel>
     </v-expansion-panels>
@@ -31,49 +33,5 @@ export default {
       ? "swoop-left"
       : "swoop-right";
   },
-  data: () => ({
-    items: [
-      {
-        question: "Where does the extension get its data?",
-        answer:
-          "A combination of archived data from before the official YouTube dislike API shut down, and extrapolated extension user behavior.",
-      },
-      {
-        question: "Why isn't the dislike count updating?",
-        answer:
-          "Right now video dislikes are cached and they aren't updated very frequently. It varies depending on a video's popularity but can take anywhere between a few hours and a few days to update.",
-      },
-      {
-        question: "Why is the dislike count on my videos inaccurate?",
-        answer:
-          "Extrapolated data tends to get better with the increase in diversity and the quantity of voters. \nTo ensure and increase the accuracy of the extrapolated vote data for your videos, you can encourage your viewers to use this extension (or any app that submits votes to returnyoutubedislikeapi.com) ",
-      },
-      {
-        question: "How does this work?",
-        answer:
-          "The extension collects the video ID of the video you are watching, fetches the dislike (and other fields like views, likes etc) using our API. The extension then displays the dislike count and ratio on the page. If you like or dislike a video, that is recorded and sent to the database so an accurate dislike count can be extrapolated.",
-      },
-      {
-        question: "Can I share my dislike count with you?",
-
-        answer:
-          "Coming soon. We are looking into using Oauth or a different read only API with a limited scope so creators can share their dislike counts verifiability. ",
-      },
-      {
-        question:
-          "What data do you collect and how is it treated?",
-        answer:
-          "The extension only collects data that is strictly necessary for it to function properly, such as IP address or ID of the video you're watching. None of your data will ever be sold to 3rd parties. If you would like to know more about how we handle security and privacy check out our <a href='https://github.com/Anarios/return-youtube-dislike/blob/main/Docs/SECURITY-FAQ.md'>security FAQ</a>.",
-      },
-      {
-        question: "How does the API/Backend work?",
-        answer: "The backend is using archived data from when the youtube api was still returning the dislike count, extension users like/discount count and extrapolation. In the near future we will be allowing content creators to submit their dislike count easily and safely and we will be adding ArchiveTeam's archived data (4.56 billion videos) into our current database. <a href='https://www.youtube.com/watch?v=GSmmtv-0yYQ'>You can also view a video on the topic.</a>",
-      },
-      {
-        question: "Why does the dislike count show 'DISLIKES DISABLED'?",
-        answer: "At the time of writing we aren't showing dislikes for videos that disabled their likes and dislikes count. The extension displays 'DISLIKES DISABLED' for these videos. We will be showing dislikes on all videos soon, this is just a temporary workaround so people don't think the extension is broken (which isn't working well). Sometimes a recently uploaded video might show 'DISLIKES DISABLED' even if the creator hasn't disabled it, this is due to how we are detecting if dislikes are disabled, it should go away in a few hours or by liking or disliking the video and refreshing the page (hopefully).",
-      },
-    ],
-  }),
 };
 </script>

+ 29 - 26
Website/pages/help.vue

@@ -1,23 +1,21 @@
 <template>
-  <div
-    style="width: 80vw"
-    class="col-xs-12 col-sm-11 col-md-9 col-lg-7 mx-auto"
-  >
-    <h1 class="title-text pt-12">Troubleshooting</h1>
+  <div class="width-constraint">
+    <h1 class="title-text pt-12">
+      {{ $vuetify.lang.t("$vuetify.help.title") }}
+    </h1>
     <ol style="line-height: 3rem; color: #aaa" class="text-left">
       <li>
-        Make sure you have latest version of extension installed,
+        {{ $vuetify.lang.t("$vuetify.help.bullet1") }}
         <code style="color: #eee">
-          <b>{{ version }}</b></code
-        >
-        right now
+          <b>{{ version }}</b>
+        </code>
+        {{ $vuetify.lang.t("$vuetify.help.bullet11") }}
       </li>
       <li>
-        Try removing extension and installing it again, then restarting the
-        browser (all active windows, not just one tab).
+        {{ $vuetify.lang.t("$vuetify.help.bullet2") }}
       </li>
       <li>
-        Make sure that this link opens:
+        {{ $vuetify.lang.t("$vuetify.help.bullet3") }}
         <a
           class="px-2 py-1"
           style="background: #222; border-radius: 0.25rem"
@@ -26,7 +24,8 @@
           https://returnyoutubedislikeapi.com/votes?videoId=QOFEgexls14
         </a>
         , <br />
-        you should see plain text: <br />
+        {{ $vuetify.lang.t("$vuetify.help.bullet31") }}
+        <br />
         <span style="color: #eee">
           {"id":"QOFEgexls14", "dateCreated":"2021-12-15T16:54:12.250813Z",
           "likes":2907, "dislikes":215, "rating":4.725641025641026,
@@ -34,8 +33,9 @@
         </span>
       </li>
       <li>
-        If nothing of above helps - report your problem in
-        <code>#bugs-and-problems</code> in our
+        {{ $vuetify.lang.t("$vuetify.help.bullet4") }}
+        <code>#bugs-and-problems</code>
+        {{ $vuetify.lang.t("$vuetify.help.bullet41") }}
         <v-btn
           class="mainAltButton"
           style="
@@ -53,8 +53,7 @@
         </v-btn>
         <ol type="a">
           <li>
-            Tell us your <b>Operating System</b>, <b>Browser Name</b> and
-            <b>Browser Version</b>.
+            {{ $vuetify.lang.t("$vuetify.help.bullet4a") }}
             <v-btn
               class="mainAltButton"
               style="
@@ -77,25 +76,29 @@
           </li>
 
           <li style="position: relative; width: 100%">
-            Take screenshot of page with problem (i.e. youtube video page) with
-            console open (press <code>F12</code>) - example screenshot below.
+            {{ $vuetify.lang.t("$vuetify.help.bullet4b") }}
+            <code>F12</code>
+            {{ $vuetify.lang.t("$vuetify.help.bullet4b1") }}
+
             <img
+              loading="eager"
               width="100%"
               style="border-radius: 1rem; border: 2px solid #333"
-              src="ui/troubleshooting.png"
+              src="ui/troubleshooting.webp"
               alt="example-screenshot"
             />
           </li>
 
           <li>
-            Take screenshot of extensions page of your browser with extension
-            installed. <br />
-            To see extensions put this into address bar:
+            {{ $vuetify.lang.t("$vuetify.help.bullet4c") }}
+            <br />
+            {{ $vuetify.lang.t("$vuetify.help.bullet4c1") }}
             <br />
-            <code>about:addons</code> for Firefox
+            <code>about:addons</code>
+            {{ $vuetify.lang.t("$vuetify.help.firefox") }}
             <br />
-            <code>chrome://extensions</code> for Chrome, Edge, Brave, Opera,
-            Vivaldi
+            <code>chrome://extensions</code>
+            {{ $vuetify.lang.t("$vuetify.help.chrome") }}
           </li>
         </ol>
       </li>

+ 12 - 10
Website/pages/index.vue

@@ -25,12 +25,12 @@
         />
       </svg>
 
-      <h1 class="title-text">Return YouTube Dislike</h1>
-      <div class="mb-4" style="color: #999">
-        <p style="margin-top: 0">
-          Browser extension and an API that shows you dislikes on Youtube
-        </p>
-      </div>
+      <h1 class="title-text">
+        {{ $vuetify.lang.t("$vuetify.home.title") }}
+      </h1>
+      <p class="mb-4" style="color: #999; margin-top: 0">
+        {{ $vuetify.lang.t("$vuetify.home.subtitle") }}
+      </p>
 
       <v-btn
         :to="installLink"
@@ -38,7 +38,7 @@
         style="font-size: 1.5em; padding: 1em; margin-bottom: 0.5em"
       >
         <v-icon large class="mr-6">mdi-tray-arrow-down</v-icon>
-        Install
+        {{ $vuetify.lang.t("$vuetify.install.name") }}
       </v-btn>
 
       <br />
@@ -62,15 +62,17 @@
     <v-spacer />
     <div id="support-ukraine" class="d-flex flex-column items-center py-2">
       <h3 class="mb-2">
-        <v-img src="/ukraine-flag-xs.png" width="40px"></v-img>
-        <a href="https://helpukrainewin.org/">Support Ukraine</a>
+        <v-img src="/ukraine-flag-xs.webp" width="42px" height="28px"></v-img>
+        <a href="https://helpukrainewin.org/">
+          {{ $vuetify.lang.t("$vuetify.home.ukraine") }}
+        </a>
       </h3>
     </div>
 
     <div id="biggest-supporters" class="d-flex flex-column items-center py-8">
       <h3 class="mb-4">
         <v-icon class="mb-2">mdi-heart</v-icon>
-        Sponsors
+        {{ $vuetify.lang.t("$vuetify.home.sponsors") }}
       </h3>
       <v-row class="justify-center mx-auto">
         <p v-for="sponsor in sponsors" :key="sponsor.name" class="sponsor">

+ 35 - 24
Website/pages/install.vue

@@ -1,13 +1,10 @@
 <template>
   <div>
-    <h1 class="title-text">Select Your Platform</h1>
+    <h1 class="title-text">{{ $vuetify.lang.t("$vuetify.install.title") }}</h1>
 
-    <div style="color: #999">
-      <p style="margin-bottom: 1rem">
-        Available for Firefox and all Chromium browsers
-        (Chrome/Edge/Opera/Brave).
-      </p>
-    </div>
+    <p style="color: #999; margin-bottom: 1rem">
+      {{ $vuetify.lang.t("$vuetify.install.subtitle") }}
+    </p>
 
     <v-btn class="mainAltButton mb-2" :href="firefoxLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-firefox</v-icon>
@@ -46,12 +43,13 @@
       Brave
     </v-btn>
 
-    <h3 style="margin-top: 3em; margin-bottom: 0">Other Platforms</h3>
-    <div style="color: #999">
-      <p style="margin-top: 0.5rem; margin-bottom: 0.5rem">
-        If your browser is not yet supported, try this UserScript.
-      </p>
-    </div>
+    <!-- Userscript -->
+    <h3 style="margin-top: 3em; margin-bottom: 0">
+      {{ $vuetify.lang.t("$vuetify.install.title2") }}
+    </h3>
+    <p style="color: #999; margin-top: 0.5rem; margin-bottom: 0.5rem">
+      {{ $vuetify.lang.t("$vuetify.install.subtitle2") }}
+    </p>
 
     <v-btn class="mainAltButton" :href="scriptLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-script-text-outline</v-icon>
@@ -59,23 +57,36 @@
       <div style="font-size: 0.55rem">(Tampermonkey)</div>
     </v-btn>
 
-    <h3 style="margin-top: 3em">Third Party Implementations</h3>
-    <div style="color: #999">
-      <p style="margin-top: 0.5rem; margin-bottom: 0.5rem">
-        No liability on our side, use at your own risk.
-      </p>
-    </div>
+    <!-- 3rd party clients -->
+    <h3 style="margin-top: 3em">
+      {{ $vuetify.lang.t("$vuetify.install.title3") }}
+    </h3>
+    <p style="color: #999; margin-top: 0.5rem; margin-bottom: 0.5rem">
+      {{ $vuetify.lang.t("$vuetify.install.subtitle3") }}
+    </p>
     <v-btn class="mainAltButton" :href="androidNewPipe" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-android</v-icon>
-      Android (NewPipe fork)
+      Android &nbsp; <span style="font-size: 0.55rem">(NewPipe fork)</span>
     </v-btn>
-    <v-btn class="mainAltButton" :href="androidVueTube" target="_blank">
-      <v-icon style="margin-right: 0.5em">mdi-android</v-icon>
-      Android (VueTube)
+    <v-btn
+      class="mainAltButton"
+      style="color: #999"
+      :href="androidVueTube"
+      target="_blank"
+    >
+      <v-icon class="white--text">mdi-android</v-icon>
+      <v-icon>mdi-apple</v-icon>
+      <v-icon>mdi-linux</v-icon>
+      <v-icon style="margin-right: 0.5em">mdi-microsoft-windows</v-icon>
+      <div style="font-size: 0.75rem">
+        VueTube (WIP) <br />
+        <span style="font-size: 0.55rem">pre-alpha</span>
+      </div>
+      <v-icon style="margin-left: 0.5rem">mdi-hammer-wrench</v-icon>
     </v-btn>
     <v-btn class="mainAltButton" :href="iosJailbreakLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-apple</v-icon>
-      iOS (Jailbroken)
+      iOS &nbsp; <span style="font-size: 0.55rem">(Jailbroken)</span>
     </v-btn>
   </div>
 </template>

+ 60 - 23
Website/pages/links.vue

@@ -1,12 +1,12 @@
 <template>
-  <div style="height: 100%">
-    <h1 class="title-text">Project Links</h1>
+  <div class="pt-12">
+    <h1 class="title-text">
+      {{ $vuetify.lang.t("$vuetify.links.title") }}
+    </h1>
 
-    <div style="color: #999">
-      <p style="margin-top: 0.5rem; margin-bottom: 1rem">
-        Links to the project and its developers
-      </p>
-    </div>
+    <p style="color: #9999; margin-top: 0.5rem; margin-bottom: 1rem">
+      {{ $vuetify.lang.t("$vuetify.links.subtitle") }}
+    </p>
 
     <v-btn class="mainAltButton" :href="githubLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-github</v-icon>
@@ -18,19 +18,40 @@
       Discord
     </v-btn>
 
-    <h1 style="margin-top: 1em">Contact Me</h1>
+    <h1 style="margin-top: 1em">
+      {{ $vuetify.lang.t("$vuetify.links.contact") }}
+    </h1>
 
     <v-btn class="mainAltButton" :href="emailLink" target="_blank">
       <v-icon style="margin-right: 0.5em">mdi-email</v-icon>
       selivano.d@gmail.com
     </v-btn>
 
-    <p id="credits" class="flex-row no-wrap">
-      Site by <v-icon color="#555">mdi-discord</v-icon> Front#2990
+    <p style="color: #555" class="my-8">
+      Site by <v-icon color="#555">mdi-discord</v-icon>
+      <a class="attr-link" href="https://github.com/Frontesque" target="_blank">
+        Front#2990
+      </a>
       <br />
       & <v-icon color="#555">mdi-discord</v-icon>
-      PickleNik#0864
+      <a class="attr-link" href="https://github.com/PickleNik" target="_blank">
+        PickleNik#0864
+      </a>
     </p>
+    <!-- Translators -->
+    <div style="color: #555; width: 250px">
+      <b class="white--text">
+        {{ $vuetify.lang.t("$vuetify.links.translators") }}
+      </b>
+      <br />
+      <div
+        v-for="translator in translators"
+        :key="translator.tag"
+        class="d-flex"
+      >
+        {{ translator.lang }} - <v-spacer /> {{ translator.tag }}
+      </div>
+    </div>
   </div>
 </template>
 
@@ -45,20 +66,36 @@ export default {
       ? "swoop-left"
       : "swoop-right";
   },
-  data() {
-    return {
-      githubLink: "https://github.com/Anarios/return-youtube-dislike",
-      discordLink: "https://discord.gg/mYnESY4Md5",
-
-      emailLink: "mailto:selivano.d@gmail.com ",
-    };
-  },
+  data: () => ({
+    githubLink: "https://github.com/Anarios/return-youtube-dislike",
+    discordLink: "https://discord.gg/mYnESY4Md5",
+    emailLink: "mailto:selivano.d@gmail.com ",
+    translators: [
+      {
+        tag: "alexuspromago#9473",
+        lang: "Español",
+      },
+      {
+        tag: "trbatuhankara#7738",
+        lang: "Türkçe",
+      },
+      {
+        tag: "PickleNik#0864",
+        lang: "Русский",
+      },
+    ],
+  }),
 };
 </script>
 
-<style scoped>
-#credits {
-  transform: translate(0, 100%);
-  color: #555;
+<style>
+.attr-link {
+  color: #555 !important;
+  text-decoration: none;
+  transition: all 0.2s;
+}
+.attr-link:hover {
+  text-decoration: underline;
+  color: #f77 !important;
 }
 </style>

BIN
Website/raw_assets/troubleshooting.png


+ 0 - 0
Website/static/ukraine-flag-xs.png → Website/raw_assets/ukraine-flag-xs.png


BIN
Website/static/ui/troubleshooting.webp


BIN
Website/static/ukraine-flag-xs.webp


+ 20 - 0
extension-description-store-Japanese.txt

@@ -0,0 +1,20 @@
+Return YouTube Dislike は、YouTubeの「低評価」数を表示する機能を復元する拡張機能です。
+
+動作しない場合:拡張機能タブ(chrome://extensions/)を開き、この拡張機能を無効にし、再度有効にしてください。これはChromeのバグで、拡張機能が壊れる可能性もあります。上記の手順でほとんどの問題が解決するはずです。Chromium開発チームが早急にこれを修正してくれることを期待します。
+
+2021年12月13日から、YouTubeはAPIから「低評価」数を表示する機能を削除しました。
+この拡張機能は、最も正確な評価を表示するためにアーカイブされた好き嫌いのデータ、および拡張機能のユーザーによって行われた好き嫌いの組み合わせを使用して、ユーザーの表示機能を復元することを目的としています。
+
+現在、2021年12月13日以前に保存された2億件以上の動画の高評価/低評価数のデータを保有しています。
+
+2021年12月13日以降も積極的にアップロードを行い、最新の状態を維持しています。
+
+本拡張機能をより多くのユーザーにご利用いただくことで、精度の高い評価を提供することができます。
+
+2021年12月13日以降にアップロードされたあまり人気のない動画では、人気のある動画に比べて表示されるデータの精度が低くなる可能性があります。
+
+この拡張機能は現在も鋭意開発中であるため、何か問題が発生した場合には、遠慮なくGitHubページまたはDiscordサーバーで報告してください。
+
+近日中にさらに新機能を追加する予定です!
+
+https://github.com/Anarios/return-youtube-dislike