mirror of
https://github.com/Anarios/return-youtube-dislike.git
synced 2026-10-27 23:31:06 +01:00
Prepare 4.1.0 release fixes and complete translations
This commit is contained in:
@@ -9,6 +9,10 @@ on:
|
||||
- "Extensions/common/**"
|
||||
- "Extensions/UserScript/**"
|
||||
- "Extensions/e2e/**"
|
||||
- "Website/_locales/**"
|
||||
- "Website/utils/locale*"
|
||||
- "Website/nuxt.config.js"
|
||||
- "Website/layouts/default.vue"
|
||||
- ".github/workflows/build.yaml"
|
||||
- ".babelrc"
|
||||
- ".gitattributes"
|
||||
@@ -18,6 +22,7 @@ on:
|
||||
- "jest.config.js"
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
- "scripts/check-locales*"
|
||||
- "playwright*.js"
|
||||
- "webpack*.js"
|
||||
pull_request:
|
||||
@@ -28,6 +33,10 @@ on:
|
||||
- "Extensions/common/**"
|
||||
- "Extensions/UserScript/**"
|
||||
- "Extensions/e2e/**"
|
||||
- "Website/_locales/**"
|
||||
- "Website/utils/locale*"
|
||||
- "Website/nuxt.config.js"
|
||||
- "Website/layouts/default.vue"
|
||||
- ".github/workflows/build.yaml"
|
||||
- ".babelrc"
|
||||
- ".gitattributes"
|
||||
@@ -37,6 +46,7 @@ on:
|
||||
- "jest.config.js"
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
- "scripts/check-locales*"
|
||||
- "playwright*.js"
|
||||
- "webpack*.js"
|
||||
|
||||
@@ -60,6 +70,9 @@ jobs:
|
||||
- name: Run Jest tests
|
||||
run: npm test -- --runInBand
|
||||
|
||||
- name: Check locale completeness
|
||||
run: npm run check:locales
|
||||
|
||||
- name: Build extension
|
||||
run: npm run build
|
||||
|
||||
|
||||
@@ -4,19 +4,21 @@ name: Website Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- Website/**
|
||||
- .github/workflows/weblint.yml
|
||||
- .nvmrc
|
||||
- scripts/check-locales*
|
||||
pull_request:
|
||||
branches:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- Website/**
|
||||
- .github/workflows/weblint.yml
|
||||
- .nvmrc
|
||||
- scripts/check-locales*
|
||||
|
||||
jobs:
|
||||
weblint:
|
||||
@@ -40,3 +42,6 @@ jobs:
|
||||
- name: Run lint
|
||||
run: npm run lint
|
||||
working-directory: Website
|
||||
|
||||
- name: Check website locales
|
||||
run: node scripts/check-locales.js --website
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// @name Return YouTube Dislike
|
||||
// @namespace https://www.returnyoutubedislike.com/
|
||||
// @homepage https://www.returnyoutubedislike.com/
|
||||
// @version 3.2.0
|
||||
// @version 3.2.1
|
||||
// @encoding utf-8
|
||||
// @description Return of the YouTube Dislike, Based off https://www.returnyoutubedislike.com/
|
||||
// @icon https://github.com/Anarios/return-youtube-dislike/raw/main/Icons/Return%20Youtube%20Dislike%20-%20Transparent.png
|
||||
@@ -529,8 +529,8 @@ function resolveDelegatedVoteActivation({
|
||||
|
||||
;// CONCATENATED MODULE: ./Extensions/common/color-themes.js
|
||||
const DEFAULT_CUSTOM_COLORS = Object.freeze({
|
||||
light: Object.freeze({ like: "#008000", dislike: "#b300b3" }),
|
||||
dark: Object.freeze({ like: "#00d000", dislike: "#ff66ff" }),
|
||||
light: Object.freeze({ like: "#007600", dislike: "#b300b3" }),
|
||||
dark: Object.freeze({ like: "#00d000", dislike: "#ff77ff" }),
|
||||
});
|
||||
|
||||
function normalizeCustomColors(value) {
|
||||
@@ -916,7 +916,7 @@ function createGmSyntheticDislikeStore() {
|
||||
|
||||
|
||||
;// CONCATENATED MODULE: ./Extensions/UserScript/userscript-version.json
|
||||
const userscript_version_namespaceObject = "3.2.0";
|
||||
const userscript_version_namespaceObject = "3.2.1";
|
||||
;// CONCATENATED MODULE: ./Extensions/UserScript/src/userscript-entry.js
|
||||
|
||||
|
||||
@@ -949,8 +949,8 @@ const extConfig = {
|
||||
coloredBar: false, // [true, false*] Colorize ratio bar (Use custom colors for ratio bar)
|
||||
colorTheme: "classic", // [classic*, accessible, neon, hibiscus, custom] Color theme (red/green, blue/yellow, pink/cyan, green/magenta, custom)
|
||||
customColors: {
|
||||
light: { like: "#008000", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff66ff" },
|
||||
light: { like: "#007600", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff77ff" },
|
||||
}, // Custom like/dislike colors for YouTube's light and dark themes (#rrggbb)
|
||||
numberDisplayFormat: "compactShort", // [compactShort*, compactLong, standard] Number format (For non-English locale users, you may be able to improve appearance with a different option. Please file a feature request if your locale is not covered)
|
||||
numberDisplayRoundDown: true, // [true*, false] Round down numbers (Show rounded down numbers)
|
||||
|
||||
@@ -132,15 +132,15 @@ test("retains the existing editable defaults and exposes separate custom palette
|
||||
test("recolors existing desktop thumbs and ratio when YouTube toggles an empty dark attribute", async () => {
|
||||
const { like, dislike, rateBar, rateBarFill } = mountWatch();
|
||||
userscript.__get__("refreshColorPresentation")();
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#008000");
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#007600");
|
||||
expect(dislike.style.getPropertyValue("--ryd-thumb-color")).toBe("#b300b3");
|
||||
expect(rateBarFill.style.backgroundColor).toBe("rgb(0, 128, 0)");
|
||||
expect(rateBarFill.style.backgroundColor).toBe("rgb(0, 118, 0)");
|
||||
|
||||
document.documentElement.setAttribute("dark", "");
|
||||
await flushMutations();
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#00d000");
|
||||
expect(dislike.style.getPropertyValue("--ryd-thumb-color")).toBe("#ff66ff");
|
||||
expect(rateBar.style.backgroundColor).toBe("rgb(255, 102, 255)");
|
||||
expect(dislike.style.getPropertyValue("--ryd-thumb-color")).toBe("#ff77ff");
|
||||
expect(rateBar.style.backgroundColor).toBe("rgb(255, 119, 255)");
|
||||
expect(rateBarFill.style.backgroundColor).toBe("rgb(0, 208, 0)");
|
||||
expect(rateBarFill.style.width).toBe("75%");
|
||||
expect(like.textContent).toBe("730");
|
||||
@@ -149,7 +149,7 @@ test("recolors existing desktop thumbs and ratio when YouTube toggles an empty d
|
||||
|
||||
document.documentElement.removeAttribute("dark");
|
||||
await flushMutations();
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#008000");
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#007600");
|
||||
expect(rateBar.style.backgroundColor).toBe("rgb(179, 0, 179)");
|
||||
});
|
||||
|
||||
@@ -197,7 +197,7 @@ test.each([
|
||||
])("recolors only the selected Shorts thumb and follows later selection changes (%j)", async (options) => {
|
||||
const { like, dislike } = mountShorts(options);
|
||||
userscript.__get__("refreshColorPresentation")();
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#008000");
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#007600");
|
||||
expect(dislike.hasAttribute("data-ryd-thumb-color")).toBe(false);
|
||||
|
||||
document.documentElement.setAttribute("dark", "");
|
||||
@@ -209,7 +209,7 @@ test.each([
|
||||
dislike.setAttribute("aria-pressed", "true");
|
||||
await flushMutations();
|
||||
expect(like.hasAttribute("data-ryd-thumb-color")).toBe(false);
|
||||
expect(dislike.style.getPropertyValue("--ryd-thumb-color")).toBe("#ff66ff");
|
||||
expect(dislike.style.getPropertyValue("--ryd-thumb-color")).toBe("#ff77ff");
|
||||
});
|
||||
|
||||
test.each([
|
||||
@@ -234,7 +234,7 @@ test.each([
|
||||
|
||||
expect(userscript.__get__("getLikeButton")()).toBe(likeHost);
|
||||
expect(userscript.__get__("getDislikeButton")()).toBe(dislikeHost);
|
||||
expect(nextLike.style.getPropertyValue("--ryd-thumb-color")).toBe("#008000");
|
||||
expect(nextLike.style.getPropertyValue("--ryd-thumb-color")).toBe("#007600");
|
||||
expect(nextDislike.style.getPropertyValue("--ryd-thumb-color")).toBe(options.shorts ? "" : "#b300b3");
|
||||
if (options.shorts) {
|
||||
nextLike.setAttribute("aria-pressed", "false");
|
||||
@@ -265,7 +265,7 @@ test("targets native thumbs and removes only its own overrides when coloring is
|
||||
expect(like.hasAttribute("data-ryd-thumb-color")).toBe(true);
|
||||
expect(dislike.hasAttribute("data-ryd-thumb-color")).toBe(true);
|
||||
expect(like.parentElement.hasAttribute("data-ryd-thumb-color")).toBe(false);
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#008000");
|
||||
expect(like.style.getPropertyValue("--ryd-thumb-color")).toBe("#007600");
|
||||
|
||||
extConfig.coloredThumbs = false;
|
||||
userscript.__get__("refreshColorPresentation")();
|
||||
|
||||
@@ -49,8 +49,8 @@ const extConfig = {
|
||||
coloredBar: false, // [true, false*] Colorize ratio bar (Use custom colors for ratio bar)
|
||||
colorTheme: "classic", // [classic*, accessible, neon, hibiscus, custom] Color theme (red/green, blue/yellow, pink/cyan, green/magenta, custom)
|
||||
customColors: {
|
||||
light: { like: "#008000", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff66ff" },
|
||||
light: { like: "#007600", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff77ff" },
|
||||
}, // Custom like/dislike colors for YouTube's light and dark themes (#rrggbb)
|
||||
numberDisplayFormat: "compactShort", // [compactShort*, compactLong, standard] Number format (For non-English locale users, you may be able to improve appearance with a different option. Please file a feature request if your locale is not covered)
|
||||
numberDisplayRoundDown: true, // [true*, false] Round down numbers (Show rounded down numbers)
|
||||
|
||||
@@ -1 +1 @@
|
||||
"3.2.0"
|
||||
"3.2.1"
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike loqosu"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "GitHub töhfəçiləri üçün giriş hazırda əlçatan deyil. Xidmətin yenilənməsi və ya konfiqurasiyasının dəyişdirilməsi lazımdır."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Bu GitHub hesabı Return YouTube Dislike layihəsinin töhfəçiləri siyahısında deyil. Töhfə verən hesabla daxil olun. Son töhfələrin görünməsi bir neçə saat çəkə bilər."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "GitHub girişi bu brauzerin geri çağırış ünvanı üçün konfiqurasiya edilməyib. Dəstək xidməti ilə əlaqə saxlayın."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Bu GitHub giriş cəhdinin vaxtı bitib və ya onu təsdiqləmək mümkün olmayıb. Yeni giriş cəhdi başladın."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "GitHub töhfəçisi kimi daxil olmaq üçün genişlənməni yeniləyin."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Həddindən artıq giriş cəhdi edilib. Yenidən cəhd etməzdən əvvəl bir dəqiqə gözləyin."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub icazəsi rədd edildi. Töhfəçi kimi daxil olmaq üçün icazə vermək lazımdır."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD şərhləri"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Return YouTube Dislike tərəfindən təqdim olunan icma müzakirəsi."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Bu şərhlər YouTube-dan ayrıdır."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD şərhlərini aç"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Bağla"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Ən yeni"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Ən populyar"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Şərhləri sırala"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Yenilə"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Şərhlər yüklənir…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Hələ şərh yoxdur. Söhbətə başlayın."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Hələ cavab yoxdur."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Şərh"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Şərh paylaş"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Cavab ver"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Cavab paylaş"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Ləğv et"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Saxla"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Redaktə et"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Sil"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Bu şərh silinsin?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Şərh silindi"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "redaktə edilib"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Cavablar ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Daha çox yüklə"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Bəyən"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Bəyənmə"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Reaksiya saxlanılır…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Davam etmək üçün genişlənmənin açılan pəncərəsindən daxil olun."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Şərh paylaşmaq aktiv Commenter və daha yüksək səviyyəli üzvlər üçün əlçatandır."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Commenter üzvü ol"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Hər kəs oxuya və reaksiya verə bilər. Aktiv Commenter və daha yüksək səviyyəli üzvlər şərh paylaşa bilər."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Şərh paylaşmazdan əvvəl hamıya görünən RYD ləqəbinizi seçin."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Hamıya görünən RYD ləqəbi"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 hərf, rəqəm, boşluq, nöqtə, defis və ya alt xətt. Bu ad şərhlərinizlə birlikdə görünəcək."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Ləqəbi saxla"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Bu ləqəb artıq istifadə olunur. Başqasını seçin."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "3–32 hərf, rəqəm, boşluq, nöqtə, defis və ya alt xətdən istifadə edin."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Ləqəbi dəyiş"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "$1 kimi şərh yazırsınız"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Müzakirəyə qoşulun…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Şikayət et"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Şərhdən şikayət et"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Səbəb"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Təqib və ya nifrət"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Digər"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Əlavə təfərrüatlar (istəyə bağlı)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Şikayəti göndər"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Şikayət alındı. Təşəkkür edirik."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderasiya"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Baxılacaq şikayət yoxdur."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Şərhi gizlət"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Şərhi bərpa et"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Şikayətləri rədd et"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Müəllifi blokla"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Müəllifin blokunu aç"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Moderasiya səbəbi"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Moderasiya əməliyyatı saxlanıldı."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 şikayət"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Bu video üçün RYD şərhləri əlçatan deyil."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Bu şərh artıq əlçatan deyil."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Bağlanmaq mümkün olmadı. Yenidən cəhd edin."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Yenidən cəhd etməzdən əvvəl bir az gözləyin."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Bu şərh dəyişib. Yeniləyin və yenidən cəhd edin."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Bu əməliyyat hesabınız üçün əlçatan deyil."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Yenidən cəhd et"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Bildirişlər"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Bütün yeniliklərdən xəbərdarsınız."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 şərhinizə cavab verdi"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Kimsə şərhinizi bəyəndi"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Şərhiniz $1 bəyənmə aldı"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Kimsə şərhinizi bəyənmədi"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Kimsə şərhinizə reaksiya verdi"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Kimsə"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Oxunmuş kimi işarələ"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Hamısını oxunmuş kimi işarələ"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Müzakirəyə bax"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 oxunmamış bildiriş"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Şərhlərinizə verilən cavabları və reaksiyaları görmək üçün daxil olun."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Bu müzakirə artıq əlçatan deyil."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Müzakirə"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Ləqəb"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Şikayətlər"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Şikayət statusu"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Açıq şikayətlər"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Rədd edilmiş şikayətlər"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Müəllif"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Siz"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Saxlanılır…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Təsdiqlə"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Şərhlərinizdə yeni fəaliyyət var"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Şərh zəncirini göstər"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Cavabları göstər ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Return YouTube Dislike-a xoş gəlmisiniz"
|
||||
},
|
||||
|
||||
@@ -557,6 +557,294 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Лагатып Return YouTube Dislike"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Каментарыі RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Абмеркаванне супольнасці на платформе Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Гэтыя каментарыі не звязаны з YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Адкрыць каментарыі RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Закрыць"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Найноўшыя"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Найлепшыя"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Сартаваць каментарыі"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Абнавіць"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Загрузка каментарыяў…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Каментарыяў пакуль няма. Пачніце размову."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Адказаў пакуль няма."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Каментарый"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Апублікаваць каментарый"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Адказаць"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Апублікаваць адказ"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Скасаваць"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Захаваць"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Рэдагаваць"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Выдаліць"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Выдаліць гэты каментарый?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Каментарый выдалены"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "адрэдагавана"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Адказы ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Загрузіць яшчэ"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Падабаецца"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Не падабаецца"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Захаванне рэакцыі…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Каб працягнуць, увайдзіце праз усплывальнае акно пашырэння."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Публікацыя даступна ўдзельнікам з актыўнай падпіскай узроўню Commenter або вышэй."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Стаць удзельнікам узроўню Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Усе могуць чытаць і рэагаваць. Удзельнікі з актыўнай падпіскай узроўню Commenter або вышэй могуць публікаваць каментарыі."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Перад публікацыяй выберыце публічны псеўданім RYD."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Публічны псеўданім RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 літары, лічбы, прабелы, кропкі, злучкі або знакі падкрэслівання. Гэтае імя будзе паказана побач з вашымі каментарыямі."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Захаваць псеўданім"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Гэты псеўданім ужо заняты. Выберыце іншы."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Выкарыстоўвайце 3–32 літары, лічбы, прабелы, кропкі, злучкі або знакі падкрэслівання."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Змяніць псеўданім"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Вы каментуеце як $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Далучайцеся да абмеркавання…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Паскардзіцца"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Паскардзіцца на каментарый"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Прычына"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Спам"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Пераслед або варожасць"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Іншае"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Дадатковыя звесткі (неабавязкова)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Адправіць скаргу"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Скарга атрымана. Дзякуй."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Мадэрацыя"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Няма скаргаў для разгляду."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Схаваць каментарый"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Аднавіць каментарый"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Адхіліць скаргі"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Заблакаваць аўтара"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Разблакаваць аўтара"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Прычына мадэрацыі"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Дзеянне мадэрацыі захавана."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "Скаргаў: $1"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Каментарыі RYD недаступны для гэтага відэа."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Гэты каментарый больш недаступны."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Не ўдалося падключыцца. Паспрабуйце зноў."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Пачакайце крыху перад наступнай спробай."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Гэты каментарый змяніўся. Абнавіце старонку і паспрабуйце зноў."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Гэтае дзеянне недаступна для вашага ўліковага запісу."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Паспрабаваць зноў"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Апавяшчэнні"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Усе апавяшчэнні прачытаны."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 адказвае на ваш каментарый"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Камусьці спадабаўся ваш каментарый"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Ваш каментарый атрымаў падабайкі: $1"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Камусьці не спадабаўся ваш каментарый"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Хтосьці адрэагаваў на ваш каментарый"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Хтосьці"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Пазначыць як прачытанае"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Пазначыць усё як прачытанае"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Паглядзець абмеркаванне"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "Непрачытаных апавяшчэнняў: $1"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Увайдзіце, каб бачыць адказы і рэакцыі на вашы каментарыі."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Гэтае абмеркаванне больш недаступна."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Абмеркаванне"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Псеўданім"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Скаргі"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Статус скаргі"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Адкрытыя скаргі"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Адхіленыя скаргі"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Аўтар"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Вы"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Захаванне…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Пацвердзіць"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Новая актыўнасць у вашых каментарыях"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Паказаць галіну абмеркавання"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Паказаць адказы ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Вітаем у Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Přihlášení přispěvatelů přes GitHub je momentálně nedostupné. Služba vyžaduje aktualizaci nebo změnu konfigurace."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Tento účet GitHub není uveden mezi přispěvateli projektu Return YouTube Dislike. Přihlaste se účtem, který do projektu přispěl. Nedávné příspěvky se mohou projevit až za několik hodin."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Přihlášení přes GitHub není nastaveno pro adresu zpětného volání tohoto prohlížeče. Kontaktujte podporu."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Tento pokus o přihlášení přes GitHub vypršel nebo jej nebylo možné ověřit. Začněte nové přihlášení."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Pro přihlášení přispěvatelů přes GitHub aktualizujte rozšíření."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Příliš mnoho pokusů o přihlášení. Před dalším pokusem počkejte minutu."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Autorizace na GitHubu byla zamítnuta. Přihlášení přispěvatelů vyžaduje autorizaci."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Komentáře RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Komunitní diskuze provozovaná službou Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Tyto komentáře jsou oddělené od YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Otevřít komentáře RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Zavřít"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Nejnovější"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Nejlepší"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Seřadit komentáře"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Obnovit"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Načítání komentářů…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Zatím tu nejsou žádné komentáře. Zahajte diskuzi."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Zatím žádné odpovědi."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Komentář"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Zveřejnit komentář"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Odpovědět"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Zveřejnit odpověď"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Zrušit"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Uložit"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Upravit"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Smazat"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Smazat tento komentář?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Komentář smazán"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "upraveno"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Odpovědi ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Načíst další"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "To se mi líbí"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "To se mi nelíbí"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Ukládání reakce…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Pro pokračování se přihlaste ve vyskakovacím okně rozšíření."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Komentáře mohou zveřejňovat členové s aktivním členstvím úrovně Commenter nebo vyšší."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Získat členství Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Číst a reagovat mohou všichni. Komentáře mohou zveřejňovat členové s aktivním členstvím úrovně Commenter nebo vyšší."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Před zveřejněním komentáře si zvolte veřejnou přezdívku RYD."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Veřejná přezdívka RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 písmen, číslic, mezer, teček, spojovníků nebo podtržítek. Toto jméno se zobrazí u vašich komentářů."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Uložit přezdívku"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Tato přezdívka je již obsazená. Zvolte jinou."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Použijte 3–32 písmen, číslic, mezer, teček, spojovníků nebo podtržítek."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Změnit přezdívku"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Komentujete jako $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Zapojte se do diskuze…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Nahlásit"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Nahlásit komentář"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Důvod"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Obtěžování nebo nenávist"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Jiné"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Další podrobnosti (nepovinné)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Odeslat hlášení"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Hlášení přijato. Děkujeme."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderování"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Žádná hlášení ke kontrole."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Skrýt komentář"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Obnovit komentář"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Zamítnout hlášení"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Zablokovat autora"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Odblokovat autora"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Důvod moderování"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Akce moderátora byla uložena."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "Počet hlášení: $1"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Komentáře RYD nejsou pro toto video dostupné."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Tento komentář již není dostupný."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Nelze se připojit. Zkuste to znovu."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Před dalším pokusem chvíli počkejte."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Tento komentář se změnil. Obnovte zobrazení a zkuste to znovu."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Tato akce není pro váš účet dostupná."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Zkusit znovu"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Oznámení"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Máte přečtená všechna oznámení."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 odpovídá na váš komentář"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Někomu se líbil váš komentář"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Váš komentář získal tento počet označení To se mi líbí: $1"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Někomu se nelíbil váš komentář"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Někdo reagoval na váš komentář"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Někdo"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Označit jako přečtené"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Označit vše jako přečtené"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Zobrazit diskuzi"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "Nepřečtená oznámení: $1"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Přihlaste se a zobrazte odpovědi a reakce na své komentáře."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Tato diskuze již není dostupná."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Diskuze"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Přezdívka"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Hlášení"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Stav hlášení"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Otevřená hlášení"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Zamítnutá hlášení"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Autor"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Vy"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Ukládání…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Potvrdit"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nová aktivita u vašich komentářů"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Zobrazit vlákno"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Zobrazit odpovědi ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Vítejte v Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike-Logo"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Die GitHub-Anmeldung für Mitwirkende ist derzeit nicht verfügbar. Der Dienst muss aktualisiert oder neu konfiguriert werden."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Dieses GitHub-Konto ist nicht als Mitwirkender an Return YouTube Dislike aufgeführt. Melde dich mit einem Konto an, das zum Projekt beigetragen hat. Neue Beiträge werden möglicherweise erst nach einigen Stunden berücksichtigt."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Die GitHub-Anmeldung ist für die Rückrufadresse dieses Browsers nicht konfiguriert. Bitte wende dich an den Support."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Dieser GitHub-Anmeldeversuch ist abgelaufen oder konnte nicht überprüft werden. Bitte starte eine neue Anmeldung."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Bitte aktualisiere die Erweiterung, um dich über GitHub als Mitwirkender anzumelden."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Zu viele Anmeldeversuche. Bitte warte eine Minute, bevor du es erneut versuchst."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Die GitHub-Autorisierung wurde abgelehnt. Für die Anmeldung als Mitwirkender ist eine Autorisierung erforderlich."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD-Kommentare"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Eine Community-Diskussion von Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Diese Kommentare sind unabhängig von YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD-Kommentare öffnen"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Schließen"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Neueste"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Beste"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Kommentare sortieren"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Aktualisieren"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Kommentare werden geladen…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Noch keine Kommentare. Beginne die Unterhaltung."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Noch keine Antworten."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Kommentar"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Kommentar posten"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Antworten"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Antwort posten"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Abbrechen"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Speichern"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Bearbeiten"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Löschen"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Diesen Kommentar löschen?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Kommentar gelöscht"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "bearbeitet"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Antworten ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Mehr laden"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Gefällt mir"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Gefällt mir nicht"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Reaktion wird gespeichert…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Melde dich im Popup der Erweiterung an, um fortzufahren."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Aktive Mitglieder der Stufe Commenter und höher können Kommentare posten."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Commenter werden"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Alle können lesen und reagieren. Aktive Mitglieder der Stufe Commenter und höher können Kommentare posten."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Wähle vor dem Posten deinen öffentlichen RYD-Nutzernamen."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Öffentlicher RYD-Nutzername"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 Buchstaben, Zahlen, Leerzeichen, Punkte, Bindestriche oder Unterstriche. Dieser Name wird bei deinen Kommentaren angezeigt."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Nutzernamen speichern"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Dieser Nutzername ist bereits vergeben. Wähle einen anderen."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Verwende 3–32 Buchstaben, Zahlen, Leerzeichen, Punkte, Bindestriche oder Unterstriche."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Nutzernamen ändern"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Kommentieren als $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Beteilige dich an der Diskussion…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Melden"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Kommentar melden"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Grund"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Belästigung oder Hass"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Sonstiges"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Weitere Angaben (optional)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Meldung senden"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Meldung erhalten. Vielen Dank."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderation"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Keine Meldungen zu prüfen."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Kommentar ausblenden"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Kommentar wiederherstellen"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Meldungen verwerfen"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Verfasser sperren"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Verfasser entsperren"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Grund für die Moderation"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Moderationsmaßnahme gespeichert."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 Meldungen"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "RYD-Kommentare sind für dieses Video nicht verfügbar."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Dieser Kommentar ist nicht mehr verfügbar."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Verbindung nicht möglich. Bitte versuche es erneut."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Bitte warte einen Moment, bevor du es erneut versuchst."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Dieser Kommentar wurde geändert. Aktualisiere die Ansicht und versuche es erneut."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Diese Aktion ist für dein Konto nicht verfügbar."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Erneut versuchen"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Benachrichtigungen"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Du bist auf dem neuesten Stand."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 hat auf deinen Kommentar geantwortet"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Jemandem gefällt dein Kommentar"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Dein Kommentar hat $1 Likes erhalten"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Jemandem gefällt dein Kommentar nicht"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Jemand hat auf deinen Kommentar reagiert"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Jemand"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Als gelesen markieren"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Alle als gelesen markieren"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Diskussion ansehen"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 ungelesene Benachrichtigungen"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Melde dich an, um Antworten und Reaktionen auf deine Kommentare zu sehen."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Diese Diskussion ist nicht mehr verfügbar."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Diskussion"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Nutzername"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Meldungen"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Meldungsstatus"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Offene Meldungen"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Verworfene Meldungen"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Verfasser"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Du"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Wird gespeichert…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Bestätigen"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Neue Aktivitäten zu deinen Kommentaren"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Thread anzeigen"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Antworten anzeigen ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Willkommen bei Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Λογότυπο Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Η σύνδεση συντελεστών μέσω GitHub δεν είναι διαθέσιμη αυτήν τη στιγμή. Η υπηρεσία χρειάζεται ενημέρωση ή αλλαγή ρυθμίσεων."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Αυτός ο λογαριασμός GitHub δεν περιλαμβάνεται στους συντελεστές του Return YouTube Dislike. Συνδεθείτε με λογαριασμό συντελεστή. Οι πρόσφατες συνεισφορές μπορεί να χρειαστούν λίγες ώρες για να εμφανιστούν."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Η σύνδεση μέσω GitHub δεν έχει ρυθμιστεί για τη διεύθυνση επανάκλησης αυτού του προγράμματος περιήγησης. Επικοινωνήστε με την υποστήριξη."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Αυτή η προσπάθεια σύνδεσης μέσω GitHub έληξε ή δεν ήταν δυνατό να επαληθευτεί. Ξεκινήστε νέα σύνδεση."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Ενημερώστε την επέκταση για να χρησιμοποιήσετε τη σύνδεση συντελεστών μέσω GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Πάρα πολλές προσπάθειες σύνδεσης. Περιμένετε ένα λεπτό πριν δοκιμάσετε ξανά."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Η εξουσιοδότηση GitHub απορρίφθηκε. Η σύνδεση συντελεστών απαιτεί εξουσιοδότηση."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Σχόλια RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Μια συζήτηση της κοινότητας που φιλοξενείται από το Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Αυτά τα σχόλια είναι ανεξάρτητα από το YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Άνοιγμα σχολίων RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Κλείσιμο"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Νεότερα"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Κορυφαία"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Ταξινόμηση σχολίων"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Ανανέωση"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Φόρτωση σχολίων…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Δεν υπάρχουν ακόμη σχόλια. Ξεκινήστε τη συζήτηση."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Δεν υπάρχουν ακόμη απαντήσεις."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Σχόλιο"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Δημοσίευση σχολίου"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Απάντηση"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Δημοσίευση απάντησης"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Ακύρωση"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Αποθήκευση"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Επεξεργασία"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Διαγραφή"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Να διαγραφεί αυτό το σχόλιο;"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Το σχόλιο διαγράφηκε"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "τροποποιήθηκε"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Απαντήσεις ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Φόρτωση περισσότερων"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Μου αρέσει"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Δεν μου αρέσει"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Αποθήκευση αντίδρασης…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Συνδεθείτε από το αναδυόμενο παράθυρο της επέκτασης για να συνεχίσετε."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Η δημοσίευση είναι διαθέσιμη σε ενεργά μέλη της βαθμίδας Commenter και άνω."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Γίνετε μέλος Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Όλοι μπορούν να διαβάζουν και να αντιδρούν. Τα ενεργά μέλη της βαθμίδας Commenter και άνω μπορούν να δημοσιεύουν."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Επιλέξτε το δημόσιο ψευδώνυμό σας στο RYD πριν δημοσιεύσετε."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Δημόσιο ψευδώνυμο RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 γράμματα, αριθμοί, κενά, τελείες, παύλες ή κάτω παύλες. Αυτό το όνομα θα εμφανίζεται μαζί με τα σχόλιά σας."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Αποθήκευση ψευδωνύμου"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Αυτό το ψευδώνυμο χρησιμοποιείται ήδη. Επιλέξτε άλλο."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Χρησιμοποιήστε 3–32 γράμματα, αριθμούς, κενά, τελείες, παύλες ή κάτω παύλες."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Αλλαγή ψευδωνύμου"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Σχολιάζετε ως $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Συμμετέχετε στη συζήτηση…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Αναφορά"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Αναφορά σχολίου"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Αιτία"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Ανεπιθύμητο περιεχόμενο"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Παρενόχληση ή μίσος"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Άλλο"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Πρόσθετες λεπτομέρειες (προαιρετικά)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Αποστολή αναφοράς"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Η αναφορά παραλήφθηκε. Ευχαριστούμε."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Συντονισμός"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Δεν υπάρχουν αναφορές για έλεγχο."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Απόκρυψη σχολίου"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Επαναφορά σχολίου"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Απόρριψη αναφορών"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Αποκλεισμός συντάκτη"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Άρση αποκλεισμού συντάκτη"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Αιτία ενέργειας συντονισμού"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Η ενέργεια συντονισμού αποθηκεύτηκε."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 αναφορές"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Τα σχόλια RYD δεν είναι διαθέσιμα για αυτό το βίντεο."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Αυτό το σχόλιο δεν είναι πλέον διαθέσιμο."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Δεν ήταν δυνατή η σύνδεση. Δοκιμάστε ξανά."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Περιμένετε λίγο πριν δοκιμάσετε ξανά."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Αυτό το σχόλιο άλλαξε. Ανανεώστε και δοκιμάστε ξανά."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Αυτή η ενέργεια δεν είναι διαθέσιμη για τον λογαριασμό σας."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Δοκιμάστε ξανά"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Ειδοποιήσεις"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Έχετε δει όλες τις ενημερώσεις."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 απάντησε στο σχόλιό σας"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Σε κάποιον άρεσε το σχόλιό σας"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Το σχόλιό σας έλαβε $1 likes"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Σε κάποιον δεν άρεσε το σχόλιό σας"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Κάποιος αντέδρασε στο σχόλιό σας"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Κάποιος"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Επισήμανση ως αναγνωσμένη"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Επισήμανση όλων ως αναγνωσμένων"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Προβολή συζήτησης"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 μη αναγνωσμένες ειδοποιήσεις"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Συνδεθείτε για να δείτε απαντήσεις και αντιδράσεις στα σχόλιά σας."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Αυτή η συζήτηση δεν είναι πλέον διαθέσιμη."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Συζήτηση"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Ψευδώνυμο"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Αναφορές"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Κατάσταση αναφοράς"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Ανοιχτές αναφορές"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Αναφορές που απορρίφθηκαν"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Συντάκτης"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Εσείς"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Αποθήκευση…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Επιβεβαίωση"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Νέα δραστηριότητα στα σχόλιά σας"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Εμφάνιση νήματος"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Εμφάνιση απαντήσεων ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Καλώς ήρθατε στο Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logotipo de Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "El inicio de sesión de colaboradores con GitHub no está disponible en este momento. El servicio necesita una actualización o un cambio de configuración."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Esta cuenta de GitHub no figura como colaboradora de Return YouTube Dislike. Inicia sesión con una cuenta que haya contribuido al proyecto. Las contribuciones recientes pueden tardar unas horas en aparecer."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "El inicio de sesión con GitHub no está configurado para la dirección de retorno de este navegador. Contacta con el servicio de asistencia."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Este intento de inicio de sesión con GitHub ha caducado o no se ha podido verificar. Inicia sesión de nuevo."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Actualiza la extensión para iniciar sesión como colaborador con GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Demasiados intentos de inicio de sesión. Espera un minuto antes de volver a intentarlo."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Se ha rechazado la autorización de GitHub. Para iniciar sesión como colaborador es necesario autorizar el acceso."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Comentarios de RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Una conversación de la comunidad alojada en Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Estos comentarios son independientes de YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Abrir los comentarios de RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Cerrar"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Más recientes"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Destacados"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Ordenar comentarios"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Actualizar"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Cargando comentarios…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Aún no hay comentarios. Inicia la conversación."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Aún no hay respuestas."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Comentario"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Publicar comentario"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Responder"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Publicar respuesta"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Cancelar"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Guardar"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Editar"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Eliminar"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "¿Eliminar este comentario?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Comentario eliminado"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "editado"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Respuestas ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Cargar más"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Me gusta"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "No me gusta"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Guardando reacción…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Inicia sesión desde la ventana emergente de la extensión para continuar."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Los miembros activos del nivel Commenter o superior pueden publicar."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Únete al nivel Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Todo el mundo puede leer y reaccionar. Los miembros activos del nivel Commenter o superior pueden publicar."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Elige tu apodo público de RYD antes de publicar."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Apodo público de RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "Entre 3 y 32 letras, números, espacios, puntos, guiones o guiones bajos. Este nombre aparecerá junto a tus comentarios."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Guardar apodo"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Este apodo ya está en uso. Elige otro."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Usa entre 3 y 32 letras, números, espacios, puntos, guiones o guiones bajos."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Cambiar apodo"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Comentando como $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Participa en la conversación…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Denunciar"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Denunciar comentario"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Motivo"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Acoso u odio"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Otro"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Detalles adicionales (opcional)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Enviar denuncia"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Denuncia recibida. Gracias."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderación"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "No hay denuncias que revisar."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Ocultar comentario"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Restaurar comentario"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Descartar denuncias"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Bloquear al autor"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Desbloquear al autor"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Motivo de moderación"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Acción de moderación guardada."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 denuncias"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Los comentarios de RYD no están disponibles para este vídeo."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Este comentario ya no está disponible."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "No se ha podido conectar. Inténtalo de nuevo."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Espera un momento antes de volver a intentarlo."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Este comentario ha cambiado. Actualiza y vuelve a intentarlo."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Esta acción no está disponible para tu cuenta."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Volver a intentar"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Notificaciones"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Estás al día."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 ha respondido a tu comentario"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "A alguien le ha gustado tu comentario"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Tu comentario ha recibido $1 me gusta"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "A alguien no le ha gustado tu comentario"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Alguien ha reaccionado a tu comentario"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Alguien"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Marcar como leído"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Marcar todo como leído"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Ver conversación"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 notificaciones sin leer"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Inicia sesión para ver las respuestas y reacciones a tus comentarios."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Esta conversación ya no está disponible."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Conversación"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Apodo"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Denuncias"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Estado de la denuncia"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Denuncias pendientes"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Denuncias descartadas"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Autor"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Tú"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Guardando…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Confirmar"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nueva actividad en tus comentarios"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Mostrar hilo"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Mostrar respuestas ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Bienvenido a Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -557,6 +557,294 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo de Return YouTube Dislike"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Commentaires RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Une discussion communautaire hébergée par Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Ces commentaires sont indépendants de YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Ouvrir les commentaires RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Fermer"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Les plus récents"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Les mieux notés"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Trier les commentaires"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Actualiser"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Chargement des commentaires…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Aucun commentaire pour le moment. Lancez la conversation."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Aucune réponse pour le moment."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Commentaire"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Publier le commentaire"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Répondre"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Publier la réponse"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Annuler"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Enregistrer"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Modifier"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Supprimer"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Supprimer ce commentaire ?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Commentaire supprimé"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "modifié"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Réponses ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Charger davantage"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "J’aime"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Je n’aime pas"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Enregistrement de la réaction…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Connectez-vous depuis la fenêtre de l’extension pour continuer."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Les membres actifs du niveau Commenter ou supérieur peuvent publier."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Devenir membre Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Tout le monde peut lire et réagir. Les membres actifs du niveau Commenter ou supérieur peuvent publier."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Choisissez votre pseudonyme public RYD avant de publier."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Pseudonyme public RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3 à 32 lettres, chiffres, espaces, points, tirets ou tirets bas. Ce nom apparaîtra avec vos commentaires."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Enregistrer le pseudonyme"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Ce pseudonyme est déjà utilisé. Choisissez-en un autre."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Utilisez 3 à 32 lettres, chiffres, espaces, points, tirets ou tirets bas."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Changer de pseudonyme"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Vous commentez en tant que $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Participez à la discussion…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Signaler"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Signaler le commentaire"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Motif"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Harcèlement ou haine"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Autre"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Précisions supplémentaires (facultatif)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Envoyer le signalement"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Signalement reçu. Merci."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Modération"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Aucun signalement à examiner."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Masquer le commentaire"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Restaurer le commentaire"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Rejeter les signalements"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Bannir l’auteur"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Débannir l’auteur"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Motif de modération"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Action de modération enregistrée."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 signalements"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Les commentaires RYD ne sont pas disponibles pour cette vidéo."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Ce commentaire n’est plus disponible."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Connexion impossible. Veuillez réessayer."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Veuillez patienter un instant avant de réessayer."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Ce commentaire a été modifié. Actualisez et réessayez."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Cette action n’est pas disponible pour votre compte."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Réessayer"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Notifications"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Vous êtes à jour."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 a répondu à votre commentaire"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Quelqu’un a aimé votre commentaire"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Votre commentaire a reçu $1 mentions J’aime"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Quelqu’un n’a pas aimé votre commentaire"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Quelqu’un a réagi à votre commentaire"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Quelqu’un"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Marquer comme lu"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Tout marquer comme lu"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Voir la discussion"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 notifications non lues"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Connectez-vous pour voir les réponses et les réactions à vos commentaires."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Cette discussion n’est plus disponible."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Discussion"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Pseudonyme"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Signalements"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Statut du signalement"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Signalements en attente"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Signalements rejetés"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Auteur"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Vous"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Enregistrement…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Confirmer"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nouvelle activité sur vos commentaires"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Afficher le fil"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Afficher les réponses ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Bienvenue sur Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike logója"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "A közreműködők GitHub-bejelentkezése jelenleg nem érhető el. A szolgáltatás frissítést vagy konfigurációmódosítást igényel."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Ez a GitHub-fiók nem szerepel a Return YouTube Dislike közreműködői között. Jelentkezz be egy közreműködői fiókkal. A friss hozzájárulások megjelenése néhány órát is igénybe vehet."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "A GitHub-bejelentkezés nincs beállítva ennek a böngészőnek a visszahívási címéhez. Fordulj az ügyfélszolgálathoz."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Ez a GitHub-bejelentkezési kísérlet lejárt, vagy nem sikerült ellenőrizni. Indíts új bejelentkezést."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "A közreműködők GitHub-bejelentkezéséhez frissítsd a bővítményt."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Túl sok bejelentkezési kísérlet. Várj egy percet, majd próbáld újra."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "A GitHub-engedélyezés elutasítva. A közreműködői bejelentkezéshez engedélyezés szükséges."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD-hozzászólások"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "A Return YouTube Dislike által biztosított közösségi beszélgetés."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Ezek a hozzászólások függetlenek a YouTube-tól."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD-hozzászólások megnyitása"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Bezárás"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Legújabbak"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Legnépszerűbbek"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Hozzászólások rendezése"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Frissítés"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Hozzászólások betöltése…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Még nincsenek hozzászólások. Indítsd el a beszélgetést."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Még nincsenek válaszok."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Hozzászólás"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Hozzászólás küldése"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Válasz"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Válasz küldése"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Mégse"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Mentés"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Szerkesztés"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Törlés"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Törlöd ezt a hozzászólást?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Hozzászólás törölve"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "szerkesztve"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Válaszok ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Továbbiak betöltése"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Tetszik"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Nem tetszik"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Reakció mentése…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "A folytatáshoz jelentkezz be a bővítmény felugró ablakában."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Az aktív Commenter és magasabb szintű tagok szólhatnak hozzá."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Legyél Commenter tag"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Mindenki olvashat és reagálhat. Az aktív Commenter és magasabb szintű tagok szólhatnak hozzá."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Hozzászólás előtt válaszd ki nyilvános RYD-becenevedet."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Nyilvános RYD-becenév"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 betű, szám, szóköz, pont, kötőjel vagy aláhúzás. Ez a név jelenik meg a hozzászólásaid mellett."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Becenév mentése"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Ez a becenév már foglalt. Válassz másikat."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Használj 3–32 betűt, számot, szóközt, pontot, kötőjelet vagy aláhúzást."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Becenév módosítása"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Hozzászólás $1 néven"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Szólj hozzá a beszélgetéshez…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Jelentés"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Hozzászólás jelentése"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Indok"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Zaklatás vagy gyűlöletkeltés"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Egyéb"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "További részletek (nem kötelező)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Jelentés küldése"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "A jelentést megkaptuk. Köszönjük."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderálás"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Nincsenek ellenőrzésre váró jelentések."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Hozzászólás elrejtése"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Hozzászólás visszaállítása"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Jelentések elutasítása"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Szerző kitiltása"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Szerző kitiltásának feloldása"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Moderálás indoka"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Moderálási művelet mentve."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 jelentés"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Ehhez a videóhoz nem érhetők el RYD-hozzászólások."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Ez a hozzászólás már nem érhető el."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Nem sikerült csatlakozni. Próbáld újra."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Várj egy kicsit, majd próbáld újra."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Ez a hozzászólás megváltozott. Frissíts, és próbáld újra."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Ez a művelet nem érhető el a fiókoddal."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Újrapróbálás"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Értesítések"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Nincsenek új értesítéseid."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 válaszolt a hozzászólásodra"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Valakinek tetszett a hozzászólásod"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "A hozzászólásod $1 kedvelést kapott"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Valakinek nem tetszett a hozzászólásod"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Valaki reagált a hozzászólásodra"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Valaki"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Megjelölés olvasottként"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Összes megjelölése olvasottként"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Beszélgetés megtekintése"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 olvasatlan értesítés"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Jelentkezz be a hozzászólásaidra érkező válaszok és reakciók megtekintéséhez."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Ez a beszélgetés már nem érhető el."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Beszélgetés"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Becenév"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Jelentések"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Jelentés állapota"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Nyitott jelentések"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Elutasított jelentések"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Szerző"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Te"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Mentés…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Megerősítés"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Új aktivitás a hozzászólásaidnál"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Hozzászóláslánc megjelenítése"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Válaszok megjelenítése ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Üdvözöljük a Return YouTube Dislike-ban"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Login kontributor GitHub saat ini tidak tersedia. Layanan memerlukan pembaruan atau perubahan konfigurasi."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Akun GitHub ini tidak terdaftar sebagai kontributor Return YouTube Dislike. Login dengan akun yang telah berkontribusi. Kontribusi terbaru mungkin memerlukan beberapa jam untuk muncul."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Login GitHub belum dikonfigurasi untuk alamat callback browser ini. Hubungi dukungan."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Upaya login GitHub ini telah kedaluwarsa atau tidak dapat diverifikasi. Mulai login baru."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Perbarui ekstensi untuk menggunakan login kontributor GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Terlalu banyak upaya login. Tunggu satu menit sebelum mencoba lagi."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Otorisasi GitHub ditolak. Login kontributor memerlukan otorisasi."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Komentar RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Diskusi komunitas yang diselenggarakan oleh Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Komentar ini terpisah dari YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Buka komentar RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Tutup"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Terbaru"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Teratas"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Urutkan komentar"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Muat ulang"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Memuat komentar…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Belum ada komentar. Mulai percakapan."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Belum ada balasan."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Komentar"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Kirim komentar"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Balas"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Kirim balasan"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Batal"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Simpan"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Edit"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Hapus"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Hapus komentar ini?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Komentar dihapus"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "diedit"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Balasan ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Muat lebih banyak"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Suka"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Tidak suka"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Menyimpan reaksi…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Login melalui popup ekstensi untuk melanjutkan."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Anggota aktif tingkat Commenter ke atas dapat mengirim komentar."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Jadi anggota Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Semua orang dapat membaca dan memberi reaksi. Anggota aktif tingkat Commenter ke atas dapat mengirim komentar."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Pilih nama panggilan RYD publik Anda sebelum mengirim komentar."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Nama panggilan RYD publik"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 karakter berupa huruf, angka, spasi, titik, tanda hubung, atau garis bawah. Nama ini akan ditampilkan bersama komentar Anda."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Simpan nama panggilan"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Nama panggilan ini sudah digunakan. Pilih yang lain."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Gunakan 3–32 karakter berupa huruf, angka, spasi, titik, tanda hubung, atau garis bawah."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Ubah nama panggilan"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Berkomentar sebagai $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Ikut berdiskusi…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Laporkan"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Laporkan komentar"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Alasan"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Pelecehan atau kebencian"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Lainnya"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Detail tambahan (opsional)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Kirim laporan"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Laporan diterima. Terima kasih."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderasi"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Tidak ada laporan untuk ditinjau."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Sembunyikan komentar"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Pulihkan komentar"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Abaikan laporan"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Blokir penulis"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Buka blokir penulis"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Alasan moderasi"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Tindakan moderasi disimpan."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 laporan"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Komentar RYD tidak tersedia untuk video ini."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Komentar ini tidak lagi tersedia."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Tidak dapat terhubung. Coba lagi."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Tunggu sebentar sebelum mencoba lagi."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Komentar ini telah berubah. Muat ulang dan coba lagi."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Tindakan ini tidak tersedia untuk akun Anda."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Coba lagi"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Notifikasi"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Semua notifikasi sudah dibaca."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 membalas komentar Anda"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Seseorang menyukai komentar Anda"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Komentar Anda mendapat $1 suka"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Seseorang tidak menyukai komentar Anda"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Seseorang memberi reaksi pada komentar Anda"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Seseorang"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Tandai sudah dibaca"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Tandai semua sudah dibaca"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Lihat diskusi"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 notifikasi belum dibaca"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Login untuk melihat balasan dan reaksi pada komentar Anda."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Diskusi ini tidak lagi tersedia."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Diskusi"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Nama panggilan"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Laporan"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Status laporan"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Laporan terbuka"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Laporan yang diabaikan"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Penulis"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Anda"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Menyimpan…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Konfirmasi"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Aktivitas baru pada komentar Anda"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Tampilkan rangkaian komentar"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Tampilkan balasan ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Selamat datang di Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "L’accesso dei collaboratori tramite GitHub non è al momento disponibile. Il servizio richiede un aggiornamento o una modifica della configurazione."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Questo account GitHub non risulta tra i collaboratori di Return YouTube Dislike. Accedi con un account che abbia contribuito al progetto. I contributi recenti potrebbero richiedere alcune ore per essere visualizzati."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "L’accesso tramite GitHub non è configurato per l’indirizzo di callback di questo browser. Contatta l’assistenza."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Questo tentativo di accesso tramite GitHub è scaduto o non è stato possibile verificarlo. Avvia un nuovo accesso."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Aggiorna l’estensione per accedere come collaboratore tramite GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Troppi tentativi di accesso. Attendi un minuto prima di riprovare."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "L’autorizzazione GitHub è stata rifiutata. Per accedere come collaboratore è necessaria l’autorizzazione."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Commenti RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Una discussione della community ospitata da Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Questi commenti sono indipendenti da YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Apri i commenti RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Chiudi"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Più recenti"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Più apprezzati"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Ordina i commenti"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Aggiorna"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Caricamento dei commenti…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Ancora nessun commento. Avvia la conversazione."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Ancora nessuna risposta."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Commento"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Pubblica commento"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Rispondi"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Pubblica risposta"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Annulla"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Salva"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Modifica"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Elimina"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Eliminare questo commento?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Commento eliminato"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "modificato"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Risposte ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Carica altri"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Mi piace"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Non mi piace"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Salvataggio della reazione…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Accedi dal popup dell’estensione per continuare."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "I membri attivi del livello Commenter o superiore possono pubblicare."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Diventa membro Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Tutti possono leggere e reagire. I membri attivi del livello Commenter o superiore possono pubblicare."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Scegli il tuo nickname pubblico RYD prima di pubblicare."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Nickname pubblico RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "Da 3 a 32 lettere, numeri, spazi, punti, trattini o trattini bassi. Questo nome apparirà accanto ai tuoi commenti."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Salva nickname"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Questo nickname è già in uso. Scegline un altro."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Usa da 3 a 32 lettere, numeri, spazi, punti, trattini o trattini bassi."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Cambia nickname"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Commenti come $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Partecipa alla discussione…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Segnala"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Segnala commento"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Motivo"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Molestie o odio"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Altro"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Ulteriori dettagli (facoltativo)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Invia segnalazione"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Segnalazione ricevuta. Grazie."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderazione"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Nessuna segnalazione da esaminare."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Nascondi commento"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Ripristina commento"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Respingi segnalazioni"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Blocca autore"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Sblocca autore"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Motivo della moderazione"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Azione di moderazione salvata."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 segnalazioni"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "I commenti RYD non sono disponibili per questo video."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Questo commento non è più disponibile."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Impossibile connettersi. Riprova."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Attendi un momento prima di riprovare."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Questo commento è stato modificato. Aggiorna e riprova."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Questa azione non è disponibile per il tuo account."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Riprova"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Notifiche"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Non ci sono novità."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 ha risposto al tuo commento"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "A qualcuno piace il tuo commento"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Il tuo commento ha ricevuto $1 Mi piace"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "A qualcuno non piace il tuo commento"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Qualcuno ha reagito al tuo commento"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Qualcuno"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Segna come letto"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Segna tutto come letto"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Visualizza discussione"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 notifiche non lette"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Accedi per vedere le risposte e le reazioni ai tuoi commenti."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Questa discussione non è più disponibile."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Discussione"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Nickname"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Segnalazioni"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Stato della segnalazione"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Segnalazioni aperte"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Segnalazioni respinte"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Autore"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Tu"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Salvataggio…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Conferma"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nuove attività sui tuoi commenti"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Mostra discussione"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Mostra risposte ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Benvenuto in Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike のロゴ"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "GitHub 貢献者向けログインは現在利用できません。サービスの更新または設定変更が必要です。"
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "この GitHub アカウントは Return YouTube Dislike の貢献者として登録されていません。貢献したアカウントでログインしてください。最近の貢献が反映されるまで数時間かかる場合があります。"
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "このブラウザのコールバックアドレス用に GitHub ログインが設定されていません。サポートにお問い合わせください。"
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "この GitHub ログインの試行は期限切れか、確認できませんでした。もう一度ログインを開始してください。"
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "GitHub 貢献者向けログインを使用するには、拡張機能を更新してください。"
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "ログインの試行回数が多すぎます。1 分待ってからもう一度お試しください。"
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub のアクセス許可が拒否されました。貢献者としてログインするにはアクセス許可が必要です。"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD コメント"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Return YouTube Dislike が提供するコミュニティディスカッションです。"
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "これらのコメントは YouTube とは別のものです。"
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD コメントを開く"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "閉じる"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "新しい順"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "人気順"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "コメントを並べ替え"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "更新"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "コメントを読み込み中…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "まだコメントはありません。会話を始めましょう。"
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "まだ返信はありません。"
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "コメント"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "コメントを投稿"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "返信"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "返信を投稿"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "キャンセル"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "保存"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "編集"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "削除"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "このコメントを削除しますか?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "コメントは削除されました"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "編集済み"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "返信($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "さらに読み込む"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "高評価"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "低評価"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "リアクションを保存中…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "続行するには、拡張機能のポップアップからログインしてください。"
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "投稿は有効な Commenter 以上のメンバーが利用できます。"
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Commenter になる"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "誰でも閲覧とリアクションができます。有効な Commenter 以上のメンバーは投稿できます。"
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "投稿する前に、公開する RYD ニックネームを選んでください。"
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "公開 RYD ニックネーム"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "文字、数字、スペース、ピリオド、ハイフン、アンダースコアを使用して 3~32 文字で入力してください。この名前はコメントとともに表示されます。"
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "ニックネームを保存"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "このニックネームはすでに使われています。別の名前を選んでください。"
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "文字、数字、スペース、ピリオド、ハイフン、アンダースコアを使用して 3~32 文字で入力してください。"
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "ニックネームを変更"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "$1 としてコメント"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "ディスカッションに参加…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "報告"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "コメントを報告"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "理由"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "スパム"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "嫌がらせやヘイト"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "その他"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "詳細(任意)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "報告を送信"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "報告を受け付けました。ありがとうございます。"
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "モデレーション"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "確認する報告はありません。"
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "コメントを非表示"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "コメントを再表示"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "報告を却下"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "投稿者を利用禁止"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "投稿者の利用禁止を解除"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "モデレーションの理由"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "モデレーション操作を保存しました。"
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 件の報告"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "この動画では RYD コメントを利用できません。"
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "このコメントは利用できなくなりました。"
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "接続できません。もう一度お試しください。"
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "しばらく待ってからもう一度お試しください。"
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "このコメントは変更されています。更新してもう一度お試しください。"
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "お使いのアカウントではこの操作を利用できません。"
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "再試行"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "通知"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "未読の通知はありません。"
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 があなたのコメントに返信しました"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "誰かがあなたのコメントを高く評価しました"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "あなたのコメントが $1 件の高評価を受けました"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "誰かがあなたのコメントを低く評価しました"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "誰かがあなたのコメントにリアクションしました"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "誰か"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "既読にする"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "すべて既読にする"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "ディスカッションを表示"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 件の未読通知"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "コメントへの返信やリアクションを確認するにはログインしてください。"
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "このディスカッションは利用できなくなりました。"
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "ディスカッション"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "ニックネーム"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "報告"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "報告の状態"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "未対応の報告"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "却下した報告"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "投稿者"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "あなた"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "保存中…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "確認"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "あなたのコメントに新しいアクティビティがあります"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "スレッドを表示"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "返信を表示($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Return YouTube Dislike へようこそ"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike 로고"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "현재 GitHub 기여자 로그인을 사용할 수 없습니다. 서비스 업데이트 또는 설정 변경이 필요합니다."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "이 GitHub 계정은 Return YouTube Dislike 기여자로 등록되어 있지 않습니다. 기여한 계정으로 로그인해 주세요. 최근 기여 내역이 반영되기까지 몇 시간이 걸릴 수 있습니다."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "이 브라우저의 콜백 주소에 대한 GitHub 로그인이 설정되어 있지 않습니다. 지원팀에 문의해 주세요."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "이 GitHub 로그인 시도가 만료되었거나 확인할 수 없습니다. 로그인을 다시 시작해 주세요."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "GitHub 기여자 로그인을 사용하려면 확장 프로그램을 업데이트해 주세요."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "로그인 시도 횟수가 너무 많습니다. 1분 후에 다시 시도해 주세요."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub 권한 승인이 거부되었습니다. 기여자로 로그인하려면 권한 승인이 필요합니다."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD 댓글"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Return YouTube Dislike에서 제공하는 커뮤니티 토론입니다."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "이 댓글은 YouTube와 별개입니다."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD 댓글 열기"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "닫기"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "최신순"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "인기순"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "댓글 정렬"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "새로고침"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "댓글 불러오는 중…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "아직 댓글이 없습니다. 대화를 시작해 보세요."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "아직 답글이 없습니다."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "댓글"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "댓글 게시"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "답글"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "답글 게시"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "취소"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "저장"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "수정"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "삭제"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "이 댓글을 삭제할까요?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "삭제된 댓글"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "수정됨"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "답글 ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "더 불러오기"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "좋아요"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "싫어요"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "반응 저장 중…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "계속하려면 확장 프로그램 팝업에서 로그인해 주세요."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Commenter 이상 등급의 활성 회원은 댓글을 게시할 수 있습니다."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Commenter 가입하기"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "누구나 읽고 반응을 남길 수 있습니다. Commenter 이상 등급의 활성 회원은 댓글을 게시할 수 있습니다."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "게시하기 전에 공개 RYD 닉네임을 정해 주세요."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "공개 RYD 닉네임"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "문자, 숫자, 공백, 마침표, 하이픈 또는 밑줄을 사용하여 3~32자로 입력하세요. 이 이름은 댓글과 함께 표시됩니다."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "닉네임 저장"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "이미 사용 중인 닉네임입니다. 다른 닉네임을 선택해 주세요."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "문자, 숫자, 공백, 마침표, 하이픈 또는 밑줄을 사용하여 3~32자로 입력하세요."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "닉네임 변경"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "$1 이름으로 댓글 작성"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "토론에 참여해 보세요…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "신고"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "댓글 신고"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "사유"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "스팸"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "괴롭힘 또는 혐오"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "기타"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "추가 정보 (선택 사항)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "신고 제출"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "신고가 접수되었습니다. 감사합니다."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "관리"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "검토할 신고가 없습니다."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "댓글 숨기기"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "댓글 복원"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "신고 기각"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "작성자 이용 정지"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "작성자 이용 정지 해제"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "관리 조치 사유"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "관리 조치가 저장되었습니다."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "신고 $1건"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "이 동영상에서는 RYD 댓글을 사용할 수 없습니다."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "더 이상 볼 수 없는 댓글입니다."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "연결할 수 없습니다. 다시 시도해 주세요."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "잠시 후에 다시 시도해 주세요."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "이 댓글이 변경되었습니다. 새로고침 후 다시 시도해 주세요."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "이 계정으로는 이 작업을 수행할 수 없습니다."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "다시 시도"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "알림"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "모든 알림을 확인했습니다."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "내 댓글에 $1의 답글이 달렸습니다"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "누군가 내 댓글에 좋아요를 눌렀습니다"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "내 댓글이 좋아요 $1개를 받았습니다"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "누군가 내 댓글에 싫어요를 눌렀습니다"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "누군가 내 댓글에 반응을 남겼습니다"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "누군가"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "읽음으로 표시"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "모두 읽음으로 표시"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "토론 보기"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "읽지 않은 알림 $1개"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "내 댓글에 달린 답글과 반응을 보려면 로그인해 주세요."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "더 이상 볼 수 없는 토론입니다."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "토론"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "닉네임"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "신고"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "신고 상태"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "미처리 신고"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "기각된 신고"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "작성자"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "나"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "저장 중…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "확인"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "내 댓글에 새로운 활동이 있습니다"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "댓글 대화 보기"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "답글 보기 ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Return YouTube Dislike에 오신 것을 환영합니다"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike-logo"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Inloggen via GitHub voor bijdragers is momenteel niet beschikbaar. De dienst heeft een update of een configuratiewijziging nodig."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Dit GitHub-account staat niet vermeld als bijdrager aan Return YouTube Dislike. Log in met een account dat aan het project heeft bijgedragen. Het kan enkele uren duren voordat recente bijdragen worden weergegeven."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Inloggen via GitHub is niet geconfigureerd voor het terugkeeradres van deze browser. Neem contact op met de ondersteuning."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Deze inlogpoging via GitHub is verlopen of kon niet worden geverifieerd. Start een nieuwe inlogpoging."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Werk de extensie bij om via GitHub als bijdrager in te loggen."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Te veel inlogpogingen. Wacht een minuut voordat je het opnieuw probeert."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "De GitHub-autorisatie is geweigerd. Autorisatie is vereist om als bijdrager in te loggen."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD-reacties"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Een discussie voor de community, gehost door Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Deze reacties staan los van YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD-reacties openen"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Sluiten"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Nieuwste"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Beste"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Reacties sorteren"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Vernieuwen"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Reacties laden…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Nog geen reacties. Begin het gesprek."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Nog geen antwoorden."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Reactie"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Reactie plaatsen"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Beantwoorden"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Antwoord plaatsen"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Annuleren"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Opslaan"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Bewerken"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Verwijderen"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Deze reactie verwijderen?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Reactie verwijderd"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "bewerkt"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Antwoorden ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Meer laden"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Vind ik leuk"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Vind ik niet leuk"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Waardering opslaan…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Log in via het pop-upvenster van de extensie om verder te gaan."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Actieve leden op het niveau Commenter en hoger kunnen reacties plaatsen."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Word lid op het niveau Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Iedereen kan lezen en waarderingen geven. Actieve leden op het niveau Commenter en hoger kunnen reacties plaatsen."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Kies je openbare RYD-bijnaam voordat je een reactie plaatst."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Openbare RYD-bijnaam"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 letters, cijfers, spaties, punten, streepjes of onderstrepingstekens. Deze naam verschijnt bij je reacties."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Bijnaam opslaan"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Deze bijnaam is al in gebruik. Kies een andere."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Gebruik 3–32 letters, cijfers, spaties, punten, streepjes of onderstrepingstekens."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Bijnaam wijzigen"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Je reageert als $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Neem deel aan de discussie…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Melden"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Reactie melden"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Reden"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Intimidatie of haat"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Overig"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Aanvullende informatie (optioneel)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Melding verzenden"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Melding ontvangen. Bedankt."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderatie"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Geen meldingen om te beoordelen."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Reactie verbergen"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Reactie herstellen"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Meldingen afwijzen"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Auteur verbannen"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Verbanning van auteur opheffen"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Reden voor moderatie"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Moderatieactie opgeslagen."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 meldingen"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "RYD-reacties zijn niet beschikbaar voor deze video."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Deze reactie is niet meer beschikbaar."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Kan geen verbinding maken. Probeer het opnieuw."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Wacht even voordat je het opnieuw probeert."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Deze reactie is gewijzigd. Vernieuw en probeer het opnieuw."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Deze actie is niet beschikbaar voor je account."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Opnieuw proberen"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Meldingen"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Je bent weer helemaal bij."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 heeft je reactie beantwoord"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Iemand vindt je reactie leuk"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Je reactie heeft $1 likes gekregen"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Iemand vindt je reactie niet leuk"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Iemand heeft je reactie gewaardeerd"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Iemand"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Markeren als gelezen"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Alles markeren als gelezen"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Discussie bekijken"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 ongelezen meldingen"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Log in om antwoorden en waarderingen op je reacties te zien."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Deze discussie is niet meer beschikbaar."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Discussie"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Bijnaam"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Meldingen"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Status van melding"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Openstaande meldingen"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Afgewezen meldingen"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Auteur"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Jij"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Opslaan…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Bevestigen"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nieuwe activiteit bij je reacties"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Gespreksreeks tonen"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Antwoorden tonen ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Welkom bij Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -557,6 +557,294 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo Return YouTube Dislike"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Komentarze RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Dyskusja społeczności prowadzona przez Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Te komentarze są niezależne od YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Otwórz komentarze RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Zamknij"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Najnowsze"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Najlepsze"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Sortuj komentarze"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Odśwież"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Wczytywanie komentarzy…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Nie ma jeszcze komentarzy. Rozpocznij rozmowę."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Nie ma jeszcze odpowiedzi."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Komentarz"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Opublikuj komentarz"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Odpowiedz"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Opublikuj odpowiedź"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Anuluj"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Zapisz"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Edytuj"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Usuń"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Usunąć ten komentarz?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Komentarz usunięty"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "edytowano"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Odpowiedzi ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Wczytaj więcej"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Lubię to"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Nie podoba mi się"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Zapisywanie reakcji…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Aby kontynuować, zaloguj się w oknie rozszerzenia."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Publikowanie jest dostępne dla osób z aktywnym członkostwem na poziomie Commenter lub wyższym."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Zostań członkiem na poziomie Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Każdy może czytać i reagować. Osoby z aktywnym członkostwem na poziomie Commenter lub wyższym mogą publikować komentarze."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Przed opublikowaniem komentarza wybierz swój publiczny pseudonim RYD."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Publiczny pseudonim RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 litery, cyfry, spacje, kropki, łączniki lub podkreślenia. Ta nazwa będzie widoczna przy Twoich komentarzach."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Zapisz pseudonim"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Ten pseudonim jest już zajęty. Wybierz inny."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Użyj 3–32 liter, cyfr, spacji, kropek, łączników lub podkreśleń."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Zmień pseudonim"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Komentujesz jako $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Dołącz do dyskusji…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Zgłoś"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Zgłoś komentarz"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Powód"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Nękanie lub nienawiść"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Inny"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Dodatkowe informacje (opcjonalnie)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Wyślij zgłoszenie"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Zgłoszenie otrzymane. Dziękujemy."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderacja"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Brak zgłoszeń do rozpatrzenia."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Ukryj komentarz"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Przywróć komentarz"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Odrzuć zgłoszenia"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Zablokuj autora"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Odblokuj autora"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Powód moderacji"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Działanie moderacyjne zapisane."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "Zgłoszenia: $1"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Komentarze RYD są niedostępne dla tego filmu."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Ten komentarz nie jest już dostępny."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Nie udało się połączyć. Spróbuj ponownie."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Poczekaj chwilę przed ponowną próbą."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Ten komentarz został zmieniony. Odśwież i spróbuj ponownie."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "To działanie jest niedostępne dla Twojego konta."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Spróbuj ponownie"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Powiadomienia"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Wszystkie powiadomienia przeczytane."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 odpowiada na Twój komentarz"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Ktoś polubił Twój komentarz"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Liczba polubień Twojego komentarza: $1"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Komuś nie spodobał się Twój komentarz"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Ktoś zareagował na Twój komentarz"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Ktoś"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Oznacz jako przeczytane"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Oznacz wszystkie jako przeczytane"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Zobacz dyskusję"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "Nieprzeczytane powiadomienia: $1"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Zaloguj się, aby zobaczyć odpowiedzi i reakcje na Twoje komentarze."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Ta dyskusja nie jest już dostępna."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Dyskusja"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Pseudonim"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Zgłoszenia"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Status zgłoszenia"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Otwarte zgłoszenia"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Odrzucone zgłoszenia"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Autor"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Ty"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Zapisywanie…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Potwierdź"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nowa aktywność przy Twoich komentarzach"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Pokaż wątek"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Pokaż odpowiedzi ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Witaj w Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo do Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "O login de colaboradores pelo GitHub está indisponível no momento. O serviço precisa de uma atualização ou alteração na configuração."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Esta conta do GitHub não está listada como colaboradora do Return YouTube Dislike. Entre com uma conta que tenha contribuído com o projeto. Contribuições recentes podem levar algumas horas para aparecer."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "O login pelo GitHub não está configurado para o endereço de retorno deste navegador. Entre em contato com o suporte."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Esta tentativa de login pelo GitHub expirou ou não pôde ser verificada. Inicie um novo login."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Atualize a extensão para entrar como colaborador pelo GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Muitas tentativas de login. Aguarde um minuto antes de tentar novamente."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "A autorização do GitHub foi recusada. O login de colaboradores exige autorização."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Comentários do RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Uma discussão da comunidade hospedada pelo Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Estes comentários são independentes do YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Abrir comentários do RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Fechar"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Mais recentes"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Mais relevantes"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Ordenar comentários"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Atualizar"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Carregando comentários…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Ainda não há comentários. Comece a conversa."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Ainda não há respostas."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Comentário"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Publicar comentário"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Responder"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Publicar resposta"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Cancelar"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Salvar"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Editar"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Excluir"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Excluir este comentário?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Comentário excluído"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "editado"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Respostas ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Carregar mais"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Curtir"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Não gostei"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Salvando reação…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Entre pela janela da extensão para continuar."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Membros ativos do nível Commenter ou superior podem publicar."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Torne-se membro do nível Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Todos podem ler e reagir. Membros ativos do nível Commenter ou superior podem publicar."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Escolha seu apelido público do RYD antes de publicar."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Apelido público do RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "De 3 a 32 letras, números, espaços, pontos, hífens ou sublinhados. Este nome aparecerá nos seus comentários."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Salvar apelido"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Este apelido já está em uso. Escolha outro."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Use de 3 a 32 letras, números, espaços, pontos, hífens ou sublinhados."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Alterar apelido"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Comentando como $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Participe da discussão…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Denunciar"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Denunciar comentário"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Motivo"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Assédio ou ódio"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Outro"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Detalhes adicionais (opcional)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Enviar denúncia"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Denúncia recebida. Obrigado."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderação"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Nenhuma denúncia para analisar."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Ocultar comentário"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Restaurar comentário"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Rejeitar denúncias"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Banir autor"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Desbanir autor"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Motivo da moderação"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Ação de moderação salva."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 denúncias"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Os comentários do RYD não estão disponíveis para este vídeo."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Este comentário não está mais disponível."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Não foi possível conectar. Tente novamente."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Aguarde um momento antes de tentar novamente."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Este comentário foi alterado. Atualize e tente novamente."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Esta ação não está disponível para sua conta."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Tentar novamente"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Notificações"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Você está em dia."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 respondeu ao seu comentário"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Alguém curtiu seu comentário"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Seu comentário recebeu $1 curtidas"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Alguém não gostou do seu comentário"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Alguém reagiu ao seu comentário"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Alguém"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Marcar como lida"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Marcar todas como lidas"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Ver discussão"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 notificações não lidas"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Entre para ver respostas e reações aos seus comentários."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Esta discussão não está mais disponível."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Discussão"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Apelido"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Denúncias"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Status da denúncia"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Denúncias abertas"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Denúncias rejeitadas"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Autor"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Você"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Salvando…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Confirmar"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nova atividade nos seus comentários"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Mostrar conversa"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Mostrar respostas ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Boas-vindas ao Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -638,6 +638,27 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Логотип Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Вход для участников проекта через GitHub сейчас недоступен. Сервису требуется обновление или изменение конфигурации."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Этот аккаунт GitHub не указан среди участников проекта Return YouTube Dislike. Войдите с аккаунта, с которого вы вносили вклад в проект. Информация о недавнем вкладе в проект может появиться через несколько часов."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Вход через GitHub не настроен для адреса обратного вызова этого браузера. Обратитесь в службу поддержки."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Срок действия этой попытки входа через GitHub истёк или её не удалось подтвердить. Начните вход заново."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Обновите расширение, чтобы войти как участник проекта через GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Слишком много попыток входа. Подождите минуту перед следующей попыткой."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Авторизация через GitHub отклонена. Для входа участника проекта требуется авторизация."
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Добро пожаловать в Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -557,6 +557,294 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logotip Return YouTube Dislike"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Komentarji RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Razprava skupnosti, ki jo gosti Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Ti komentarji so ločeni od YouTuba."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Odpri komentarje RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Zapri"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Najnovejši"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Najboljši"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Razvrsti komentarje"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Osveži"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Nalaganje komentarjev…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Komentarjev še ni. Začnite pogovor."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Odgovorov še ni."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Komentar"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Objavi komentar"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Odgovori"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Objavi odgovor"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Prekliči"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Shrani"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Uredi"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Izbriši"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Želite izbrisati ta komentar?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Komentar je izbrisan"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "urejeno"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Odgovori ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Naloži več"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Všeč mi je"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Ni mi všeč"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Shranjevanje odziva…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Za nadaljevanje se prijavite v pojavnem oknu razširitve."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Objavljanje je na voljo članom z aktivnim članstvom na stopnji Commenter ali višji."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Pridobite članstvo Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Vsi lahko berejo in se odzivajo. Člani z aktivnim članstvom na stopnji Commenter ali višji lahko objavljajo."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Pred objavo izberite svoj javni vzdevek RYD."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Javni vzdevek RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 črk, številk, presledkov, pik, vezajev ali podčrtajev. To ime bo prikazano ob vaših komentarjih."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Shrani vzdevek"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Ta vzdevek je že zaseden. Izberite drugega."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Uporabite 3–32 črk, številk, presledkov, pik, vezajev ali podčrtajev."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Spremeni vzdevek"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Komentirate kot $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Pridružite se razpravi…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Prijavi"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Prijavi komentar"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Razlog"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Neželena vsebina"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Nadlegovanje ali sovraštvo"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Drugo"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Dodatne podrobnosti (neobvezno)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Pošlji prijavo"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Prijava je prejeta. Hvala."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderiranje"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Ni prijav za pregled."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Skrij komentar"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Obnovi komentar"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Zavrni prijave"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Blokiraj avtorja"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Odblokiraj avtorja"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Razlog moderiranja"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Dejanje moderiranja je shranjeno."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "Prijave: $1"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Komentarji RYD za ta videoposnetek niso na voljo."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Ta komentar ni več na voljo."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Povezave ni bilo mogoče vzpostaviti. Poskusite znova."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Pred ponovnim poskusom malo počakajte."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Ta komentar je bil spremenjen. Osvežite in poskusite znova."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "To dejanje za vaš račun ni na voljo."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Poskusi znova"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Obvestila"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Prebrali ste vsa obvestila."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 odgovarja na vaš komentar"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Nekomu je bil všeč vaš komentar"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Vaš komentar ima toliko všečkov: $1"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Nekomu ni bil všeč vaš komentar"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Nekdo se je odzval na vaš komentar"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Nekdo"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Označi kot prebrano"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Označi vse kot prebrano"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Ogled razprave"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "Neprebrana obvestila: $1"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Prijavite se za ogled odgovorov in odzivov na svoje komentarje."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Ta razprava ni več na voljo."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Razprava"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Vzdevek"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Prijave"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Stanje prijave"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Odprte prijave"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Zavrnjene prijave"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Avtor"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Vi"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Shranjevanje…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Potrdi"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Nova dejavnost pri vaših komentarjih"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Prikaži nit"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Prikaži odgovore ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Dobrodošli v Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike-logotyp"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Inloggning med GitHub för bidragsgivare är inte tillgänglig för tillfället. Tjänsten behöver uppdateras eller konfigureras om."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Det här GitHub-kontot finns inte med bland bidragsgivarna till Return YouTube Dislike. Logga in med ett konto som har bidragit. Det kan ta några timmar innan nya bidrag syns."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "GitHub-inloggning är inte konfigurerad för den här webbläsarens återanropsadress. Kontakta supporten."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Det här GitHub-inloggningsförsöket har löpt ut eller kunde inte verifieras. Starta en ny inloggning."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Uppdatera tillägget för att använda GitHub-inloggning för bidragsgivare."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "För många inloggningsförsök. Vänta en minut innan du försöker igen."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Åtkomst via GitHub nekades. Inloggning för bidragsgivare kräver att du ger åtkomst."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD-kommentarer"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "En diskussion för communityn som tillhandahålls av Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Dessa kommentarer är fristående från YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Öppna RYD-kommentarer"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Stäng"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Senaste"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Populäraste"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Sortera kommentarer"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Uppdatera"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Läser in kommentarer…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Inga kommentarer ännu. Starta diskussionen."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Inga svar ännu."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Kommentar"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Publicera kommentar"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Svara"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Publicera svar"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Avbryt"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Spara"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Redigera"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Ta bort"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Vill du ta bort den här kommentaren?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Kommentaren har tagits bort"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "redigerad"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Svar ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Läs in fler"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Gilla"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Ogilla"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Sparar reaktion…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Logga in via tilläggets popupfönster för att fortsätta."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Aktiva medlemmar på nivån Commenter och högre kan publicera kommentarer."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Bli Commenter-medlem"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Alla kan läsa och reagera. Aktiva medlemmar på nivån Commenter och högre kan publicera kommentarer."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Välj ditt offentliga RYD-smeknamn innan du publicerar."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Offentligt RYD-smeknamn"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 bokstäver, siffror, mellanslag, punkter, bindestreck eller understreck. Det här namnet visas vid dina kommentarer."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Spara smeknamn"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Det här smeknamnet är redan upptaget. Välj ett annat."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Använd 3–32 bokstäver, siffror, mellanslag, punkter, bindestreck eller understreck."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Ändra smeknamn"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Kommenterar som $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Delta i diskussionen…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Rapportera"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Rapportera kommentar"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Orsak"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Skräppost"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Trakasserier eller hat"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Annat"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Ytterligare information (valfritt)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Skicka rapport"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Rapporten har tagits emot. Tack."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderering"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Inga rapporter att granska."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Dölj kommentar"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Återställ kommentar"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Avfärda rapporter"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Stäng av författaren"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Häv författarens avstängning"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Orsak till moderering"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Modereringsåtgärden har sparats."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 rapporter"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "RYD-kommentarer är inte tillgängliga för den här videon."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Den här kommentaren är inte längre tillgänglig."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Det gick inte att ansluta. Försök igen."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Vänta en stund innan du försöker igen."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Den här kommentaren har ändrats. Uppdatera och försök igen."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Den här åtgärden är inte tillgänglig för ditt konto."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Försök igen"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Aviseringar"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Du har sett allt nytt."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 svarade på din kommentar"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Någon gillade din kommentar"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Din kommentar fick $1 gilla-markeringar"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Någon ogillade din kommentar"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Någon reagerade på din kommentar"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Någon"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Markera som läst"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Markera alla som lästa"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Visa diskussion"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 olästa aviseringar"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Logga in för att se svar och reaktioner på dina kommentarer."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Den här diskussionen är inte längre tillgänglig."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Diskussion"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Smeknamn"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Rapporter"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Rapportstatus"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Öppna rapporter"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Avfärdade rapporter"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Författare"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Du"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Sparar…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Bekräfta"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Ny aktivitet på dina kommentarer"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Visa tråd"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Visa svar ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Välkommen till Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike logosu"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Katkıda bulunanlar için GitHub ile giriş şu anda kullanılamıyor. Hizmetin güncellenmesi veya yapılandırmasının değiştirilmesi gerekiyor."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Bu GitHub hesabı, Return YouTube Dislike projesine katkıda bulunanlar arasında yer almıyor. Katkıda bulunan bir hesapla giriş yapın. Son katkıların görünmesi birkaç saat sürebilir."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "GitHub ile giriş, bu tarayıcının geri çağrı adresi için yapılandırılmamış. Lütfen destek ekibiyle iletişime geçin."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Bu GitHub giriş denemesinin süresi doldu veya deneme doğrulanamadı. Lütfen yeniden giriş yapmayı deneyin."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Katkıda bulunanlar için GitHub ile girişi kullanmak üzere lütfen uzantıyı güncelleyin."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Çok fazla giriş denemesi yapıldı. Tekrar denemeden önce lütfen bir dakika bekleyin."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub yetkilendirmesi reddedildi. Katkıda bulunanlar için giriş, yetkilendirme gerektirir."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD yorumları"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Return YouTube Dislike tarafından barındırılan bir topluluk tartışması."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Bu yorumlar YouTube yorumlarından ayrıdır."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "RYD yorumlarını aç"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Kapat"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "En yeni"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "En popüler"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Yorumları sırala"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Yenile"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Yorumlar yükleniyor…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Henüz yorum yok. Sohbeti başlatın."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Henüz yanıt yok."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Yorum"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Yorum gönder"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Yanıtla"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Yanıt gönder"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "İptal"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Kaydet"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Düzenle"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Sil"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Bu yorum silinsin mi?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Yorum silindi"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "düzenlendi"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Yanıtlar ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Daha fazla yükle"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Beğen"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Beğenme"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Tepki kaydediliyor…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Devam etmek için uzantının açılır penceresinden giriş yapın."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Yorum gönderme, aktif Commenter ve üzeri seviyelerdeki üyelere açıktır."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Commenter üyesi olun"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Herkes okuyabilir ve tepki verebilir. Aktif Commenter ve üzeri seviyelerdeki üyeler yorum gönderebilir."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Yorum göndermeden önce herkese açık RYD takma adınızı seçin."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Herkese açık RYD takma adı"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 harf, rakam, boşluk, nokta, kısa çizgi veya alt çizgi. Bu ad yorumlarınızla birlikte görünecektir."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Takma adı kaydet"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Bu takma ad zaten kullanılıyor. Başka bir takma ad seçin."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "3–32 harf, rakam, boşluk, nokta, kısa çizgi veya alt çizgi kullanın."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Takma adı değiştir"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "$1 olarak yorum yapıyorsunuz"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Tartışmaya katılın…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Şikayet et"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Yorumu şikayet et"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Neden"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Spam"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Taciz veya nefret"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Diğer"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Ek ayrıntılar (isteğe bağlı)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Şikayeti gönder"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Şikayet alındı. Teşekkür ederiz."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Moderasyon"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "İncelenecek şikayet yok."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Yorumu gizle"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Yorumu geri yükle"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Şikayetleri reddet"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Yazarı yasakla"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Yazarın yasağını kaldır"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Moderasyon nedeni"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Moderasyon işlemi kaydedildi."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 şikayet"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Bu video için RYD yorumları kullanılamıyor."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Bu yorum artık kullanılamıyor."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Bağlantı kurulamadı. Lütfen tekrar deneyin."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Tekrar denemeden önce lütfen biraz bekleyin."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Bu yorum değişti. Yenileyip tekrar deneyin."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Bu işlem hesabınız için kullanılamıyor."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Tekrar dene"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Bildirimler"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Tüm yeni bildirimleri gördünüz."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 yorumunuza yanıt verdi"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Birisi yorumunuzu beğendi"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Yorumunuz $1 beğeni aldı"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Birisi yorumunuzu beğenmedi"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Birisi yorumunuza tepki verdi"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Birisi"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Okundu olarak işaretle"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Tümünü okundu olarak işaretle"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Tartışmayı görüntüle"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 okunmamış bildirim"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Yorumlarınıza gelen yanıtları ve tepkileri görmek için giriş yapın."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Bu tartışma artık kullanılamıyor."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Tartışma"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Takma ad"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Şikayetler"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Şikayet durumu"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Açık şikayetler"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Reddedilen şikayetler"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Yazar"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Siz"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Kaydediliyor…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Onayla"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Yorumlarınızda yeni etkinlik var"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Yorum dizisini göster"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Yanıtları göster ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Return YouTube Dislike’a hoş geldiniz"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Логотип Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Вхід для учасників проєкту через GitHub зараз недоступний. Сервіс потребує оновлення або зміни конфігурації."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Цей обліковий запис GitHub не вказано серед учасників проєкту Return YouTube Dislike. Увійдіть з облікового запису, з якого ви робили внески в проєкт. Нещодавні внески можуть відобразитися за кілька годин."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Вхід через GitHub не налаштовано для адреси зворотного виклику цього браузера. Зверніться до служби підтримки."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Термін дії цієї спроби входу через GitHub минув або її не вдалося підтвердити. Почніть вхід заново."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Оновіть розширення, щоб увійти як учасник проєкту через GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Забагато спроб входу. Зачекайте хвилину перед наступною спробою."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Авторизацію через GitHub відхилено. Для входу учасника проєкту потрібна авторизація."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Коментарі RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Обговорення спільноти на платформі Return YouTube Dislike."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Ці коментарі не пов’язані з YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Відкрити коментарі RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Закрити"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Найновіші"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Найкращі"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Сортувати коментарі"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Оновити"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Завантаження коментарів…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Коментарів поки немає. Розпочніть розмову."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Відповідей поки немає."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Коментар"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Опублікувати коментар"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Відповісти"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Опублікувати відповідь"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Скасувати"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Зберегти"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Редагувати"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Видалити"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Видалити цей коментар?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Коментар видалено"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "відредаговано"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Відповіді ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Завантажити ще"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Подобається"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Не подобається"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Збереження реакції…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Щоб продовжити, увійдіть через спливне вікно розширення."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Публікація доступна учасникам з активною підпискою рівня Commenter або вище."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Стати учасником рівня Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Усі можуть читати й реагувати. Учасники з активною підпискою рівня Commenter або вище можуть публікувати коментарі."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Перед публікацією виберіть свій публічний псевдонім RYD."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Публічний псевдонім RYD"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 літери, цифри, пробіли, крапки, дефіси або знаки підкреслення. Це ім’я відображатиметься біля ваших коментарів."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Зберегти псевдонім"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Цей псевдонім уже зайнятий. Виберіть інший."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Використовуйте 3–32 літери, цифри, пробіли, крапки, дефіси або знаки підкреслення."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Змінити псевдонім"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Ви коментуєте як $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Долучайтеся до обговорення…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Поскаржитися"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Поскаржитися на коментар"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Причина"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Спам"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Переслідування або ненависть"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Інше"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Додаткові відомості (необов’язково)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Надіслати скаргу"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Скаргу отримано. Дякуємо."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Модерація"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Немає скарг для розгляду."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Приховати коментар"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Відновити коментар"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Відхилити скарги"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Заблокувати автора"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Розблокувати автора"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Причина модерації"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Дію модерації збережено."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "Скарг: $1"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Коментарі RYD недоступні для цього відео."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Цей коментар більше недоступний."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Не вдалося під’єднатися. Спробуйте ще раз."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Зачекайте трохи перед наступною спробою."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Цей коментар змінився. Оновіть і спробуйте ще раз."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Ця дія недоступна для вашого облікового запису."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Спробувати ще раз"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Сповіщення"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Усі сповіщення прочитано."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 відповідає на ваш коментар"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Комусь сподобався ваш коментар"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Кількість уподобань вашого коментаря: $1"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Комусь не сподобався ваш коментар"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Хтось відреагував на ваш коментар"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Хтось"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Позначити як прочитане"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Позначити все як прочитане"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Переглянути обговорення"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "Непрочитаних сповіщень: $1"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Увійдіть, щоб бачити відповіді й реакції на ваші коментарі."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Це обговорення більше недоступне."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Обговорення"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Псевдонім"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Скарги"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Статус скарги"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Відкриті скарги"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Відхилені скарги"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Автор"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Ви"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Збереження…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Підтвердити"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Нова активність у ваших коментарях"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Показати гілку обговорення"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Показати відповіді ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Вітаємо в Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Logo Return YouTube Dislike"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "Hiện không thể đăng nhập với tư cách người đóng góp GitHub. Dịch vụ cần được cập nhật hoặc thay đổi cấu hình."
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "Tài khoản GitHub này không có trong danh sách người đóng góp cho Return YouTube Dislike. Hãy đăng nhập bằng tài khoản đã đóng góp. Các đóng góp gần đây có thể mất vài giờ mới được hiển thị."
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "Đăng nhập GitHub chưa được cấu hình cho địa chỉ gọi lại của trình duyệt này. Vui lòng liên hệ bộ phận hỗ trợ."
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "Lần đăng nhập GitHub này đã hết hạn hoặc không thể xác minh. Vui lòng bắt đầu đăng nhập lại."
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "Vui lòng cập nhật tiện ích mở rộng để đăng nhập với tư cách người đóng góp GitHub."
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "Bạn đã thử đăng nhập quá nhiều lần. Vui lòng đợi một phút trước khi thử lại."
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "Quyền truy cập GitHub đã bị từ chối. Đăng nhập với tư cách người đóng góp cần được cấp quyền."
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "Bình luận RYD"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "Cuộc thảo luận cộng đồng do Return YouTube Dislike tổ chức."
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "Những bình luận này tách biệt với YouTube."
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "Mở bình luận RYD"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "Đóng"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "Mới nhất"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "Hàng đầu"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "Sắp xếp bình luận"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "Làm mới"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "Đang tải bình luận…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "Chưa có bình luận nào. Hãy bắt đầu cuộc trò chuyện."
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "Chưa có phản hồi nào."
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "Bình luận"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "Đăng bình luận"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "Phản hồi"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "Đăng phản hồi"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "Hủy"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "Lưu"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "Chỉnh sửa"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "Xóa"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "Xóa bình luận này?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "Bình luận đã bị xóa"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "đã chỉnh sửa"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "Phản hồi ($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "Tải thêm"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "Thích"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "Không thích"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "Đang lưu cảm xúc…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "Đăng nhập từ cửa sổ bật lên của tiện ích mở rộng để tiếp tục."
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "Thành viên đang hoạt động ở cấp Commenter trở lên có thể đăng bài."
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "Trở thành thành viên Commenter"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "Mọi người đều có thể đọc và bày tỏ cảm xúc. Thành viên đang hoạt động ở cấp Commenter trở lên có thể đăng bài."
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "Chọn biệt danh RYD công khai trước khi đăng bài."
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "Biệt danh RYD công khai"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "3–32 ký tự gồm chữ cái, chữ số, dấu cách, dấu chấm, dấu gạch ngang hoặc dấu gạch dưới. Tên này sẽ hiển thị cùng bình luận của bạn."
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "Lưu biệt danh"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "Biệt danh này đã được sử dụng. Hãy chọn biệt danh khác."
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "Dùng 3–32 ký tự gồm chữ cái, chữ số, dấu cách, dấu chấm, dấu gạch ngang hoặc dấu gạch dưới."
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "Đổi biệt danh"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "Bình luận với tên $1"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "Tham gia thảo luận…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "Báo cáo"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "Báo cáo bình luận"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "Lý do"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "Nội dung rác"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "Quấy rối hoặc thù ghét"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "Khác"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "Thông tin bổ sung (không bắt buộc)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "Gửi báo cáo"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "Đã nhận được báo cáo. Cảm ơn bạn."
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "Kiểm duyệt"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "Không có báo cáo nào cần xem xét."
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "Ẩn bình luận"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "Khôi phục bình luận"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "Bác bỏ báo cáo"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "Cấm tác giả"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "Bỏ cấm tác giả"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "Lý do kiểm duyệt"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "Đã lưu thao tác kiểm duyệt."
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 báo cáo"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "Bình luận RYD không khả dụng cho video này."
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "Bình luận này không còn khả dụng."
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "Không thể kết nối. Vui lòng thử lại."
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "Vui lòng đợi một lát trước khi thử lại."
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "Bình luận này đã thay đổi. Hãy làm mới và thử lại."
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "Tài khoản của bạn không thể thực hiện thao tác này."
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "Thử lại"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "Thông báo"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "Bạn đã xem hết thông báo."
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 đã phản hồi bình luận của bạn"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "Có người đã thích bình luận của bạn"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "Bình luận của bạn nhận được $1 lượt thích"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "Có người đã bấm không thích bình luận của bạn"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "Có người đã bày tỏ cảm xúc về bình luận của bạn"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "Ai đó"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "Đánh dấu đã đọc"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "Đánh dấu tất cả đã đọc"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "Xem thảo luận"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 thông báo chưa đọc"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "Đăng nhập để xem phản hồi và cảm xúc về bình luận của bạn."
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "Cuộc thảo luận này không còn khả dụng."
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "Thảo luận"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "Biệt danh"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "Báo cáo"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "Trạng thái báo cáo"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "Báo cáo chưa xử lý"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "Báo cáo đã bác bỏ"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "Tác giả"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "Bạn"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "Đang lưu…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "Xác nhận"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "Hoạt động mới trên bình luận của bạn"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "Hiện chuỗi bình luận"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "Hiện phản hồi ($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "Chào mừng đến với Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike 标志"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "GitHub 贡献者登录目前不可用。服务需要更新或更改配置。"
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "此 GitHub 账户未被列为 Return YouTube Dislike 的贡献者。请使用有贡献记录的账户登录。近期的贡献可能需要几小时才会显示。"
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "尚未为此浏览器的回调地址配置 GitHub 登录。请联系支持人员。"
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "此次 GitHub 登录尝试已过期或无法验证。请重新登录。"
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "请更新扩展以使用 GitHub 贡献者登录。"
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "登录尝试次数过多。请等待一分钟后重试。"
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub 授权被拒绝。贡献者登录需要授权。"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD 评论"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "由 Return YouTube Dislike 提供的社区讨论。"
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "这些评论独立于 YouTube。"
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "打开 RYD 评论"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "关闭"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "最新"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "热门"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "评论排序"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "刷新"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "正在加载评论…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "还没有评论。来开启讨论吧。"
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "还没有回复。"
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "评论"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "发表评论"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "回复"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "发布回复"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "取消"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "保存"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "编辑"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "删除"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "删除这条评论?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "评论已删除"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "已编辑"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "回复($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "加载更多"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "点赞"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "点踩"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "正在保存回应…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "请在扩展弹出窗口中登录以继续。"
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "有效的 Commenter 及以上等级会员可以发言。"
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "成为 Commenter 会员"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "所有人都可以阅读和回应。有效的 Commenter 及以上等级会员可以发言。"
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "发言前请设置您的 RYD 公开昵称。"
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "RYD 公开昵称"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "可使用 3–32 个字母、数字、空格、句点、连字符或下划线。此昵称将随您的评论一起显示。"
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "保存昵称"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "此昵称已被使用。请选择其他昵称。"
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "请使用 3–32 个字母、数字、空格、句点、连字符或下划线。"
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "更改昵称"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "以 $1 的身份评论"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "参与讨论…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "举报"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "举报评论"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "原因"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "垃圾信息"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "骚扰或仇恨"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "其他"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "补充详情(可选)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "提交举报"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "举报已收到。谢谢。"
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "内容管理"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "没有待审核的举报。"
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "隐藏评论"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "恢复评论"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "驳回举报"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "封禁作者"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "解封作者"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "管理操作原因"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "管理操作已保存。"
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 次举报"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "此视频无法使用 RYD 评论。"
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "此评论已不可用。"
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "无法连接。请重试。"
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "请稍等片刻后重试。"
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "此评论已被更改。请刷新后重试。"
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "您的账户无法执行此操作。"
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "重试"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "通知"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "您已查看所有通知。"
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 回复了您的评论"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "有人赞了您的评论"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "您的评论收到了 $1 个赞"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "有人踩了您的评论"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "有人回应了您的评论"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "有人"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "标为已读"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "全部标为已读"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "查看讨论"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 条未读通知"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "登录后可查看您评论收到的回复和回应。"
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "此讨论已不可用。"
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "讨论"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "昵称"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "举报"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "举报状态"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "待处理举报"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "已驳回的举报"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "作者"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "您"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "正在保存…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "确认"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "您的评论有新动态"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "显示评论串"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "显示回复($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "欢迎使用 Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -536,6 +536,315 @@
|
||||
"changelog_brand_logo_alt": {
|
||||
"message": "Return YouTube Dislike 標誌"
|
||||
},
|
||||
"githubLoginUnavailable": {
|
||||
"message": "目前無法使用 GitHub 貢獻者登入。服務需要更新或變更設定。"
|
||||
},
|
||||
"githubLoginNotContributor": {
|
||||
"message": "此 GitHub 帳戶未列為 Return YouTube Dislike 的貢獻者。請使用有貢獻紀錄的帳戶登入。近期的貢獻可能需要幾個小時才會顯示。"
|
||||
},
|
||||
"githubLoginBrowserUnavailable": {
|
||||
"message": "尚未為此瀏覽器的回呼位址設定 GitHub 登入。請聯絡支援人員。"
|
||||
},
|
||||
"githubLoginExpired": {
|
||||
"message": "此次 GitHub 登入嘗試已過期或無法驗證。請重新登入。"
|
||||
},
|
||||
"githubLoginUpdateRequired": {
|
||||
"message": "請更新擴充功能以使用 GitHub 貢獻者登入。"
|
||||
},
|
||||
"githubLoginRateLimited": {
|
||||
"message": "登入嘗試次數過多。請等待一分鐘後再試。"
|
||||
},
|
||||
"githubLoginDenied": {
|
||||
"message": "GitHub 授權遭拒。貢獻者登入需要授權。"
|
||||
},
|
||||
"discussion_title": {
|
||||
"message": "RYD 留言"
|
||||
},
|
||||
"discussion_subtitle": {
|
||||
"message": "由 Return YouTube Dislike 提供的社群討論。"
|
||||
},
|
||||
"discussion_independent": {
|
||||
"message": "這些留言獨立於 YouTube。"
|
||||
},
|
||||
"discussion_open": {
|
||||
"message": "開啟 RYD 留言"
|
||||
},
|
||||
"discussion_close": {
|
||||
"message": "關閉"
|
||||
},
|
||||
"discussion_new": {
|
||||
"message": "最新"
|
||||
},
|
||||
"discussion_top": {
|
||||
"message": "熱門"
|
||||
},
|
||||
"discussion_sort": {
|
||||
"message": "留言排序"
|
||||
},
|
||||
"discussion_refresh": {
|
||||
"message": "重新整理"
|
||||
},
|
||||
"discussion_loading": {
|
||||
"message": "正在載入留言…"
|
||||
},
|
||||
"discussion_empty": {
|
||||
"message": "還沒有留言。來開啟討論吧。"
|
||||
},
|
||||
"discussion_replyEmpty": {
|
||||
"message": "還沒有回覆。"
|
||||
},
|
||||
"discussion_comment": {
|
||||
"message": "留言"
|
||||
},
|
||||
"discussion_post": {
|
||||
"message": "發布留言"
|
||||
},
|
||||
"discussion_reply": {
|
||||
"message": "回覆"
|
||||
},
|
||||
"discussion_postReply": {
|
||||
"message": "發布回覆"
|
||||
},
|
||||
"discussion_cancel": {
|
||||
"message": "取消"
|
||||
},
|
||||
"discussion_save": {
|
||||
"message": "儲存"
|
||||
},
|
||||
"discussion_edit": {
|
||||
"message": "編輯"
|
||||
},
|
||||
"discussion_delete": {
|
||||
"message": "刪除"
|
||||
},
|
||||
"discussion_deleteConfirm": {
|
||||
"message": "要刪除此留言嗎?"
|
||||
},
|
||||
"discussion_deleted": {
|
||||
"message": "留言已刪除"
|
||||
},
|
||||
"discussion_edited": {
|
||||
"message": "已編輯"
|
||||
},
|
||||
"discussion_replies": {
|
||||
"message": "回覆($1)"
|
||||
},
|
||||
"discussion_more": {
|
||||
"message": "載入更多"
|
||||
},
|
||||
"discussion_like": {
|
||||
"message": "按讚"
|
||||
},
|
||||
"discussion_dislike": {
|
||||
"message": "不喜歡"
|
||||
},
|
||||
"discussion_reacting": {
|
||||
"message": "正在儲存反應…"
|
||||
},
|
||||
"discussion_signInRequired": {
|
||||
"message": "請從擴充功能的彈出視窗登入以繼續。"
|
||||
},
|
||||
"discussion_tierRequired": {
|
||||
"message": "有效的 Commenter 及以上等級會員可以發言。"
|
||||
},
|
||||
"discussion_join": {
|
||||
"message": "成為 Commenter 會員"
|
||||
},
|
||||
"discussion_gate": {
|
||||
"message": "所有人都可以閱讀和表達反應。有效的 Commenter 及以上等級會員可以發言。"
|
||||
},
|
||||
"discussion_nicknameRequired": {
|
||||
"message": "發言前請設定您的 RYD 公開暱稱。"
|
||||
},
|
||||
"discussion_nicknameLabel": {
|
||||
"message": "RYD 公開暱稱"
|
||||
},
|
||||
"discussion_nicknameHint": {
|
||||
"message": "可使用 3–32 個字母、數字、空格、句點、連字號或底線。此暱稱會與您的留言一起顯示。"
|
||||
},
|
||||
"discussion_nicknameSave": {
|
||||
"message": "儲存暱稱"
|
||||
},
|
||||
"discussion_nicknameTaken": {
|
||||
"message": "此暱稱已被使用。請選擇其他暱稱。"
|
||||
},
|
||||
"discussion_nicknameInvalid": {
|
||||
"message": "請使用 3–32 個字母、數字、空格、句點、連字號或底線。"
|
||||
},
|
||||
"discussion_nicknameChange": {
|
||||
"message": "變更暱稱"
|
||||
},
|
||||
"discussion_as": {
|
||||
"message": "以 $1 的身分留言"
|
||||
},
|
||||
"discussion_placeholder": {
|
||||
"message": "參與討論…"
|
||||
},
|
||||
"discussion_characters": {
|
||||
"message": "$1 / $2"
|
||||
},
|
||||
"discussion_report": {
|
||||
"message": "檢舉"
|
||||
},
|
||||
"discussion_reportTitle": {
|
||||
"message": "檢舉留言"
|
||||
},
|
||||
"discussion_reportReason": {
|
||||
"message": "原因"
|
||||
},
|
||||
"discussion_reportSpam": {
|
||||
"message": "垃圾訊息"
|
||||
},
|
||||
"discussion_reportAbuse": {
|
||||
"message": "騷擾或仇恨"
|
||||
},
|
||||
"discussion_reportOther": {
|
||||
"message": "其他"
|
||||
},
|
||||
"discussion_reportDetails": {
|
||||
"message": "補充詳情(選填)"
|
||||
},
|
||||
"discussion_reportSend": {
|
||||
"message": "送出檢舉"
|
||||
},
|
||||
"discussion_reportDone": {
|
||||
"message": "已收到檢舉,謝謝。"
|
||||
},
|
||||
"discussion_moderation": {
|
||||
"message": "內容管理"
|
||||
},
|
||||
"discussion_queueEmpty": {
|
||||
"message": "沒有待審核的檢舉。"
|
||||
},
|
||||
"discussion_hide": {
|
||||
"message": "隱藏留言"
|
||||
},
|
||||
"discussion_restore": {
|
||||
"message": "還原留言"
|
||||
},
|
||||
"discussion_dismiss": {
|
||||
"message": "駁回檢舉"
|
||||
},
|
||||
"discussion_ban": {
|
||||
"message": "封鎖作者"
|
||||
},
|
||||
"discussion_unban": {
|
||||
"message": "解除封鎖作者"
|
||||
},
|
||||
"discussion_moderationReason": {
|
||||
"message": "管理操作原因"
|
||||
},
|
||||
"discussion_moderationSaved": {
|
||||
"message": "管理操作已儲存。"
|
||||
},
|
||||
"discussion_reported": {
|
||||
"message": "$1 次檢舉"
|
||||
},
|
||||
"discussion_unavailable": {
|
||||
"message": "此影片無法使用 RYD 留言。"
|
||||
},
|
||||
"discussion_commentUnavailable": {
|
||||
"message": "此留言已無法查看。"
|
||||
},
|
||||
"discussion_error": {
|
||||
"message": "無法連線。請再試一次。"
|
||||
},
|
||||
"discussion_rateLimited": {
|
||||
"message": "請稍候再試。"
|
||||
},
|
||||
"discussion_conflict": {
|
||||
"message": "此留言已被變更。請重新整理後再試。"
|
||||
},
|
||||
"discussion_forbidden": {
|
||||
"message": "您的帳戶無法執行此操作。"
|
||||
},
|
||||
"discussion_retry": {
|
||||
"message": "再試一次"
|
||||
},
|
||||
"discussion_notifications": {
|
||||
"message": "通知"
|
||||
},
|
||||
"discussion_notificationEmpty": {
|
||||
"message": "您已查看所有通知。"
|
||||
},
|
||||
"discussion_notificationReply": {
|
||||
"message": "$1 回覆了您的留言"
|
||||
},
|
||||
"discussion_notificationLike": {
|
||||
"message": "有人對您的留言按讚"
|
||||
},
|
||||
"discussion_notificationLikes": {
|
||||
"message": "您的留言獲得了 $1 個讚"
|
||||
},
|
||||
"discussion_notificationDislike": {
|
||||
"message": "有人對您的留言按了不喜歡"
|
||||
},
|
||||
"discussion_notificationReaction": {
|
||||
"message": "有人對您的留言表達了反應"
|
||||
},
|
||||
"discussion_someone": {
|
||||
"message": "有人"
|
||||
},
|
||||
"discussion_markRead": {
|
||||
"message": "標示為已讀"
|
||||
},
|
||||
"discussion_markAllRead": {
|
||||
"message": "全部標示為已讀"
|
||||
},
|
||||
"discussion_view": {
|
||||
"message": "查看討論"
|
||||
},
|
||||
"discussion_unread": {
|
||||
"message": "$1 則未讀通知"
|
||||
},
|
||||
"discussion_signedOutInbox": {
|
||||
"message": "登入後即可查看您留言收到的回覆與反應。"
|
||||
},
|
||||
"discussion_notificationUnavailable": {
|
||||
"message": "此討論已無法查看。"
|
||||
},
|
||||
"discussion_discussionTab": {
|
||||
"message": "討論"
|
||||
},
|
||||
"discussion_nickname": {
|
||||
"message": "暱稱"
|
||||
},
|
||||
"discussion_reportCount": {
|
||||
"message": "檢舉"
|
||||
},
|
||||
"discussion_reportStatus": {
|
||||
"message": "檢舉狀態"
|
||||
},
|
||||
"discussion_openReports": {
|
||||
"message": "待處理檢舉"
|
||||
},
|
||||
"discussion_resolvedReports": {
|
||||
"message": "已駁回的檢舉"
|
||||
},
|
||||
"discussion_author": {
|
||||
"message": "作者"
|
||||
},
|
||||
"discussion_me": {
|
||||
"message": "您"
|
||||
},
|
||||
"discussion_saving": {
|
||||
"message": "正在儲存…"
|
||||
},
|
||||
"discussion_confirm": {
|
||||
"message": "確認"
|
||||
},
|
||||
"discussion_notificationUpdated": {
|
||||
"message": "您的留言有新動態"
|
||||
},
|
||||
"discussion_showThread": {
|
||||
"message": "顯示留言串"
|
||||
},
|
||||
"discussion_loadReplies": {
|
||||
"message": "顯示回覆($1)"
|
||||
},
|
||||
"patreonTierCommenter": {
|
||||
"message": "Commenter"
|
||||
},
|
||||
"changelog_page_title": {
|
||||
"message": "歡迎使用 Return YouTube Dislike"
|
||||
},
|
||||
|
||||
@@ -946,12 +946,21 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
}
|
||||
|
||||
.ryd-premium-teaser {
|
||||
background: var(--yt-spec-base-background, #202020);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
--ryd-teaser-bg: var(--yt-spec-base-background, #fff);
|
||||
--ryd-teaser-fg: var(--yt-spec-text-primary, #0f0f0f);
|
||||
--ryd-teaser-muted: var(--yt-spec-text-secondary, #606060);
|
||||
--ryd-teaser-control: var(--ryd-teaser-muted);
|
||||
--ryd-teaser-subtitle: var(--ryd-teaser-muted);
|
||||
--ryd-teaser-highlights: var(--ryd-teaser-muted);
|
||||
--ryd-teaser-link: var(--ryd-teaser-muted);
|
||||
--ryd-teaser-hover-fg: var(--ryd-teaser-fg);
|
||||
--ryd-teaser-border: rgba(0, 0, 0, 0.08);
|
||||
background: var(--ryd-teaser-bg);
|
||||
border: 1px solid var(--ryd-teaser-border);
|
||||
border-radius: 16px;
|
||||
padding: 12px 18px 10px;
|
||||
margin-bottom: 16px;
|
||||
color: var(--yt-spec-text-primary, #ffffff);
|
||||
color: var(--ryd-teaser-fg);
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
|
||||
font-family: Roboto, Arial, sans-serif;
|
||||
transition:
|
||||
@@ -965,6 +974,18 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
html[dark] .ryd-premium-teaser {
|
||||
--ryd-teaser-bg: var(--yt-spec-base-background, #202020);
|
||||
--ryd-teaser-fg: var(--yt-spec-text-primary, #fff);
|
||||
--ryd-teaser-muted: var(--yt-spec-text-secondary, #9ca3af);
|
||||
--ryd-teaser-control: var(--yt-spec-text-secondary, #94a3b8);
|
||||
--ryd-teaser-subtitle: var(--yt-spec-text-secondary, #bcccdc);
|
||||
--ryd-teaser-highlights: var(--yt-spec-text-secondary, #93adc8);
|
||||
--ryd-teaser-link: var(--yt-spec-text-secondary, #8ea4c8);
|
||||
--ryd-teaser-hover-fg: var(--yt-spec-text-primary, #f8fafc);
|
||||
--ryd-teaser-border: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.ryd-premium-teaser.is-expanded {
|
||||
gap: 12px;
|
||||
padding: 12px 18px 16px;
|
||||
@@ -1067,7 +1088,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--yt-spec-text-secondary, #9ca3af);
|
||||
color: var(--ryd-teaser-muted);
|
||||
}
|
||||
|
||||
.ryd-premium-teaser__count-value {
|
||||
@@ -1085,7 +1106,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: rgba(148, 163, 184, 0.16);
|
||||
color: var(--yt-spec-text-secondary, #94a3b8);
|
||||
color: var(--ryd-teaser-control);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
@@ -1102,7 +1123,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
.ryd-premium-teaser__toggle:hover,
|
||||
.ryd-premium-teaser__toggle:focus-visible {
|
||||
background: rgba(148, 163, 184, 0.28);
|
||||
color: var(--yt-spec-text-primary, #f8fafc);
|
||||
color: var(--ryd-teaser-hover-fg);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -1125,7 +1146,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
color: var(--yt-spec-text-secondary, #94a3b8);
|
||||
color: var(--ryd-teaser-control);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -1141,7 +1162,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
.ryd-premium-teaser__close:hover,
|
||||
.ryd-premium-teaser__close:focus-visible {
|
||||
background: rgba(148, 163, 184, 0.16);
|
||||
color: var(--yt-spec-text-primary, #f8fafc);
|
||||
color: var(--ryd-teaser-hover-fg);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -1171,7 +1192,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
.ryd-premium-teaser__subtitle {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--yt-spec-text-secondary, #bcccdc);
|
||||
color: var(--ryd-teaser-subtitle);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
@@ -1180,7 +1201,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--yt-spec-text-secondary, #9ca3af);
|
||||
color: var(--ryd-teaser-muted);
|
||||
}
|
||||
|
||||
.ryd-premium-teaser__highlights-list {
|
||||
@@ -1189,7 +1210,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--yt-spec-text-secondary, #93adc8);
|
||||
color: var(--ryd-teaser-highlights);
|
||||
}
|
||||
|
||||
.ryd-premium-teaser__links {
|
||||
@@ -1221,7 +1242,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
}
|
||||
|
||||
.ryd-premium-teaser__secondary {
|
||||
color: var(--yt-spec-text-secondary, #8ea4c8);
|
||||
color: var(--ryd-teaser-link);
|
||||
font-size: 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
@@ -1233,7 +1254,7 @@ ytd-menu-renderer.ytd-watch-metadata {
|
||||
.ryd-premium-teaser__status {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--yt-spec-text-secondary, #9ca3af);
|
||||
color: var(--ryd-teaser-muted);
|
||||
}
|
||||
|
||||
html[dark] .ryd-premium-teaser__count {
|
||||
|
||||
@@ -10,8 +10,8 @@ const customColors = {
|
||||
dark: { like: "#abcdef", dislike: "#fedcba" },
|
||||
};
|
||||
const defaultColors = {
|
||||
light: { like: "#008000", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff66ff" },
|
||||
light: { like: "#007600", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff77ff" },
|
||||
};
|
||||
|
||||
describe("popup color settings", () => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<!--- HEADER -->
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" />
|
||||
<meta charset="utf-8" />
|
||||
<title title="__MSG_extensionName__">__MSG_extensionName__</title>
|
||||
<link rel="stylesheet" href="popup.css" />
|
||||
<link rel="stylesheet" href="content-style.css" />
|
||||
@@ -239,7 +239,7 @@
|
||||
</div>
|
||||
<div id="custom_colors_light" class="custom-color-inputs" hidden>
|
||||
<label for="custom_color_light_like">__MSG_colorThemeLike__</label>
|
||||
<input type="color" id="custom_color_light_like" value="#008000" disabled />
|
||||
<input type="color" id="custom_color_light_like" value="#007600" disabled />
|
||||
<label for="custom_color_light_dislike">__MSG_colorThemeDislike__</label>
|
||||
<input type="color" id="custom_color_light_dislike" value="#b300b3" disabled />
|
||||
</div>
|
||||
@@ -260,7 +260,7 @@
|
||||
<label for="custom_color_dark_like">__MSG_colorThemeLike__</label>
|
||||
<input type="color" id="custom_color_dark_like" value="#00d000" disabled />
|
||||
<label for="custom_color_dark_dislike">__MSG_colorThemeDislike__</label>
|
||||
<input type="color" id="custom_color_dark_dislike" value="#ff66ff" disabled />
|
||||
<input type="color" id="custom_color_dark_dislike" value="#ff77ff" disabled />
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getButtons, getDislikeButton, getLikeButton } from "./buttons";
|
||||
import { extConfig, isMobile, isLikesDisabled, isNewDesign, isRoundedDesign, isShorts } from "./state";
|
||||
import { extConfig, isMobile, isLikesDisabled, isNewDesign, isRoundedDesign, isShorts, isVideoLiked } from "./state";
|
||||
import { getColorFromTheme, getElementWidth, getVideoId, isInViewport, querySelector } from "./utils";
|
||||
|
||||
function closestConfigured(element, selectors) {
|
||||
@@ -147,6 +147,7 @@ function createRateBar(likes, dislikes) {
|
||||
<div class="ryd-tooltip-bar-container">
|
||||
<div
|
||||
id="ryd-bar-container"
|
||||
data-ryd-liked="${isVideoLiked()}"
|
||||
style="width: 100%; height: 2px;${colorDislikeStyle}"
|
||||
>
|
||||
<div
|
||||
@@ -175,6 +176,7 @@ function createRateBar(likes, dislikes) {
|
||||
} else {
|
||||
const currentParts = getRateBarParts(buttons);
|
||||
currentParts.wrapper.setAttribute("data-ryd-video-id", videoId);
|
||||
currentParts.rateBar.setAttribute("data-ryd-liked", String(isVideoLiked()));
|
||||
currentParts.wrapper.style.width = widthPx + "px";
|
||||
currentParts.fill.style.width = widthPercent + "%";
|
||||
const tooltipHost = buttons.querySelector("#ryd-dislike-tooltip");
|
||||
|
||||
@@ -29,6 +29,7 @@ jest.mock("./state", () => ({
|
||||
isNewDesign: jest.fn(() => true),
|
||||
isRoundedDesign: jest.fn(() => true),
|
||||
isShorts: jest.fn(() => false),
|
||||
isVideoLiked: jest.fn(() => false),
|
||||
}));
|
||||
|
||||
jest.mock("./utils", () => ({
|
||||
@@ -48,8 +49,8 @@ jest.mock("./utils", () => ({
|
||||
|
||||
const { getButtons, getDislikeButton, getLikeButton } = require("./buttons");
|
||||
const { createRateBar, hasUsableRateBar } = require("./bar");
|
||||
const { isLikesDisabled, isMobile, isNewDesign, isRoundedDesign, isShorts } = require("./state");
|
||||
const { getVideoId } = require("./utils");
|
||||
const { isLikesDisabled, isMobile, isNewDesign, isRoundedDesign, isShorts, isVideoLiked } = require("./state");
|
||||
const { getVideoId, isInViewport } = require("./utils");
|
||||
|
||||
describe("rate-bar stylesheet contrast", () => {
|
||||
test("uses the same high-contrast negative track recipe as the userscript", () => {
|
||||
@@ -95,6 +96,7 @@ describe("rate-bar visual ownership", () => {
|
||||
isNewDesign.mockReturnValue(true);
|
||||
isRoundedDesign.mockReturnValue(true);
|
||||
isShorts.mockReturnValue(false);
|
||||
isVideoLiked.mockReturnValue(false);
|
||||
getVideoId.mockReturnValue("BBBBBBBBBBB");
|
||||
const buttons = document.querySelector('[data-watch-buttons="BBBBBBBBBBB"]');
|
||||
getButtons.mockReturnValue(buttons);
|
||||
@@ -102,6 +104,32 @@ describe("rate-bar visual ownership", () => {
|
||||
getDislikeButton.mockReturnValue(buttons.querySelector("dislike-button-view-model"));
|
||||
});
|
||||
|
||||
test.each([false, true])("initializes the custom CSS hook from the native liked state: %s", (liked) => {
|
||||
isVideoLiked.mockReturnValue(liked);
|
||||
|
||||
createRateBar(80, 20);
|
||||
|
||||
expect(getButtons().querySelector("#ryd-bar-container").getAttribute("data-ryd-liked")).toBe(String(liked));
|
||||
});
|
||||
|
||||
test("refreshes the liked hook when reusing or recreating the bar", () => {
|
||||
isInViewport.mockReturnValue(true);
|
||||
createRateBar(80, 20);
|
||||
const originalBar = getButtons().querySelector("#ryd-bar-container");
|
||||
isVideoLiked.mockReturnValue(true);
|
||||
|
||||
createRateBar(81, 20);
|
||||
|
||||
expect(getButtons().querySelector("#ryd-bar-container")).toBe(originalBar);
|
||||
expect(originalBar.getAttribute("data-ryd-liked")).toBe("true");
|
||||
|
||||
originalBar.closest(".ryd-tooltip").remove();
|
||||
createRateBar(81, 20);
|
||||
const recreatedBar = getButtons().querySelector("#ryd-bar-container");
|
||||
expect(recreatedBar).not.toBe(originalBar);
|
||||
expect(recreatedBar.getAttribute("data-ryd-liked")).toBe("true");
|
||||
});
|
||||
|
||||
test("mutates only the selected current watch tree when stale duplicate IDs come first", () => {
|
||||
const currentButtons = document.querySelector('[data-watch-buttons="BBBBBBBBBBB"]');
|
||||
expect(currentButtons.closest("#top-row")).toBe(document.querySelector('[data-watch-row="BBBBBBBBBBB"]'));
|
||||
@@ -160,6 +188,7 @@ describe("rate-bar visual ownership", () => {
|
||||
expect(currentButtons.querySelector("#ryd-bar").style.width).toBe("85.99%");
|
||||
|
||||
getVideoId.mockReturnValue("AAAAAAAAAAA");
|
||||
isVideoLiked.mockReturnValue(true);
|
||||
expect(hasUsableRateBar(currentButtons)).toBe(false);
|
||||
createRateBar(3_591, 1_409);
|
||||
|
||||
@@ -168,6 +197,7 @@ describe("rate-bar visual ownership", () => {
|
||||
expect(staleWrapper.isConnected).toBe(false);
|
||||
expect(currentWrapper).not.toBe(staleWrapper);
|
||||
expect(currentWrapper.getAttribute("data-ryd-video-id")).toBe("AAAAAAAAAAA");
|
||||
expect(currentWrapper.querySelector("#ryd-bar-container").getAttribute("data-ryd-liked")).toBe("true");
|
||||
expect(currentButtons.querySelector("#ryd-bar").style.width).toBe("71.82%");
|
||||
expect(hasUsableRateBar(currentButtons)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -20,10 +20,10 @@ describe("Belarusian localization", () => {
|
||||
);
|
||||
|
||||
it.each(dynamicMessages.filter((key) => key.startsWith("discussion_")))(
|
||||
"uses the English fallback and substitutions for %s",
|
||||
"uses the Belarusian translation and substitutions for %s",
|
||||
(key) => {
|
||||
const substitutions = ["First value", "Second value"];
|
||||
const expected = english[key].message.replace(/\$(\d+)/g, (_, index) => substitutions[Number(index) - 1]);
|
||||
const expected = belarusian[key].message.replace(/\$(\d+)/g, (_, index) => substitutions[Number(index) - 1]);
|
||||
expect(discussionText(key.slice("discussion_".length), substitutions, "be")).toBe(expected);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
} from "../../common/shorts-control-readiness";
|
||||
|
||||
const buttonsVideoOwnership = new WeakMap();
|
||||
const createdDislikeTextTypography = new WeakMap();
|
||||
const COUNT_TYPOGRAPHY_ATTRIBUTE = "data-ryd-count-typography";
|
||||
const COUNT_TYPOGRAPHY_PROPERTIES = ["font-size", "font-weight", "font-family", "line-height"];
|
||||
const SYNTHETIC_SHORTS_DISLIKE_SELECTOR = "[data-ryd-synthetic-shorts-dislike]";
|
||||
const SHORTS_DISLIKE_ICON_PATH =
|
||||
"m8.482 1.5.294.005a9.01 9.01 0 013.918 1.04l.257.143.203.116c.17.097.357.16.55.185l.194.012h1.477l.115.006c.53.054.95.475 1.004 1.005l.006.114v4.499c0 .621-.504 1.125-1.125 1.125h-1.343a.75.75 0 00-.66.395l-.048.107-2.24 6.402a.75.75 0 01-.832.491l-.78-.13a3 3 0 01-2.439-3.587L7.5 11.25H4.454a2.749 2.749 0 01-2.683-2.151 2.762 2.762 0 01.479-2.237l-.016-.065A2.862 2.862 0 013 4.125v-.032c0-.227.037-.453.108-.668l.08-.211A2.816 2.816 0 015.78 1.5h2.703ZM5.78 3c-.566 0-1.069.362-1.248.9a.613.613 0 00-.031.193v.654l-.44.44c-.333.332-.47.813-.364 1.271l.015.065.157.675-.413.557a1.248 1.248 0 00.999 1.995H7.5a1.501 1.501 0 011.467 1.815L8.5 13.742a1.5 1.5 0 001.22 1.794l.157.027 2.031-5.806a2.25 2.25 0 012.124-1.507H15V4.501h-1.102a3.001 3.001 0 01-1.489-.396l-.202-.116A7.504 7.504 0 008.482 3H5.78Z";
|
||||
@@ -560,6 +563,99 @@ function updateDislikeButtonShape(dislikeButton) {
|
||||
}
|
||||
}
|
||||
|
||||
function getNativeCountTypography(likeButton) {
|
||||
const root = getLikeTextContainer(likeButton);
|
||||
if (!root?.isConnected) return undefined;
|
||||
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
||||
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
||||
if (!/\p{N}/u.test(node.data)) continue;
|
||||
const element = node.parentElement;
|
||||
if (element.closest("[hidden], [inert]")) continue;
|
||||
const rect = element.getBoundingClientRect();
|
||||
if (rect.width <= 1 || rect.height <= 1) continue;
|
||||
const typography = window.getComputedStyle(element);
|
||||
let visible = true;
|
||||
for (let current = element; current && root.contains(current); current = current.parentElement) {
|
||||
const style = current === element ? typography : window.getComputedStyle(current);
|
||||
if (
|
||||
style.display === "none" ||
|
||||
style.visibility === "hidden" ||
|
||||
style.visibility === "collapse" ||
|
||||
Number.parseFloat(style.opacity) === 0 ||
|
||||
style.clip === "rect(0px, 0px, 0px, 0px)" ||
|
||||
style.clipPath === "inset(50%)" ||
|
||||
style.clipPath === "inset(100%)"
|
||||
) {
|
||||
visible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (visible) return typography;
|
||||
}
|
||||
}
|
||||
|
||||
function getCreatedDislikeTextTypography(textContainer) {
|
||||
const existing = createdDislikeTextTypography.get(textContainer);
|
||||
if (existing) return existing;
|
||||
const saved = textContainer?.getAttribute(COUNT_TYPOGRAPHY_ATTRIBUTE);
|
||||
if (saved == null) return undefined;
|
||||
try {
|
||||
const entries = JSON.parse(saved);
|
||||
if (!entries || typeof entries !== "object" || Array.isArray(entries)) return undefined;
|
||||
const overrides = new Map();
|
||||
for (const property of COUNT_TYPOGRAPHY_PROPERTIES) {
|
||||
const entry = entries[property];
|
||||
if (entry === undefined) continue;
|
||||
if (
|
||||
!entry ||
|
||||
typeof entry.value !== "string" ||
|
||||
typeof entry.computedValue !== "string" ||
|
||||
(entry.priority !== "" && entry.priority !== "important")
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
overrides.set(property, { value: entry.value, priority: entry.priority, computedValue: entry.computedValue });
|
||||
}
|
||||
createdDislikeTextTypography.set(textContainer, overrides);
|
||||
return overrides;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function refreshDislikeTextTypography(likeButton = getLikeButton(), dislikeButton = getDislikeButton()) {
|
||||
const textContainer = findDislikeTextContainer(dislikeButton, getNativeButton(dislikeButton));
|
||||
const overrides = getCreatedDislikeTextTypography(textContainer);
|
||||
if (!overrides) return;
|
||||
const nativeTypography = getNativeCountTypography(likeButton);
|
||||
if (!nativeTypography && overrides.size === 0) return;
|
||||
const currentTypography = window.getComputedStyle(textContainer);
|
||||
const currentValues = COUNT_TYPOGRAPHY_PROPERTIES.map((property) => currentTypography.getPropertyValue(property));
|
||||
COUNT_TYPOGRAPHY_PROPERTIES.forEach((property, index) => {
|
||||
const value = nativeTypography?.getPropertyValue(property);
|
||||
const previous = overrides.get(property);
|
||||
if (previous && (!value || value === previous.computedValue)) {
|
||||
if (previous.value) textContainer.style.setProperty(property, previous.value, previous.priority);
|
||||
else textContainer.style.removeProperty(property);
|
||||
overrides.delete(property);
|
||||
} else if (value && value !== currentValues[index]) {
|
||||
if (!previous) {
|
||||
overrides.set(property, {
|
||||
value: textContainer.style.getPropertyValue(property),
|
||||
priority: textContainer.style.getPropertyPriority(property),
|
||||
computedValue: currentValues[index],
|
||||
});
|
||||
}
|
||||
textContainer.style.setProperty(property, value);
|
||||
}
|
||||
});
|
||||
// Cloned action bars retain our inline styles and need their original values for restoration.
|
||||
const saved = JSON.stringify(Object.fromEntries(overrides));
|
||||
if (textContainer.getAttribute(COUNT_TYPOGRAPHY_ATTRIBUTE) !== saved) {
|
||||
textContainer.setAttribute(COUNT_TYPOGRAPHY_ATTRIBUTE, saved);
|
||||
}
|
||||
}
|
||||
|
||||
function createDislikeTextContainer(controls = getButtonControls()) {
|
||||
const { dislikeButton, dislikeTextContainer, nativeDislikeButton, textContainerTemplate } = controls;
|
||||
if (dislikeTextContainer) return dislikeTextContainer;
|
||||
@@ -588,11 +684,15 @@ function createDislikeTextContainer(controls = getButtonControls()) {
|
||||
textContainer.innerText = "";
|
||||
nativeDislikeButton.insertBefore(textNodeClone, null);
|
||||
updateDislikeButtonShape(nativeDislikeButton);
|
||||
createdDislikeTextTypography.set(textContainer, new Map());
|
||||
textContainer.setAttribute(COUNT_TYPOGRAPHY_ATTRIBUTE, "{}");
|
||||
return textContainer;
|
||||
}
|
||||
|
||||
function getDislikeTextContainer(controls = getButtonControls()) {
|
||||
return controls.dislikeTextContainer ?? createDislikeTextContainer(controls);
|
||||
const textContainer = controls.dislikeTextContainer ?? createDislikeTextContainer(controls);
|
||||
refreshDislikeTextTypography(controls.likeButton, controls.dislikeButton);
|
||||
return textContainer;
|
||||
}
|
||||
|
||||
function checkForSignInButton() {
|
||||
@@ -618,6 +718,7 @@ export {
|
||||
hasRenderedBox,
|
||||
isSyntheticShortsDislike,
|
||||
markButtonsForVideo,
|
||||
refreshDislikeTextTypography,
|
||||
setSyntheticShortsDislikeEnabled,
|
||||
setSyntheticShortsDislikePressed,
|
||||
shortsControlSurfaceIsReadyForMutation,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @jest-environment jsdom */
|
||||
|
||||
const { extConfig } = require("./state");
|
||||
const { extConfig, refreshReactionPresentation } = require("./state");
|
||||
const {
|
||||
ensureSyntheticShortsDislikeButton,
|
||||
getButtonControls,
|
||||
@@ -13,6 +13,7 @@ const {
|
||||
hasRenderedBox,
|
||||
isSyntheticShortsDislike,
|
||||
markButtonsForVideo,
|
||||
refreshDislikeTextTypography,
|
||||
setSyntheticShortsDislikeEnabled,
|
||||
setSyntheticShortsDislikePressed,
|
||||
} = require("./buttons");
|
||||
@@ -42,6 +43,52 @@ function setBox(element, { height = 48, width = 320, x = 20, y = 20 } = {}) {
|
||||
});
|
||||
}
|
||||
|
||||
function typographyControls(nativeText) {
|
||||
document.body.innerHTML = `
|
||||
<style>
|
||||
.ytSpecButtonShapeNextButtonTextContent,
|
||||
.ytSpecButtonShapeNextButtonTextContent > span[role='text'] {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
font-family: Roboto, Arial, sans-serif;
|
||||
line-height: 40px;
|
||||
}
|
||||
like-button-view-model .fixture-digit {
|
||||
font-size: 21px;
|
||||
font-weight: 600;
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 21px;
|
||||
}
|
||||
like-button-view-model .fixture-large { font-size: 25px; line-height: 27px; }
|
||||
like-button-view-model .fixture-static { font-size: 18px; line-height: 24px; }
|
||||
.fixture-screen-reader { position: absolute; clip: rect(0px, 0px, 0px, 0px); }
|
||||
</style>
|
||||
<ytd-watch-flexy video-id="BBBBBBBBBBB">
|
||||
<ytd-menu-renderer class="ytd-watch-metadata">
|
||||
<div id="current">
|
||||
<like-button-view-model>
|
||||
<button aria-pressed="false">
|
||||
<div class="ytSpecButtonShapeNextButtonTextContent ytSpecButtonShapeNextElevatedContent">${nativeText}</div>
|
||||
</button>
|
||||
</like-button-view-model>
|
||||
<dislike-button-view-model>
|
||||
<button class="ytSpecButtonShapeNextIconButton" aria-pressed="false">
|
||||
<span class="ytSpecButtonShapeNextIcon"><svg width="24" height="24"><path d="M0 0"></path></svg></span>
|
||||
</button>
|
||||
</dislike-button-view-model>
|
||||
</div>
|
||||
</ytd-menu-renderer>
|
||||
</ytd-watch-flexy>`;
|
||||
const current = document.querySelector("#current");
|
||||
setBox(current);
|
||||
setNativeTextBoxes();
|
||||
return current;
|
||||
}
|
||||
|
||||
function setNativeTextBoxes() {
|
||||
document.querySelectorAll("like-button-view-model *").forEach((element) => setBox(element));
|
||||
}
|
||||
|
||||
describe("desktop watch button ownership", () => {
|
||||
beforeEach(() => {
|
||||
history.replaceState({}, "", "/watch?v=BBBBBBBBBBB");
|
||||
@@ -348,6 +395,126 @@ describe("desktop watch button ownership", () => {
|
||||
expect(dislike.querySelectorAll("#text[role='text']")).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("matches nested native digit typography without changing the native count or dislike icon", () => {
|
||||
const current = typographyControls(`
|
||||
<span hidden>999</span>
|
||||
<span class="fixture-screen-reader">999</span>
|
||||
<animated-rolling-number><animated-rolling-character class="fixture-digit" aria-hidden="true">2</animated-rolling-character></animated-rolling-number>`);
|
||||
const like = current.querySelector("like-button-view-model");
|
||||
const dislike = current.querySelector("dislike-button-view-model");
|
||||
const nativeContent = like.innerHTML;
|
||||
const nativeIcon = dislike.querySelector("svg").outerHTML;
|
||||
|
||||
const count = getDislikeTextContainer(getButtonControls(current));
|
||||
|
||||
expect(count.style.fontSize).toBe("21px");
|
||||
expect(count.style.fontWeight).toBe("600");
|
||||
expect(count.style.fontFamily).toBe("Arial, sans-serif");
|
||||
expect(count.style.lineHeight).toBe("21px");
|
||||
expect(like.innerHTML).toBe(nativeContent);
|
||||
expect(dislike.querySelector("svg").outerHTML).toBe(nativeIcon);
|
||||
expect(dislike.querySelectorAll("animated-rolling-number")).toHaveLength(0);
|
||||
expect(dislike.querySelector("button").classList.contains("ytSpecButtonShapeNextIconLeading")).toBe(true);
|
||||
|
||||
const observer = new MutationObserver(() => {});
|
||||
observer.observe(count, { attributes: true });
|
||||
expect(getDislikeTextContainer(getButtonControls(current))).toBe(count);
|
||||
refreshDislikeTextTypography(like, dislike);
|
||||
expect(observer.takeRecords()).toHaveLength(0);
|
||||
observer.disconnect();
|
||||
expect(dislike.querySelectorAll("#text[role='text']")).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("refreshes delayed native digits and restores ordinary typography on reused controls", () => {
|
||||
const current = typographyControls("254");
|
||||
const nativeText = current.querySelector("like-button-view-model .ytSpecButtonShapeNextButtonTextContent");
|
||||
const count = getDislikeTextContainer(getButtonControls(current));
|
||||
count.innerText = "42";
|
||||
expect(count.style.cssText).toBe("");
|
||||
|
||||
nativeText.innerHTML = '<animated-rolling-character class="fixture-digit">2</animated-rolling-character>';
|
||||
setNativeTextBoxes();
|
||||
refreshReactionPresentation();
|
||||
expect(count.style.fontSize).toBe("21px");
|
||||
|
||||
nativeText.firstElementChild.classList.add("fixture-large");
|
||||
refreshReactionPresentation();
|
||||
expect(count.style.fontSize).toBe("25px");
|
||||
expect(count.style.lineHeight).toBe("27px");
|
||||
|
||||
nativeText.textContent = "254";
|
||||
refreshReactionPresentation();
|
||||
expect(count.style.cssText).toBe("");
|
||||
expect(getDislikeTextContainer(getButtonControls(current))).toBe(count);
|
||||
expect(count.innerText).toBe("42");
|
||||
});
|
||||
|
||||
test.each(["ordinary", "missing"])(
|
||||
"restores original inline values and priorities after cloned controls receive %s native text",
|
||||
(nativeState) => {
|
||||
const originalInlineStyle = "font-size: 14px !important; line-height: 40px !important;";
|
||||
const current = typographyControls(
|
||||
`<span role="text" style="${originalInlineStyle}"><animated-rolling-character class="fixture-digit">2</animated-rolling-character></span>`,
|
||||
);
|
||||
const count = getDislikeTextContainer(getButtonControls(current));
|
||||
count.textContent = "42";
|
||||
expect(count.style.fontSize).toBe("21px");
|
||||
|
||||
const clonedControls = current.cloneNode(true);
|
||||
current.replaceWith(clonedControls);
|
||||
setBox(clonedControls);
|
||||
const nativeText = clonedControls.querySelector("like-button-view-model .ytSpecButtonShapeNextButtonTextContent");
|
||||
nativeText.querySelector(".fixture-digit").classList.add("fixture-large");
|
||||
setNativeTextBoxes();
|
||||
const clonedCount = getDislikeTextContainer(getButtonControls(clonedControls));
|
||||
expect(clonedCount).not.toBe(count);
|
||||
expect(clonedCount.style.fontSize).toBe("25px");
|
||||
expect(clonedCount.style.lineHeight).toBe("27px");
|
||||
|
||||
nativeText.textContent = nativeState === "ordinary" ? "254" : "";
|
||||
refreshReactionPresentation();
|
||||
expect(clonedCount.style.cssText).toBe(originalInlineStyle);
|
||||
expect(clonedCount.style.getPropertyPriority("font-size")).toBe("important");
|
||||
expect(clonedCount.style.getPropertyPriority("line-height")).toBe("important");
|
||||
expect(clonedCount.textContent).toBe("42");
|
||||
|
||||
const observer = new MutationObserver(() => {});
|
||||
observer.observe(clonedCount, { attributes: true });
|
||||
expect(getDislikeTextContainer(getButtonControls(clonedControls))).toBe(clonedCount);
|
||||
refreshReactionPresentation();
|
||||
expect(observer.takeRecords()).toHaveLength(0);
|
||||
observer.disconnect();
|
||||
expect(clonedControls.querySelectorAll("dislike-button-view-model #text[role='text']")).toHaveLength(1);
|
||||
},
|
||||
);
|
||||
|
||||
test("matches native typography scoped to the Like ancestor for ordinary text too", () => {
|
||||
const current = typographyControls('<span class="fixture-static" role="text">254</span>');
|
||||
const count = getDislikeTextContainer(getButtonControls(current));
|
||||
|
||||
expect(count.style.fontSize).toBe("18px");
|
||||
expect(count.style.lineHeight).toBe("24px");
|
||||
expect(count.style.fontWeight).toBe("");
|
||||
expect(count.style.fontFamily).toBe("");
|
||||
});
|
||||
|
||||
test("preserves matching cloned inline styles and existing native dislike text", () => {
|
||||
const current = typographyControls('<span role="text" style="font-size: 18px; line-height: 24px">254</span>');
|
||||
const nativeCount = current.querySelector("like-button-view-model span[role='text']");
|
||||
const count = getDislikeTextContainer(getButtonControls(current));
|
||||
expect(count.style.cssText).toBe(nativeCount.style.cssText);
|
||||
|
||||
const dislike = current.querySelector("dislike-button-view-model");
|
||||
dislike.querySelector(".ytSpecButtonShapeNextButtonTextContent").remove();
|
||||
const existing = document.createElement("span");
|
||||
existing.setAttribute("role", "text");
|
||||
existing.style.fontSize = "16px";
|
||||
dislike.querySelector("button").appendChild(existing);
|
||||
expect(getDislikeTextContainer(getButtonControls(current))).toBe(existing);
|
||||
refreshReactionPresentation();
|
||||
expect(existing.style.cssText).toBe("font-size: 16px;");
|
||||
});
|
||||
|
||||
test("inserts one owned Shorts Dislike after Like instead of treating Comments as Dislike", () => {
|
||||
history.replaceState({}, "", "/shorts/BBBBBBBBBBB");
|
||||
document.body.innerHTML = `
|
||||
|
||||
@@ -32,7 +32,7 @@ test("changes custom colors in an open tab and refreshes the current video's pre
|
||||
|
||||
test("ignores custom color events from other storage areas", () => {
|
||||
storageChangeHandler({ customColors: { newValue: { light: { like: "#123456" } } } }, "local");
|
||||
expect(getColorFromTheme(true)).toBe("#008000");
|
||||
expect(getColorFromTheme(true)).toBe("#007600");
|
||||
expect(createRateBar).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -69,6 +69,6 @@ test("theme attribute changes repaint current controls without fetching counts",
|
||||
expect(createRateBar).toHaveBeenCalledTimes(1);
|
||||
document.documentElement.removeAttribute("dark");
|
||||
await Promise.resolve();
|
||||
expect(getColorFromTheme(true)).toBe("#008000");
|
||||
expect(getColorFromTheme(true)).toBe("#007600");
|
||||
expect(createRateBar).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { initDiscussion } from "./index";
|
||||
import { NATIVE_STATE_REQUEST, NATIVE_STATE_ATTRIBUTE } from "./detector";
|
||||
import { threadUrl } from "./dom";
|
||||
import { discussionText } from "./localize";
|
||||
|
||||
const VIDEO = "abcdefghijk";
|
||||
const OTHER = "zyxwvutsrqp";
|
||||
@@ -201,12 +202,30 @@ test("restoring a cached page recreates the panel with a fresh request scope", a
|
||||
expect(document.querySelectorAll("#ryd-discussion-panel")).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("switching YouTube language refreshes the panel language", async () => {
|
||||
test.each(["ru", "be-BY", "de-DE", "pt_BR", "sv_SE", "zh-Hans", "zh-Hant"])(
|
||||
"switching YouTube language to %s refreshes the panel language",
|
||||
async (language) => {
|
||||
feature = initDiscussion({ request });
|
||||
await flush();
|
||||
const previousPanel = document.getElementById("ryd-discussion-panel");
|
||||
document.documentElement.lang = language;
|
||||
await flush();
|
||||
jest.advanceTimersByTime(150);
|
||||
await flush();
|
||||
expect(document.getElementById("ryd-discussion-panel")).not.toBe(previousPanel);
|
||||
expect(document.querySelector(".ryd-discussion-title").textContent).toBe(discussionText("title", [], language));
|
||||
},
|
||||
);
|
||||
|
||||
test("switching between Chinese scripts refreshes an existing translated panel", async () => {
|
||||
document.documentElement.lang = "zh-Hans";
|
||||
feature = initDiscussion({ request });
|
||||
await flush();
|
||||
document.documentElement.lang = "ru";
|
||||
const previousPanel = document.getElementById("ryd-discussion-panel");
|
||||
document.documentElement.lang = "zh-Hant";
|
||||
await feature.refresh();
|
||||
expect(document.querySelector(".ryd-discussion-title").textContent).toBe("Комментарии RYD");
|
||||
expect(document.getElementById("ryd-discussion-panel")).not.toBe(previousPanel);
|
||||
expect(document.querySelector(".ryd-discussion-title").textContent).toBe(discussionText("title", [], "zh-TW"));
|
||||
});
|
||||
|
||||
test("an opened Shorts drawer survives a transiently hidden and replaced same-video container", async () => {
|
||||
|
||||
@@ -1,13 +1,75 @@
|
||||
import azerbaijani from "../../_locales/az/messages.json";
|
||||
import belarusian from "../../_locales/be/messages.json";
|
||||
import czech from "../../_locales/cs/messages.json";
|
||||
import german from "../../_locales/de/messages.json";
|
||||
import greek from "../../_locales/el/messages.json";
|
||||
import english from "../../_locales/en/messages.json";
|
||||
import spanish from "../../_locales/es/messages.json";
|
||||
import french from "../../_locales/fr/messages.json";
|
||||
import hungarian from "../../_locales/hu/messages.json";
|
||||
import indonesian from "../../_locales/id/messages.json";
|
||||
import italian from "../../_locales/it/messages.json";
|
||||
import japanese from "../../_locales/ja/messages.json";
|
||||
import korean from "../../_locales/ko/messages.json";
|
||||
import dutch from "../../_locales/nl/messages.json";
|
||||
import polish from "../../_locales/pl/messages.json";
|
||||
import portuguese from "../../_locales/pt_BR/messages.json";
|
||||
import russian from "../../_locales/ru/messages.json";
|
||||
import slovenian from "../../_locales/sl/messages.json";
|
||||
import swedish from "../../_locales/sv_SE/messages.json";
|
||||
import turkish from "../../_locales/tr/messages.json";
|
||||
import ukrainian from "../../_locales/uk/messages.json";
|
||||
import vietnamese from "../../_locales/vi/messages.json";
|
||||
import simplifiedChinese from "../../_locales/zh_CN/messages.json";
|
||||
import traditionalChinese from "../../_locales/zh_TW/messages.json";
|
||||
|
||||
const catalogs = {
|
||||
az: azerbaijani,
|
||||
be: belarusian,
|
||||
cs: czech,
|
||||
de: german,
|
||||
el: greek,
|
||||
en: english,
|
||||
es: spanish,
|
||||
fr: french,
|
||||
hu: hungarian,
|
||||
id: indonesian,
|
||||
it: italian,
|
||||
ja: japanese,
|
||||
ko: korean,
|
||||
nl: dutch,
|
||||
pl: polish,
|
||||
"pt-BR": portuguese,
|
||||
ru: russian,
|
||||
sl: slovenian,
|
||||
"sv-SE": swedish,
|
||||
tr: turkish,
|
||||
uk: ukrainian,
|
||||
vi: vietnamese,
|
||||
"zh-CN": simplifiedChinese,
|
||||
"zh-TW": traditionalChinese,
|
||||
};
|
||||
|
||||
export function discussionLanguage(language = document.documentElement.lang || navigator.language) {
|
||||
return /^ru(?:-|$)/i.test(language || "") ? "ru" : "en";
|
||||
if (typeof language !== "string") return "en";
|
||||
try {
|
||||
const locale = new Intl.Locale(language.trim().replace(/_/g, "-"));
|
||||
if (locale.language === "zh") {
|
||||
if (locale.script === "Hans") return "zh-CN";
|
||||
if (locale.script === "Hant" || ["TW", "HK", "MO"].includes(locale.region)) return "zh-TW";
|
||||
return "zh-CN";
|
||||
}
|
||||
if (locale.language === "pt") return "pt-BR";
|
||||
if (locale.language === "sv") return "sv-SE";
|
||||
return catalogs[locale.language] ? locale.language : "en";
|
||||
} catch {
|
||||
return "en";
|
||||
}
|
||||
}
|
||||
|
||||
export function discussionText(key, substitutions = [], language) {
|
||||
const name = `discussion_${key}`;
|
||||
const catalog = discussionLanguage(language) === "ru" ? russian : english;
|
||||
const catalog = catalogs[discussionLanguage(language)];
|
||||
const text = catalog[name]?.message || english[name]?.message || key;
|
||||
return text.replace(/\$(\d+)/g, (_, number) => String(substitutions[Number(number) - 1] ?? ""));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/** @jest-environment jsdom */
|
||||
|
||||
import { discussionError, discussionLanguage, discussionText } from "./localize";
|
||||
import { shortDate } from "./dom";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const localeRoot = path.resolve(__dirname, "../../_locales");
|
||||
const catalogues = fs.readdirSync(localeRoot).map((code) => [code, require(`${localeRoot}/${code}/messages.json`)]);
|
||||
const english = require("../../_locales/en/messages.json");
|
||||
const german = require("../../_locales/de/messages.json");
|
||||
const dynamicKeys = Object.keys(english).filter(
|
||||
(key) => key.startsWith("discussion_") && /\$\d+/.test(english[key].message),
|
||||
);
|
||||
|
||||
afterEach(() => {
|
||||
document.documentElement.lang = "";
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
test.each(catalogues)("selects the %s catalogue with a locale suitable for dates and counts", (code, catalogue) => {
|
||||
const language = discussionLanguage(code);
|
||||
expect(language).toBe(code.replace(/_/g, "-"));
|
||||
expect(discussionText("title", [], code)).toBe(catalogue.discussion_title.message);
|
||||
expect(() => (1234).toLocaleString(language)).not.toThrow();
|
||||
expect(() => shortDate("2026-10-18T12:00:00Z", language)).not.toThrow();
|
||||
});
|
||||
|
||||
test.each(catalogues)("substitutes the dynamic discussion messages from %s", (code, catalogue) => {
|
||||
const substitutions = ["First value", "Second value"];
|
||||
for (const key of dynamicKeys) {
|
||||
const expected = catalogue[key].message.replace(/\$(\d+)/g, (_, number) => substitutions[Number(number) - 1]);
|
||||
expect(discussionText(key.slice("discussion_".length), substitutions, code)).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
test.each([
|
||||
["DE-de", "de"],
|
||||
["be_BY", "be"],
|
||||
["ru_RU", "ru"],
|
||||
["es-419", "es"],
|
||||
["in-ID", "id"],
|
||||
["pt", "pt-BR"],
|
||||
[" pt_br ", "pt-BR"],
|
||||
["pt-PT", "pt-BR"],
|
||||
["sv", "sv-SE"],
|
||||
["SV_se", "sv-SE"],
|
||||
["sv-FI", "sv-SE"],
|
||||
["zh", "zh-CN"],
|
||||
["zh_cn", "zh-CN"],
|
||||
["ZH_tw", "zh-TW"],
|
||||
["zh-SG", "zh-CN"],
|
||||
["zh-HK", "zh-TW"],
|
||||
["zh-MO", "zh-TW"],
|
||||
["zh-Hans", "zh-CN"],
|
||||
["zh-Hant", "zh-TW"],
|
||||
["zh-Hans-TW", "zh-CN"],
|
||||
["zh-Hant-CN", "zh-TW"],
|
||||
["zh-TW-u-nu-hanidec", "zh-TW"],
|
||||
])("normalizes %s to %s", (input, expected) => {
|
||||
expect(discussionLanguage(input)).toBe(expected);
|
||||
expect(discussionText("title", [], input)).toBe(discussionText("title", [], expected));
|
||||
});
|
||||
|
||||
test.each(["", "xx", "ar-SA", "not a locale", "ru--RU", "ru!", null, 42])(
|
||||
"falls back to English for %j",
|
||||
(language) => {
|
||||
expect(discussionLanguage(language)).toBe("en");
|
||||
expect(discussionText("title", [], language)).toBe(english.discussion_title.message);
|
||||
},
|
||||
);
|
||||
|
||||
test("prefers YouTube's language over the browser and observes later language changes", () => {
|
||||
jest.spyOn(navigator, "language", "get").mockReturnValue("ru-RU");
|
||||
document.documentElement.lang = "de-DE";
|
||||
expect(discussionLanguage()).toBe("de");
|
||||
expect(discussionText("title")).toBe(german.discussion_title.message);
|
||||
document.documentElement.lang = "zh-Hant";
|
||||
expect(discussionLanguage()).toBe("zh-TW");
|
||||
document.documentElement.lang = "xx";
|
||||
expect(discussionLanguage()).toBe("en");
|
||||
document.documentElement.lang = "";
|
||||
expect(discussionLanguage()).toBe("ru");
|
||||
});
|
||||
|
||||
test.each([undefined, { message: "" }])("falls back to English when a translated message is %j", (entry) => {
|
||||
const original = german.discussion_characters;
|
||||
try {
|
||||
german.discussion_characters = entry;
|
||||
expect(discussionText("characters", [12, 2000], "de")).toBe("12 / 2000");
|
||||
} finally {
|
||||
german.discussion_characters = original;
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps unknown keys and preserves literal and missing substitution values", () => {
|
||||
expect(discussionText("unknownKey", [], "de")).toBe("unknownKey");
|
||||
expect(discussionText("characters", [0, "$1"], "en")).toBe("0 / $1");
|
||||
expect(discussionText("characters", [12], "en")).toBe("12 / ");
|
||||
});
|
||||
|
||||
test.each([
|
||||
[{ code: "invalid_session" }, "signInRequired"],
|
||||
[{ code: "membership_inactive" }, "tierRequired"],
|
||||
[{ code: "made_for_kids" }, "unavailable"],
|
||||
[{ code: "comment_not_found" }, "commentUnavailable"],
|
||||
[{ code: "nickname_taken" }, "nicknameTaken"],
|
||||
[{ code: "conflict", status: 403 }, "conflict"],
|
||||
[{ status: 401 }, "signInRequired"],
|
||||
[{ status: 403 }, "forbidden"],
|
||||
[{ status: 429 }, "rateLimited"],
|
||||
[{ code: "unknown", status: 500 }, "error"],
|
||||
[null, "error"],
|
||||
])("preserves localized error mapping for %j", (error, key) => {
|
||||
document.documentElement.lang = "de";
|
||||
expect(discussionError(error)).toBe(discussionText(key, [], "de"));
|
||||
});
|
||||
@@ -112,7 +112,7 @@ function observeReactionPresentation(likeButton, dislikeButton) {
|
||||
presentationObserver.disconnect();
|
||||
const options = {
|
||||
attributes: true,
|
||||
attributeFilter: ["aria-label", "aria-pressed"],
|
||||
attributeFilter: ["aria-label", "aria-pressed", "class"],
|
||||
characterData: true,
|
||||
childList: true,
|
||||
subtree: true,
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
NEUTRAL_STATE,
|
||||
} from "./state";
|
||||
|
||||
const { createRateBar: renderRateBar } = jest.requireActual("./bar");
|
||||
const innerTextDescriptor = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerText");
|
||||
|
||||
beforeAll(() => {
|
||||
@@ -148,6 +149,89 @@ test("native count markup is untouched when reformatting is off", async () => {
|
||||
expect(node.data).toBe("731");
|
||||
});
|
||||
|
||||
test("an initially liked video exposes its native state as soon as the bar is created", () => {
|
||||
const controls = mount();
|
||||
controls.nativeLikeButton.setAttribute("aria-pressed", "true");
|
||||
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
|
||||
expect(document.querySelector("#ryd-bar-container").getAttribute("data-ryd-liked")).toBe("true");
|
||||
});
|
||||
|
||||
test("native like, unlike, and dislike transitions update the CSS hook without changing bar styling", async () => {
|
||||
const controls = mount();
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
const bar = document.querySelector("#ryd-bar-container");
|
||||
const barStyle = bar.getAttribute("style");
|
||||
const fillStyle = bar.querySelector("#ryd-bar").getAttribute("style");
|
||||
expect(bar.getAttribute("data-ryd-liked")).toBe("false");
|
||||
refreshReactionPresentation();
|
||||
createRateBar.mockClear();
|
||||
|
||||
for (const [liked, disliked] of [
|
||||
[true, false],
|
||||
[false, false],
|
||||
[true, false],
|
||||
[false, true],
|
||||
]) {
|
||||
controls.nativeLikeButton.setAttribute("aria-pressed", String(liked));
|
||||
controls.nativeDislikeButton.setAttribute("aria-pressed", String(disliked));
|
||||
await flushMutations();
|
||||
|
||||
expect(bar.getAttribute("data-ryd-liked")).toBe(String(liked));
|
||||
expect(bar.getAttribute("style")).toBe(barStyle);
|
||||
expect(bar.querySelector("#ryd-bar").getAttribute("style")).toBe(fillStyle);
|
||||
}
|
||||
expect(storedData.likes).toBe(730);
|
||||
expect(createRateBar).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("a replaced native like button refreshes the bar's liked hook", async () => {
|
||||
const controls = mount();
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
const replacement = controls.nativeLikeButton.cloneNode(true);
|
||||
replacement.setAttribute("aria-pressed", "true");
|
||||
|
||||
controls.nativeLikeButton.replaceWith(replacement);
|
||||
await flushMutations();
|
||||
|
||||
expect(document.querySelector("#ryd-bar-container").getAttribute("data-ryd-liked")).toBe("true");
|
||||
});
|
||||
|
||||
test("native active-class transitions refresh the bar's liked hook", async () => {
|
||||
const controls = mount();
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
const bar = document.querySelector("#ryd-bar-container");
|
||||
|
||||
controls.likeButton.classList.add("style-default-active");
|
||||
await flushMutations();
|
||||
expect(bar.getAttribute("data-ryd-liked")).toBe("true");
|
||||
|
||||
controls.likeButton.classList.remove("style-default-active");
|
||||
await flushMutations();
|
||||
expect(bar.getAttribute("data-ryd-liked")).toBe("false");
|
||||
});
|
||||
|
||||
test("navigation on reused controls replaces the outgoing bar's liked state", async () => {
|
||||
const controls = mount();
|
||||
controls.nativeLikeButton.setAttribute("aria-pressed", "true");
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
const outgoingBar = document.querySelector("#ryd-bar-container");
|
||||
expect(outgoingBar.getAttribute("data-ryd-liked")).toBe("true");
|
||||
|
||||
history.replaceState({}, "", "/watch?v=zyxwvutsrqp");
|
||||
Object.assign(storedData, { videoId: "zyxwvutsrqp", likes: 3591, dislikes: 1409 });
|
||||
controls.nativeLikeButton.setAttribute("aria-pressed", "false");
|
||||
renderRateBar(storedData.likes, storedData.dislikes);
|
||||
const destinationBar = document.querySelector("#ryd-bar-container");
|
||||
expect(destinationBar).not.toBe(outgoingBar);
|
||||
expect(destinationBar.getAttribute("data-ryd-liked")).toBe("false");
|
||||
|
||||
controls.nativeLikeButton.setAttribute("aria-pressed", "true");
|
||||
await flushMutations();
|
||||
expect(destinationBar.getAttribute("data-ryd-liked")).toBe("true");
|
||||
});
|
||||
|
||||
test("later native labels refresh stored likes and the rate bar when reformatting is off", async () => {
|
||||
const controls = mount();
|
||||
refreshReactionPresentation();
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getButtons,
|
||||
getLikeTextContainer,
|
||||
getDislikeTextContainer,
|
||||
refreshDislikeTextTypography,
|
||||
isSyntheticShortsDislike,
|
||||
setSyntheticShortsDislikeEnabled,
|
||||
setSyntheticShortsDislikePressed,
|
||||
@@ -283,6 +284,12 @@ function setLikes(likesCount) {
|
||||
}
|
||||
|
||||
function refreshReactionPresentation() {
|
||||
refreshDislikeTextTypography();
|
||||
const rateBar = getButtons()?.querySelector("#ryd-bar-container");
|
||||
if (rateBar) {
|
||||
const liked = String(isVideoLiked());
|
||||
if (rateBar.getAttribute("data-ryd-liked") !== liked) rateBar.setAttribute("data-ryd-liked", liked);
|
||||
}
|
||||
const nativeLikeCount = readNativeLikeCount();
|
||||
const nativeLikes = nativeLikeCount?.likes ?? false;
|
||||
if (nativeLikes > 0 && nativeLikeCount.videoId === storedData.videoId && !nativeLikeCount.presented) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const DEFAULT_CUSTOM_COLORS = Object.freeze({
|
||||
light: Object.freeze({ like: "#008000", dislike: "#b300b3" }),
|
||||
dark: Object.freeze({ like: "#00d000", dislike: "#ff66ff" }),
|
||||
light: Object.freeze({ like: "#007600", dislike: "#b300b3" }),
|
||||
dark: Object.freeze({ like: "#00d000", dislike: "#ff77ff" }),
|
||||
});
|
||||
|
||||
function normalizeCustomColors(value) {
|
||||
|
||||
@@ -24,10 +24,10 @@ test.each([
|
||||
|
||||
test("Hibiscus uses distinct light and dark palettes without reading custom settings", () => {
|
||||
const custom = { light: { like: "#123456", dislike: "#654321" } };
|
||||
expect(getThemeColor("hibiscus", true, false, custom)).toBe("#008000");
|
||||
expect(getThemeColor("hibiscus", true, false, custom)).toBe("#007600");
|
||||
expect(getThemeColor("hibiscus", false, false, custom)).toBe("#b300b3");
|
||||
expect(getThemeColor("hibiscus", true, true, custom)).toBe("#00d000");
|
||||
expect(getThemeColor("hibiscus", false, true, custom)).toBe("#ff66ff");
|
||||
expect(getThemeColor("hibiscus", false, true, custom)).toBe("#ff77ff");
|
||||
});
|
||||
|
||||
test("custom colors use the matching theme and recover each malformed field independently", () => {
|
||||
@@ -43,7 +43,7 @@ test("custom colors use the matching theme and recover each malformed field inde
|
||||
});
|
||||
const colors = normalizeCustomColors();
|
||||
colors.light.like = "#ffffff";
|
||||
expect(normalizeCustomColors().light.like).toBe("#008000");
|
||||
expect(normalizeCustomColors().light.like).toBe("#007600");
|
||||
});
|
||||
|
||||
test.each(["", "true", "false"])("recognizes dark attribute by its presence (%s)", (value) => {
|
||||
@@ -92,3 +92,15 @@ test.each([
|
||||
expect((levels[0] + 0.05) / (levels[1] + 0.05)).toBeGreaterThanOrEqual(3);
|
||||
}
|
||||
});
|
||||
|
||||
test.each([
|
||||
[false, "#f2f2f2"],
|
||||
[false, "#e5e5e5"],
|
||||
[true, "#272727"],
|
||||
[true, "#3f3f3f"],
|
||||
])("Hibiscus text has at least 4.5:1 contrast with idle and hovered buttons (dark=%s, %s)", (dark, surface) => {
|
||||
for (const isLike of [true, false]) {
|
||||
const levels = [luminance(getThemeColor("hibiscus", isLike, dark)), luminance(surface)].sort((a, b) => b - a);
|
||||
expect((levels[0] + 0.05) / (levels[1] + 0.05)).toBeGreaterThanOrEqual(4.5);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const { expect } = require("@playwright/test");
|
||||
|
||||
const HIBISCUS = Object.freeze({
|
||||
light: { like: "#008000", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff66ff" },
|
||||
light: { like: "#007600", dislike: "#b300b3" },
|
||||
dark: { like: "#00d000", dislike: "#ff77ff" },
|
||||
});
|
||||
const CUSTOM_COLORS = Object.freeze({
|
||||
light: { like: "#006633", dislike: "#990099" },
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
const path = require("node:path");
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { VIDEO_A, VIDEO_B } = require("../../UserScript/e2e/harness");
|
||||
const { HermeticExtensionArtifactAdapter, startHermeticApiServer } = require("../hermetic-artifact-smoke");
|
||||
|
||||
const EXTENSION_ARTIFACT = path.resolve(
|
||||
process.env.RYD_EXTENSION_ARTIFACT || path.join(__dirname, "../../combined/dist/chrome"),
|
||||
);
|
||||
const LIKE_TEXT = '[data-fixture-role="like"] .ytSpecButtonShapeNextButtonTextContent';
|
||||
const DISLIKE_TEXT = '[data-fixture-role="dislike"] #text';
|
||||
|
||||
async function installCounterTypography(context, nestedSemanticSpan) {
|
||||
await context.addInitScript((nested) => {
|
||||
if (location.hostname !== "www.youtube.com") return;
|
||||
document.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
body { color: #17212b; background: #fff; }
|
||||
body.fixture-dark { color: #f4f5f6; background: #15191d; }
|
||||
[data-fixture-role] button { color: inherit; background: #e6e9ed; font: 500 14px/40px Arial, sans-serif; }
|
||||
body.fixture-dark [data-fixture-role] button { background: #272727; }
|
||||
[data-fixture-role="like"] .fixture-digit { font: 600 21px/24px Georgia, serif; }
|
||||
[data-fixture-role="like"].fixture-compact .fixture-digit { font: 500 17px/22px Arial, sans-serif; }
|
||||
.fixture-accessible-count { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); font-size: 32px; }
|
||||
`;
|
||||
document.head.append(style);
|
||||
const template = document.querySelector('[data-fixture-role="like"] .ytSpecButtonShapeNextButtonTextContent');
|
||||
const digits = `<span hidden>999</span><span class="fixture-accessible-count">300 likes</span><span class="fixture-digit">300</span>`;
|
||||
template.innerHTML = nested ? `<span role="text">${digits}</span>` : digits;
|
||||
// Exercise the reaction observer without the separate smartimation observer.
|
||||
const smartimation = document.querySelector("yt-smartimation");
|
||||
smartimation.replaceWith(...smartimation.childNodes);
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
}, nestedSemanticSpan);
|
||||
}
|
||||
|
||||
async function readTypography(page) {
|
||||
return page.evaluate(
|
||||
({ likeSelector, dislikeSelector }) => {
|
||||
const like = document.querySelector(`${likeSelector} .fixture-digit`) || document.querySelector(likeSelector);
|
||||
const dislike = document.querySelector(dislikeSelector);
|
||||
const read = (element) => {
|
||||
const style = getComputedStyle(element);
|
||||
return {
|
||||
fontSize: style.fontSize,
|
||||
fontFamily: style.fontFamily,
|
||||
fontWeight: style.fontWeight,
|
||||
lineHeight: style.lineHeight,
|
||||
color: style.color,
|
||||
};
|
||||
};
|
||||
return { like: read(like), dislike: read(dislike) };
|
||||
},
|
||||
{ likeSelector: LIKE_TEXT, dislikeSelector: DISLIKE_TEXT },
|
||||
);
|
||||
}
|
||||
|
||||
for (const nestedSemanticSpan of [false, true]) {
|
||||
test(`generated extension matches nested counter typography with semantic span ${nestedSemanticSpan}`, async ({}, testInfo) => {
|
||||
const apiServer = await startHermeticApiServer();
|
||||
const adapter = new HermeticExtensionArtifactAdapter({
|
||||
apiServer,
|
||||
artifactDirectory: EXTENSION_ARTIFACT,
|
||||
backendOptions: {
|
||||
countsByVideo: { [VIDEO_A]: { likes: 300, dislikes: 100 }, [VIDEO_B]: { likes: 400, dislikes: 80 } },
|
||||
fixture: { nativeDislikeText: false, roleAttribute: "data-fixture-role" },
|
||||
},
|
||||
});
|
||||
try {
|
||||
await adapter.start();
|
||||
await installCounterTypography(adapter.context, nestedSemanticSpan);
|
||||
await adapter.openWatch(VIDEO_A);
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveText("100");
|
||||
await expect
|
||||
.poll(async () => (await readTypography(adapter.page)).dislike)
|
||||
.toEqual((await readTypography(adapter.page)).like);
|
||||
expect((await readTypography(adapter.page)).like.fontSize).toBe("21px");
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveCount(1);
|
||||
|
||||
for (const dark of [false, true]) {
|
||||
await adapter.page.evaluate((enabled) => document.body.classList.toggle("fixture-dark", enabled), dark);
|
||||
const typography = await readTypography(adapter.page);
|
||||
expect(typography.dislike).toEqual(typography.like);
|
||||
await adapter.page
|
||||
.locator("#top-row")
|
||||
.screenshot({ path: testInfo.outputPath(dark ? "dark.png" : "light.png") });
|
||||
}
|
||||
|
||||
await adapter.page.locator("#top-row #top-level-buttons-computed").evaluate((element) => {
|
||||
element.replaceWith(element.cloneNode(true));
|
||||
});
|
||||
await adapter.page
|
||||
.locator('[data-fixture-role="like"]')
|
||||
.evaluate((element) => element.classList.add("fixture-compact"));
|
||||
await expect.poll(async () => (await readTypography(adapter.page)).dislike.fontSize).toBe("17px");
|
||||
|
||||
await adapter.page.locator(LIKE_TEXT).evaluate((element) => {
|
||||
element.innerHTML = '<span class="fixture-digit">301</span>';
|
||||
});
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveText("100");
|
||||
await expect
|
||||
.poll(async () => (await readTypography(adapter.page)).dislike)
|
||||
.toEqual((await readTypography(adapter.page)).like);
|
||||
|
||||
await adapter.page.locator(LIKE_TEXT).evaluate((element) => {
|
||||
element.textContent = "301";
|
||||
});
|
||||
await expect.poll(async () => (await readTypography(adapter.page)).dislike.fontSize).toBe("14px");
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveCount(1);
|
||||
|
||||
// A hard navigation creates a fresh control with a different authoritative count.
|
||||
await adapter.openWatch(VIDEO_B);
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveText("80");
|
||||
await expect
|
||||
.poll(async () => (await readTypography(adapter.page)).dislike)
|
||||
.toEqual((await readTypography(adapter.page)).like);
|
||||
await expect(adapter.page.locator(DISLIKE_TEXT)).toHaveCount(1);
|
||||
await adapter.assertNoPageSignals("counter-typography");
|
||||
expect(adapter.backend.blockedRequests).toEqual([]);
|
||||
expect(apiServer.unexpectedRequests).toEqual([]);
|
||||
} finally {
|
||||
await adapter.close();
|
||||
await apiServer.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
const path = require("node:path");
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { HermeticExtensionArtifactAdapter, startHermeticApiServer } = require("../hermetic-artifact-smoke");
|
||||
|
||||
const EXTENSION_ARTIFACT = path.resolve(
|
||||
process.env.RYD_EXTENSION_ARTIFACT || path.join(__dirname, "../../combined/dist/chrome"),
|
||||
);
|
||||
|
||||
test("built popup decodes the inbox back arrow as UTF-8 and returns to settings", async ({}, testInfo) => {
|
||||
const apiServer = await startHermeticApiServer();
|
||||
const adapter = new HermeticExtensionArtifactAdapter({ apiServer, artifactDirectory: EXTENSION_ARTIFACT });
|
||||
try {
|
||||
await adapter.start();
|
||||
await adapter.context.route("https://fonts.googleapis.com/**", (route) =>
|
||||
route.fulfill({ body: "", contentType: "text/css", status: 200 }),
|
||||
);
|
||||
await adapter.context.route("https://fonts.gstatic.com/**", (route) =>
|
||||
route.fulfill({ body: "", contentType: "font/woff2", status: 200 }),
|
||||
);
|
||||
await adapter.context.route("https://raw.githubusercontent.com/**", (route) =>
|
||||
route.fulfill({ body: JSON.stringify({ version: "4.0.5" }), contentType: "application/json", status: 200 }),
|
||||
);
|
||||
const page = adapter.page;
|
||||
await page.setViewportSize({ width: 360, height: 541 });
|
||||
await page.goto(`chrome-extension://${adapter.extensionId}/popup.html`, { waitUntil: "load" });
|
||||
const toggle = page.locator("#ryd-discussion-inbox-toggle");
|
||||
const inbox = page.locator("#ryd-discussion-popup");
|
||||
const back = page.locator(".ryd-discussion-inbox-back");
|
||||
await toggle.click();
|
||||
|
||||
expect(await page.evaluate(() => document.characterSet)).toBe("UTF-8");
|
||||
await expect(inbox).toBeVisible();
|
||||
await expect(back).toHaveText("\u2190");
|
||||
await expect(back).toHaveAccessibleName("Close");
|
||||
await expect(back).toBeFocused();
|
||||
await page.locator(".ryd-discussion-inbox-brand").screenshot({ path: testInfo.outputPath("inbox-header.png") });
|
||||
|
||||
await back.click();
|
||||
await expect(inbox).toBeHidden();
|
||||
await expect(toggle).toBeVisible();
|
||||
await expect(toggle).toBeFocused();
|
||||
await adapter.assertNoPageSignals(testInfo.title);
|
||||
expect(adapter.backend.blockedRequests).toEqual([]);
|
||||
expect(apiServer.unexpectedRequests).toEqual([]);
|
||||
} finally {
|
||||
await adapter.close().catch(() => {});
|
||||
await apiServer.close().catch(() => {});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,144 @@
|
||||
const path = require("node:path");
|
||||
const { test, expect } = require("@playwright/test");
|
||||
const { VIDEO_A } = require("../../UserScript/e2e/harness");
|
||||
const { HermeticExtensionArtifactAdapter, startHermeticApiServer } = require("../hermetic-artifact-smoke");
|
||||
|
||||
const EXTENSION_ARTIFACT = path.resolve(
|
||||
process.env.RYD_EXTENSION_ARTIFACT || path.join(__dirname, "../../combined/dist/chrome"),
|
||||
);
|
||||
const PANEL = ".ryd-premium-teaser";
|
||||
const PALETTES = {
|
||||
light: { background: "rgb(255, 255, 255)", primary: "rgb(15, 15, 15)", secondary: "rgb(96, 96, 96)" },
|
||||
dark: { background: "rgb(32, 32, 32)", primary: "rgb(255, 255, 255)", secondary: "rgb(156, 163, 175)" },
|
||||
};
|
||||
const LEGACY_PALETTES = {
|
||||
light: { background: "rgb(255, 248, 240)", primary: "rgb(48, 32, 16)", secondary: "rgb(112, 80, 48)" },
|
||||
dark: { background: "rgb(21, 25, 35)", primary: "rgb(228, 234, 255)", secondary: "rgb(171, 184, 210)" },
|
||||
};
|
||||
|
||||
async function installTeaserContainer(context) {
|
||||
await context.addInitScript(() => {
|
||||
if (location.hostname !== "www.youtube.com") return;
|
||||
document.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
const secondary = document.createElement("aside");
|
||||
secondary.id = "secondary";
|
||||
secondary.style.cssText = "width: 400px; margin: 24px;";
|
||||
const inner = document.createElement("div");
|
||||
inner.id = "secondary-inner";
|
||||
secondary.append(inner);
|
||||
document.body.append(secondary);
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
async function setPageTheme(page, theme, legacyTokens) {
|
||||
await page.evaluate(
|
||||
({ dark, palette }) => {
|
||||
const root = document.documentElement;
|
||||
root.toggleAttribute("dark", dark);
|
||||
root.style.setProperty("--yt-spec-base-background", palette?.background || "initial");
|
||||
root.style.setProperty("--yt-spec-text-primary", palette?.primary || "initial");
|
||||
root.style.setProperty("--yt-spec-text-secondary", palette?.secondary || "initial");
|
||||
root.style.backgroundColor = dark ? "#0f0f0f" : "#fff";
|
||||
document.body.style.backgroundColor = dark ? "#0f0f0f" : "#fff";
|
||||
},
|
||||
{ dark: theme === "dark", palette: legacyTokens ? LEGACY_PALETTES[theme] : null },
|
||||
);
|
||||
}
|
||||
|
||||
async function expectTeaserPalette(page, theme, legacyTokens) {
|
||||
const palette = (legacyTokens ? LEGACY_PALETTES : PALETTES)[theme];
|
||||
await expect(page.locator(PANEL)).toHaveCSS("background-color", palette.background);
|
||||
await expect(page.locator(PANEL)).toHaveCSS("color", palette.primary);
|
||||
await expect(page.locator("#ryd-premium-teaser-likes")).toHaveCSS("color", palette.primary);
|
||||
await expect(page.locator("#ryd-premium-teaser-dislikes")).toHaveCSS("color", palette.primary);
|
||||
await expect(page.locator(".ryd-premium-teaser__count-label").first()).toHaveCSS("color", palette.secondary);
|
||||
|
||||
const secondaryRoles = {
|
||||
".ryd-premium-teaser__subtitle": "rgb(188, 204, 220)",
|
||||
".ryd-premium-teaser__highlights-title": "rgb(156, 163, 175)",
|
||||
".ryd-premium-teaser__highlights-list": "rgb(147, 173, 200)",
|
||||
".ryd-premium-teaser__secondary": "rgb(142, 164, 200)",
|
||||
".ryd-premium-teaser__status": "rgb(156, 163, 175)",
|
||||
".ryd-premium-teaser__close": "rgb(148, 163, 184)",
|
||||
".ryd-premium-teaser__toggle": "rgb(148, 163, 184)",
|
||||
};
|
||||
await page.mouse.move(0, 0);
|
||||
await page.locator(PANEL).evaluate(() => document.activeElement?.blur());
|
||||
for (const [selector, darkFallback] of Object.entries(secondaryRoles)) {
|
||||
const color = legacyTokens || theme === "light" ? palette.secondary : darkFallback;
|
||||
await expect(page.locator(selector)).toHaveCSS("color", color);
|
||||
}
|
||||
|
||||
for (const selector of ["#ryd-premium-teaser-close", "#ryd-premium-teaser-toggle"]) {
|
||||
const control = page.locator(selector);
|
||||
await control.hover();
|
||||
const hoverColor = legacyTokens || theme === "light" ? palette.primary : "rgb(248, 250, 252)";
|
||||
await expect(control).toHaveCSS("color", hoverColor);
|
||||
await page.mouse.move(0, 0);
|
||||
await control.focus();
|
||||
await expect(control).toHaveCSS("color", hoverColor);
|
||||
await control.blur();
|
||||
}
|
||||
}
|
||||
|
||||
for (const legacyTokens of [false, true]) {
|
||||
for (const colorScheme of ["light", "dark"]) {
|
||||
test(`raw-count panel follows YouTube theme with ${colorScheme} system theme and legacy tokens ${legacyTokens}`, async ({}, testInfo) => {
|
||||
const apiServer = await startHermeticApiServer();
|
||||
const adapter = new HermeticExtensionArtifactAdapter({
|
||||
apiServer,
|
||||
artifactDirectory: EXTENSION_ARTIFACT,
|
||||
contextOptions: { colorScheme },
|
||||
});
|
||||
try {
|
||||
await adapter.start();
|
||||
await adapter.setPremiumTeaserHidden(false);
|
||||
await installTeaserContainer(adapter.context);
|
||||
await adapter.openWatch(VIDEO_A);
|
||||
await expect(adapter.page.locator("#ryd-premium-teaser-likes")).toHaveText("100");
|
||||
await expect(adapter.page.locator("#ryd-premium-teaser-dislikes")).toHaveText("25");
|
||||
const panel = await adapter.page.locator(PANEL).elementHandle();
|
||||
const themes = colorScheme === "dark" ? ["light", "dark", "light"] : ["dark", "light", "dark"];
|
||||
const details = adapter.page.locator("#ryd-premium-teaser-details");
|
||||
const toggle = adapter.page.locator("#ryd-premium-teaser-toggle");
|
||||
|
||||
for (const expanded of [false, true]) {
|
||||
if (expanded) await toggle.click();
|
||||
for (const theme of themes) {
|
||||
await setPageTheme(adapter.page, theme, legacyTokens);
|
||||
await expectTeaserPalette(adapter.page, theme, legacyTokens);
|
||||
await expect(toggle).toHaveAttribute("aria-expanded", String(expanded));
|
||||
if (expanded) {
|
||||
await expect(details).toBeVisible();
|
||||
await expect(adapter.page.locator(".ryd-premium-teaser__title")).toHaveCSS(
|
||||
"color",
|
||||
(legacyTokens ? LEGACY_PALETTES : PALETTES)[theme].primary,
|
||||
);
|
||||
await adapter.page.locator(PANEL).screenshot({ path: testInfo.outputPath(`${theme}-expanded.png`) });
|
||||
} else {
|
||||
await expect(details).toBeHidden();
|
||||
}
|
||||
expect(await panel.evaluate((element) => element === document.querySelector(".ryd-premium-teaser"))).toBe(
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
await toggle.click();
|
||||
await expect(details).toBeHidden();
|
||||
|
||||
expect(adapter.backend.requestsFor("GET", "/votes")).toHaveLength(1);
|
||||
await adapter.assertNoPageSignals(testInfo.title);
|
||||
expect(adapter.backend.blockedRequests).toEqual([]);
|
||||
expect(apiServer.unexpectedRequests).toEqual([]);
|
||||
} finally {
|
||||
await adapter.close().catch(() => {});
|
||||
await apiServer.close().catch(() => {});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -134,6 +134,9 @@ export default {
|
||||
subtitle: "プロジェクトおよび開発者へのリンク",
|
||||
contact: "お問い合わせ先",
|
||||
translators: "翻訳者",
|
||||
coolProjects: "おすすめのプロジェクト",
|
||||
sponsorBlockDescription: "動画に組み込まれた広告をスキップ",
|
||||
filmotDescription: "字幕で YouTube 動画を検索",
|
||||
github: "GitHub",
|
||||
discord: "Discord",
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { pt_BR } from "vuetify/src/locale";
|
||||
import { pt } from "vuetify/src/locale";
|
||||
// by Unnamed-orbert
|
||||
export default {
|
||||
...pt_BR,
|
||||
...pt,
|
||||
home: {
|
||||
name: "Inicio",
|
||||
title: "Return YouTube Dislike",
|
||||
|
||||
@@ -138,6 +138,7 @@ export default {
|
||||
subtitle: "Ссылки на проект и его разработчиков",
|
||||
contact: "Связаться",
|
||||
translators: "Переводчики",
|
||||
coolProjects: "Интересные проекты",
|
||||
sponsorBlockDescription: "Проматывает рекламу, встроенную в видео",
|
||||
filmotDescription: "Поиск по субтитрам YouTube",
|
||||
github: "GitHub",
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { readLocalePreference, writeLocalePreference } from "../utils/locale";
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
links: [
|
||||
@@ -115,6 +117,11 @@ export default {
|
||||
{ name: "Bahasa Indonesia", locale: "id" },
|
||||
{ name: "Tiếng Việt", locale: "vi"},
|
||||
{ name: "Slovenščina", locale: "sl" },
|
||||
{ name: "Azərbaycanca", locale: "az" },
|
||||
{ name: "Italiano", locale: "it-IT" },
|
||||
{ name: "Nederlands", locale: "nl" },
|
||||
{ name: "Svenska", locale: "sv" },
|
||||
{ name: "Magyar", locale: "hu" },
|
||||
],
|
||||
alert: {
|
||||
show: false,
|
||||
@@ -123,10 +130,12 @@ export default {
|
||||
}),
|
||||
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;
|
||||
if (process.client) {
|
||||
this.$vuetify.lang.current = readLocalePreference(
|
||||
localStorage,
|
||||
navigator.language,
|
||||
Object.keys(this.$vuetify.lang.locales),
|
||||
);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -145,11 +154,12 @@ export default {
|
||||
},
|
||||
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;
|
||||
this.$vuetify.lang.current = writeLocalePreference(
|
||||
localStorage,
|
||||
navigator.language,
|
||||
locale,
|
||||
Object.keys(this.$vuetify.lang.locales),
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,6 +14,11 @@ import id from "./_locales/id";
|
||||
import vi from "./_locales/vi";
|
||||
import be from "./_locales/be";
|
||||
import sl from "./_locales/sl";
|
||||
import az from "./_locales/az";
|
||||
import itIT from "./_locales/it-IT";
|
||||
import nl from "./_locales/nl";
|
||||
import pt_BR from "./_locales/pt_BR";
|
||||
import sv from "./_locales/sv";
|
||||
// ...
|
||||
export default {
|
||||
// Global page headers: https://go.nuxtjs.dev/config-head
|
||||
@@ -58,7 +63,7 @@ export default {
|
||||
// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
|
||||
vuetify: {
|
||||
lang: {
|
||||
locales: { en, es, tr, ru, cs, ja, fr, uk, ko, pl, de, hu, id, vi, be, sl /*...*/ },
|
||||
locales: { en, es, tr, ru, cs, ja, fr, uk, ko, pl, de, hu, id, vi, be, sl, az, "it-IT": itIT, nl, pt_BR, sv },
|
||||
current: "en",
|
||||
},
|
||||
theme: {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
function resolveLocale(locale, supportedLocales) {
|
||||
const normalize = (value) => value.replace(/_/g, "-").toLowerCase();
|
||||
const normalized = typeof locale === "string" ? normalize(locale) : "";
|
||||
const exact = supportedLocales.find((supported) => normalize(supported) === normalized);
|
||||
if (exact) return exact;
|
||||
|
||||
const language = normalized.split("-")[0];
|
||||
return supportedLocales.find((supported) => normalize(supported).split("-")[0] === language) || "en";
|
||||
}
|
||||
|
||||
function readLocalePreference(storage, browserLocale, supportedLocales) {
|
||||
const storedLocale = storage.getItem("locale");
|
||||
return resolveLocale(storedLocale === null ? browserLocale : storedLocale, supportedLocales);
|
||||
}
|
||||
|
||||
function writeLocalePreference(storage, browserLocale, locale, supportedLocales) {
|
||||
const resolvedLocale = resolveLocale(locale, supportedLocales);
|
||||
if (resolvedLocale === resolveLocale(browserLocale, supportedLocales)) {
|
||||
storage.removeItem("locale");
|
||||
} else {
|
||||
storage.setItem("locale", resolvedLocale);
|
||||
}
|
||||
return resolvedLocale;
|
||||
}
|
||||
|
||||
module.exports = { resolveLocale, readLocalePreference, writeLocalePreference };
|
||||
@@ -0,0 +1,67 @@
|
||||
/* eslint-env jest */
|
||||
const { readLocalePreference, resolveLocale, writeLocalePreference } = require("./locale");
|
||||
|
||||
const supportedLocales = ["en", "es", "it-IT", "pt_BR", "az", "nl", "sv", "hu"];
|
||||
|
||||
describe("website locale resolution", () => {
|
||||
test.each([
|
||||
["en-US", "en"],
|
||||
["es-MX", "es"],
|
||||
["it-IT", "it-IT"],
|
||||
["it", "it-IT"],
|
||||
["it-CH", "it-IT"],
|
||||
["pt-BR", "pt_BR"],
|
||||
["pt_BR", "pt_BR"],
|
||||
["pt-PT", "pt_BR"],
|
||||
["PT-br", "pt_BR"],
|
||||
["az-AZ", "az"],
|
||||
["nl-NL", "nl"],
|
||||
["sv-SE", "sv"],
|
||||
["hu-HU", "hu"],
|
||||
["zz-ZZ", "en"],
|
||||
["", "en"],
|
||||
[undefined, "en"],
|
||||
])("resolves %s to registered locale %s", (locale, expected) => {
|
||||
expect(resolveLocale(locale, supportedLocales)).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("website locale preferences", () => {
|
||||
function createStorage(values = {}) {
|
||||
const items = new Map(Object.entries(values));
|
||||
return {
|
||||
getItem: (key) => items.get(key) ?? null,
|
||||
setItem: (key, value) => items.set(key, value),
|
||||
removeItem: (key) => items.delete(key),
|
||||
};
|
||||
}
|
||||
|
||||
test("uses the browser locale when no preference is saved", () => {
|
||||
expect(readLocalePreference(createStorage(), "pt-BR", supportedLocales)).toBe("pt_BR");
|
||||
});
|
||||
|
||||
test.each(["pt_BR", "pt-BR", "it-IT", "es"])("preserves a supported saved choice %s", (locale) => {
|
||||
expect(readLocalePreference(createStorage({ locale }), "nl-NL", supportedLocales)).toBe(
|
||||
resolveLocale(locale, supportedLocales)
|
||||
);
|
||||
});
|
||||
|
||||
test("falls back to English for an unsupported saved choice", () => {
|
||||
expect(readLocalePreference(createStorage({ locale: "zz" }), "nl-NL", supportedLocales)).toBe("en");
|
||||
});
|
||||
|
||||
test("saves a manual choice that differs from the browser locale", () => {
|
||||
const storage = createStorage();
|
||||
expect(writeLocalePreference(storage, "nl-NL", "pt_BR", supportedLocales)).toBe("pt_BR");
|
||||
expect(storage.getItem("locale")).toBe("pt_BR");
|
||||
expect(readLocalePreference(storage, "nl-NL", supportedLocales)).toBe("pt_BR");
|
||||
});
|
||||
|
||||
test("resets only the locale preference when selecting the browser default", () => {
|
||||
const storage = createStorage({ locale: "es", otherSetting: "retained" });
|
||||
expect(writeLocalePreference(storage, "pt-BR", "pt_BR", supportedLocales)).toBe("pt_BR");
|
||||
expect(storage.getItem("locale")).toBeNull();
|
||||
expect(storage.getItem("otherSetting")).toBe("retained");
|
||||
expect(readLocalePreference(storage, "pt-BR", supportedLocales)).toBe("pt_BR");
|
||||
});
|
||||
});
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "return-youtube-dislike",
|
||||
"version": "4.0.6",
|
||||
"version": "4.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "return-youtube-dislike",
|
||||
"version": "4.0.6",
|
||||
"version": "4.1.0",
|
||||
"dependencies": {
|
||||
"@microsoft/signalr": "9.0.6",
|
||||
"country-code-lookup": "^0.1.3",
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "return-youtube-dislike",
|
||||
"version": "4.0.6",
|
||||
"version": "4.1.0",
|
||||
"description": "Chrome extension to return youtube dislikes",
|
||||
"main": "ryd.content-script.js",
|
||||
"packageManager": "npm@10.8.2",
|
||||
@@ -20,6 +20,7 @@
|
||||
"reload:live:extension": "node Extensions/UserScript/e2e/live/reload-live-extension.js",
|
||||
"check:extension-artifact": "node Extensions/e2e/verify-extension-artifact.js",
|
||||
"test": "jest",
|
||||
"check:locales": "node scripts/check-locales.js",
|
||||
"test:e2e:artifacts": "npm run check:extension-artifact && npm run check:userscript-artifact && node Extensions/e2e/hermetic-artifact-smoke.js",
|
||||
"test:e2e:extension:run": "npm run check:extension-artifact && playwright test --config playwright.extension.config.js",
|
||||
"test:e2e:extension": "npm run build && npm run check:extension-artifact && npm run test:e2e:extension:run",
|
||||
|
||||
@@ -12,7 +12,7 @@ const menuFixerPath = join(firefoxOutputDirectory, "menu-fixer.js");
|
||||
const maxContentScriptBytes = 5 * 1024 * 1024;
|
||||
const expectedNodeVersion = "v22.17.0";
|
||||
const expectedNpmVersion = "10.8.2";
|
||||
const expectedExtensionVersion = "4.0.6";
|
||||
const expectedExtensionVersion = "4.1.0";
|
||||
const expectedFirefoxExtensionId = "{762f9885-5a13-4abd-9c77-433dcd38b8fd}";
|
||||
const expectedRequiredDataCollectionPermissions = [
|
||||
"personallyIdentifyingInfo",
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const ROOT = path.resolve(__dirname, "..");
|
||||
// Both dependency trees already include the parser; Website CI installs only its own dependencies.
|
||||
const parser = require(require.resolve("@babel/parser", { paths: [ROOT, path.join(ROOT, "Website")] }));
|
||||
const EMPTY_WEBSITE_FRAGMENTS = new Set([
|
||||
"cs:help.bullet11",
|
||||
"de:help.bullet11",
|
||||
"es:help.bullet11",
|
||||
"uk:help.bullet11",
|
||||
"vi:help.bullet11",
|
||||
]);
|
||||
|
||||
function object(value) {
|
||||
return value !== null && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function propertyName(node) {
|
||||
if (node.computed || !["Identifier", "StringLiteral"].includes(node.key?.type)) {
|
||||
throw new Error("Expected a literal property name");
|
||||
}
|
||||
return node.key.name ?? node.key.value;
|
||||
}
|
||||
|
||||
function readObject(node, rootSpreads = new Set()) {
|
||||
if (node?.type === "StringLiteral") return node.value;
|
||||
if (node?.type !== "ObjectExpression") throw new Error("Expected an object or string literal");
|
||||
const result = Object.create(null);
|
||||
for (const prop of node.properties) {
|
||||
if (prop.type === "SpreadElement" && prop.argument.type === "Identifier" && rootSpreads.has(prop.argument.name)) {
|
||||
continue;
|
||||
}
|
||||
if (prop.type !== "ObjectProperty") throw new Error("Only literal locale properties are supported");
|
||||
const key = propertyName(prop);
|
||||
if (Object.hasOwn(result, key)) throw new Error(`Duplicate key: ${key}`);
|
||||
result[key] = readObject(prop.value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseModule(source) {
|
||||
return parser.parse(source, { sourceType: "module", plugins: ["typescript"] }).program.body;
|
||||
}
|
||||
|
||||
function readWebsiteLocale(source) {
|
||||
const statements = parseModule(source);
|
||||
const spreads = new Set();
|
||||
for (const statement of statements) {
|
||||
if (statement.type === "ImportDeclaration" && statement.source.value === "vuetify/src/locale") {
|
||||
for (const specifier of statement.specifiers) spreads.add(specifier.local.name);
|
||||
} else if (statement.type !== "ExportDefaultDeclaration") {
|
||||
throw new Error("Expected only a Vuetify locale import and a default locale object");
|
||||
}
|
||||
}
|
||||
const exported = statements.find((statement) => statement.type === "ExportDefaultDeclaration");
|
||||
return readObject(exported?.declaration, spreads);
|
||||
}
|
||||
|
||||
function readExtensionLocale(source) {
|
||||
JSON.parse(source); // Enforce JSON syntax before reading the object and detecting duplicate keys.
|
||||
return readObject(parser.parseExpression(source));
|
||||
}
|
||||
|
||||
function tokens(text, website = false) {
|
||||
// $$ escapes a dollar in extension messages. Named placeholders are case-insensitive.
|
||||
const pattern = website ? /\{\d+\}|\$\$|\$[a-zA-Z0-9_]+\$|\$\d+/g : /\$\$|\$[a-zA-Z0-9_]+\$|\$\d+/g;
|
||||
return (text.match(pattern) || [])
|
||||
.filter((token) => token !== "$$")
|
||||
.map((token) => token.toLowerCase())
|
||||
.sort();
|
||||
}
|
||||
|
||||
function sameTokens(left, right, website = false) {
|
||||
return JSON.stringify(tokens(left, website)) === JSON.stringify(tokens(right, website));
|
||||
}
|
||||
|
||||
function extensionPlaceholders(entry, key, errors) {
|
||||
const result = Object.create(null);
|
||||
if (entry.placeholders !== undefined && !object(entry.placeholders)) {
|
||||
errors.push(`${key}: placeholders must be an object`);
|
||||
return result;
|
||||
}
|
||||
for (const [name, definition] of Object.entries(entry.placeholders || {})) {
|
||||
const normalized = name.toLowerCase();
|
||||
if (!/^[a-zA-Z0-9_]+$/.test(name) || Object.hasOwn(result, normalized)) {
|
||||
errors.push(`${key}: invalid or duplicate placeholder ${name}`);
|
||||
continue;
|
||||
}
|
||||
if (!object(definition) || typeof definition.content !== "string" || !definition.content.trim()) {
|
||||
errors.push(`${key}: placeholder ${name} needs nonempty string content`);
|
||||
continue;
|
||||
}
|
||||
if (definition.example !== undefined && typeof definition.example !== "string") {
|
||||
errors.push(`${key}: placeholder ${name} example must be a string`);
|
||||
}
|
||||
result[normalized] = definition.content;
|
||||
}
|
||||
for (const token of tokens(entry.message || "")) {
|
||||
if (token.endsWith("$") && !Object.hasOwn(result, token.slice(1, -1))) {
|
||||
errors.push(`${key}: undefined placeholder ${token}`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function compareExtension(base, locale) {
|
||||
const result = { errors: [], extra: [], identical: [] };
|
||||
if (!object(base) || !object(locale)) {
|
||||
result.errors.push("Locale must be an object");
|
||||
return result;
|
||||
}
|
||||
for (const key of Object.keys(base)) {
|
||||
if (!Object.hasOwn(locale, key)) result.errors.push(`${key}: missing key`);
|
||||
}
|
||||
for (const [key, entry] of Object.entries(locale)) {
|
||||
if (!Object.hasOwn(base, key)) result.extra.push(key);
|
||||
if (!object(entry) || typeof entry.message !== "string" || !entry.message.trim()) {
|
||||
result.errors.push(`${key}: message must be a nonempty string`);
|
||||
continue;
|
||||
}
|
||||
if (entry.description !== undefined && typeof entry.description !== "string") {
|
||||
result.errors.push(`${key}: description must be a string`);
|
||||
}
|
||||
const placeholders = extensionPlaceholders(entry, key, result.errors);
|
||||
const reference = base[key];
|
||||
if (!object(reference) || typeof reference.message !== "string") continue;
|
||||
if (!sameTokens(reference.message, entry.message))
|
||||
result.errors.push(`${key}: placeholder tokens differ from English`);
|
||||
const expected = extensionPlaceholders(reference, key, []);
|
||||
if (JSON.stringify(Object.entries(expected).sort()) !== JSON.stringify(Object.entries(placeholders).sort())) {
|
||||
result.errors.push(`${key}: placeholder definitions differ from English`);
|
||||
}
|
||||
if (entry.message === reference.message) result.identical.push(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function flattenWebsite(value, prefix = "", result = {}) {
|
||||
for (const [key, item] of Object.entries(value)) {
|
||||
const name = prefix ? `${prefix}.${key}` : key;
|
||||
if (object(item)) flattenWebsite(item, name, result);
|
||||
else result[name] = item;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function compareWebsite(base, locale, language) {
|
||||
const result = { errors: [], extra: [], identical: [] };
|
||||
if (!object(base) || !object(locale)) {
|
||||
result.errors.push("Locale must be an object");
|
||||
return result;
|
||||
}
|
||||
const reference = flattenWebsite(base);
|
||||
const translated = flattenWebsite(locale);
|
||||
for (const key of Object.keys(reference)) {
|
||||
if (!Object.hasOwn(translated, key)) result.errors.push(`${key}: missing key`);
|
||||
}
|
||||
for (const [key, value] of Object.entries(translated)) {
|
||||
if (!Object.hasOwn(reference, key)) result.extra.push(key);
|
||||
// These fragments follow the version number; their preceding sentence already supplies the meaning.
|
||||
const allowedEmpty = value === "" && EMPTY_WEBSITE_FRAGMENTS.has(`${language}:${key}`);
|
||||
if (typeof value !== "string" || (!value.trim() && !allowedEmpty)) {
|
||||
result.errors.push(`${key}: value must be a nonempty string`);
|
||||
continue;
|
||||
}
|
||||
if (typeof reference[key] !== "string") continue;
|
||||
if (!sameTokens(reference[key], value, true)) result.errors.push(`${key}: placeholder tokens differ from English`);
|
||||
if (value === reference[key]) result.identical.push(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function findProperty(node, name) {
|
||||
if (node?.type !== "ObjectExpression") throw new Error(`Expected an object containing ${name}`);
|
||||
const matches = node.properties.filter((prop) => prop.type === "ObjectProperty" && propertyName(prop) === name);
|
||||
if (matches.length !== 1) throw new Error(`Expected exactly one ${name} property`);
|
||||
return matches[0].value;
|
||||
}
|
||||
|
||||
function checkWebsiteRegistration(configSource, layoutSource, languages) {
|
||||
const statements = parseModule(configSource);
|
||||
const imports = new Map();
|
||||
for (const statement of statements.filter((item) => item.type === "ImportDeclaration")) {
|
||||
for (const specifier of statement.specifiers) imports.set(specifier.local.name, statement.source.value);
|
||||
}
|
||||
let config = statements.find((statement) => statement.type === "ExportDefaultDeclaration")?.declaration;
|
||||
for (const key of ["vuetify", "lang", "locales"]) config = findProperty(config, key);
|
||||
const registered = new Set();
|
||||
const errors = [];
|
||||
for (const prop of config.properties) {
|
||||
if (prop.type !== "ObjectProperty") throw new Error("Expected literal website locale registrations");
|
||||
const language = propertyName(prop);
|
||||
if (registered.has(language)) errors.push(`${language}: duplicate registration`);
|
||||
registered.add(language);
|
||||
if (prop.value.type !== "Identifier" || imports.get(prop.value.name) !== `./_locales/${language}`) {
|
||||
errors.push(`${language}: registration must use its matching locale import`);
|
||||
}
|
||||
}
|
||||
const script = layoutSource.match(/<script(?:\s[^>]*)?>([\s\S]*?)<\/script>/)?.[1];
|
||||
if (!script) throw new Error("Website layout script is missing");
|
||||
const layout = parseModule(script).find((statement) => statement.type === "ExportDefaultDeclaration")?.declaration;
|
||||
const data = findProperty(layout, "data");
|
||||
const langs = findProperty(data.body, "langs");
|
||||
if (data.type !== "ArrowFunctionExpression" || langs.type !== "ArrayExpression") {
|
||||
throw new Error("Expected a literal website language picker array");
|
||||
}
|
||||
const selectable = new Set();
|
||||
for (const item of langs.elements) {
|
||||
const language = findProperty(item, "locale");
|
||||
if (language.type !== "StringLiteral") throw new Error("Expected literal picker locale codes");
|
||||
if (selectable.has(language.value)) errors.push(`${language.value}: duplicate picker entry`);
|
||||
selectable.add(language.value);
|
||||
}
|
||||
for (const language of new Set([...languages, ...registered, ...selectable])) {
|
||||
if (!languages.includes(language)) errors.push(`${language}: locale file is missing`);
|
||||
if (!registered.has(language)) errors.push(`${language}: locale is not registered`);
|
||||
if (!selectable.has(language)) errors.push(`${language}: locale is missing from the picker`);
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
function checkCatalogs(root, system) {
|
||||
const website = system === "website";
|
||||
const directory = path.join(root, website ? "Website/_locales" : "Extensions/combined/_locales");
|
||||
const files = fs
|
||||
.readdirSync(directory, { withFileTypes: true })
|
||||
.filter((entry) => (website ? entry.isFile() && entry.name.endsWith(".ts") : entry.isDirectory()))
|
||||
.map((entry) => ({
|
||||
language: website ? entry.name.slice(0, -3) : entry.name,
|
||||
file: path.join(directory, entry.name, ...(website ? [] : ["messages.json"])),
|
||||
}))
|
||||
.sort((left, right) => left.language.localeCompare(right.language));
|
||||
const read = (file) => (website ? readWebsiteLocale : readExtensionLocale)(fs.readFileSync(file, "utf8"));
|
||||
const baseFile = files.find(({ language }) => language === "en");
|
||||
if (!baseFile) throw new Error(`${system}: English locale is missing`);
|
||||
const base = read(baseFile.file);
|
||||
if (!(website ? Object.keys(flattenWebsite(base)) : Object.keys(base)).length) {
|
||||
throw new Error(`${system}: English locale must contain messages`);
|
||||
}
|
||||
const reports = files.map(({ language, file }) => {
|
||||
try {
|
||||
const catalog = language === "en" ? base : read(file);
|
||||
const report = website ? compareWebsite(base, catalog, language) : compareExtension(base, catalog);
|
||||
if (language === "en") report.identical = [];
|
||||
return { name: `${system}/${language}`, ...report };
|
||||
} catch (error) {
|
||||
return { name: `${system}/${language}`, errors: [error.message], extra: [], identical: [] };
|
||||
}
|
||||
});
|
||||
if (website) {
|
||||
const errors = checkWebsiteRegistration(
|
||||
fs.readFileSync(path.join(root, "Website/nuxt.config.js"), "utf8"),
|
||||
fs.readFileSync(path.join(root, "Website/layouts/default.vue"), "utf8"),
|
||||
files.map(({ language }) => language),
|
||||
);
|
||||
reports.push({ name: "website/registration", errors, extra: [], identical: [] });
|
||||
}
|
||||
return reports;
|
||||
}
|
||||
|
||||
function main(args = process.argv.slice(2), root = ROOT) {
|
||||
const allowed = new Set(["--extension", "--website", "--verbose"]);
|
||||
if (args.some((argument) => !allowed.has(argument)))
|
||||
throw new Error("Usage: node scripts/check-locales.js [--extension|--website] [--verbose]");
|
||||
const selected = ["extension", "website"].filter((system) => args.includes(`--${system}`));
|
||||
const reports = (selected.length ? selected : ["extension", "website"]).flatMap((system) =>
|
||||
checkCatalogs(root, system),
|
||||
);
|
||||
for (const report of reports) {
|
||||
for (const error of report.errors) console.error(`ERROR ${report.name}: ${error}`);
|
||||
for (const [kind, keys] of [
|
||||
["extra keys", report.extra],
|
||||
["identical to English (may be intentional)", report.identical],
|
||||
]) {
|
||||
if (!keys.length) continue;
|
||||
const shown = args.includes("--verbose") ? keys : keys.slice(0, 5);
|
||||
console.log(
|
||||
`Advisory ${report.name}: ${keys.length} ${kind}: ${shown.join(", ")}${shown.length < keys.length ? ", ... (use --verbose)" : ""}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
const count = reports.reduce((sum, report) => sum + report.errors.length, 0);
|
||||
console.log(
|
||||
`Checked ${reports.filter((report) => !report.name.endsWith("/registration")).length} locales; ${count} error(s).`,
|
||||
);
|
||||
return count ? 1 : 0;
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
try {
|
||||
process.exitCode = main();
|
||||
} catch (error) {
|
||||
console.error(`ERROR ${error.message}`);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readWebsiteLocale,
|
||||
readExtensionLocale,
|
||||
compareExtension,
|
||||
compareWebsite,
|
||||
checkWebsiteRegistration,
|
||||
checkCatalogs,
|
||||
main,
|
||||
};
|
||||
@@ -0,0 +1,187 @@
|
||||
/** @jest-environment node */
|
||||
const fs = require("node:fs");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const {
|
||||
readWebsiteLocale,
|
||||
readExtensionLocale,
|
||||
compareExtension,
|
||||
compareWebsite,
|
||||
checkWebsiteRegistration,
|
||||
checkCatalogs,
|
||||
main,
|
||||
} = require("./check-locales");
|
||||
|
||||
const message = (text) => ({ message: text });
|
||||
const websiteSource = (body) => `import { en } from "vuetify/src/locale"; export default { ...en, ${body} };`;
|
||||
|
||||
test("extension completeness follows added English keys and validates extra message shapes", () => {
|
||||
const result = compareExtension(
|
||||
{ greeting: message("Hello"), added: message("New") },
|
||||
{
|
||||
greeting: message("Bonjour"),
|
||||
obsolete: { message: null },
|
||||
},
|
||||
);
|
||||
expect(result.errors).toEqual(["added: missing key", "obsolete: message must be a nonempty string"]);
|
||||
expect(result.extra).toEqual(["obsolete"]);
|
||||
});
|
||||
|
||||
test.each([null, [], "text", 17])("rejects invalid extension catalogue shape %p", (value) => {
|
||||
expect(compareExtension({ hello: message("Hello") }, value).errors).toContain("Locale must be an object");
|
||||
});
|
||||
|
||||
test.each([undefined, null, [], {}, "", " "])("rejects invalid extension message %p", (value) => {
|
||||
expect(compareExtension({ hello: message("Hello") }, { hello: message(value) }).errors).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("checks positional placeholder identity and multiplicity while allowing reordering", () => {
|
||||
const base = { greeting: message("$1 has $2 and $1") };
|
||||
expect(compareExtension(base, { greeting: message("$1, $1, $2") }).errors).toEqual([]);
|
||||
expect(compareExtension(base, { greeting: message("$1, $2") }).errors).toContain(
|
||||
"greeting: placeholder tokens differ from English",
|
||||
);
|
||||
expect(compareExtension(base, { greeting: message("$1, $1, $3") }).errors).toContain(
|
||||
"greeting: placeholder tokens differ from English",
|
||||
);
|
||||
});
|
||||
|
||||
test("escaped dollars are literal and named placeholders are case-insensitive", () => {
|
||||
const base = {
|
||||
greeting: { message: "Hello $NAME$ ($$1)", placeholders: { NAME: { content: "$1", example: "Alex" } } },
|
||||
};
|
||||
const translated = {
|
||||
greeting: { message: "Bonjour $name$ ($$2)", placeholders: { name: { content: "$1", example: "Léa" } } },
|
||||
};
|
||||
expect(compareExtension(base, translated).errors).toEqual([]);
|
||||
});
|
||||
|
||||
test("detects undefined named placeholders and changed substitution definitions", () => {
|
||||
const base = { greeting: { message: "$NAME$", placeholders: { NAME: { content: "$1" } } } };
|
||||
const swapped = { greeting: { message: "$NAME$", placeholders: { NAME: { content: "$2" } } } };
|
||||
expect(compareExtension(base, swapped).errors).toContain("greeting: placeholder definitions differ from English");
|
||||
expect(compareExtension(base, { greeting: message("$NAME$") }).errors).toContain(
|
||||
"greeting: undefined placeholder $name$",
|
||||
);
|
||||
expect(compareExtension(base, { greeting: { message: "$NAME$", placeholders: [] } }).errors).toContain(
|
||||
"greeting: placeholders must be an object",
|
||||
);
|
||||
});
|
||||
|
||||
test("reports identical English strings and extra keys as advisories only", () => {
|
||||
const result = compareExtension(
|
||||
{ brand: message("YouTube") },
|
||||
{ brand: message("YouTube"), extra: message("Extra") },
|
||||
);
|
||||
expect(result).toEqual({ errors: [], identical: ["brand"], extra: ["extra"] });
|
||||
});
|
||||
|
||||
test("statically reads website custom strings while excluding the upstream Vuetify spread", () => {
|
||||
expect(readWebsiteLocale(websiteSource('home: { name: "Home", quoted: "café" }'))).toEqual({
|
||||
home: { name: "Home", quoted: "café" },
|
||||
});
|
||||
expect(() => readWebsiteLocale(websiteSource("home: { name: runCode() }"))).toThrow(/literal/);
|
||||
expect(() => readWebsiteLocale('import other from "elsewhere"; export default {...other}')).toThrow(/Vuetify/);
|
||||
expect(() => readWebsiteLocale(websiteSource("home: { ...en }"))).toThrow(/literal/);
|
||||
});
|
||||
|
||||
test("detects duplicate keys before JSON or module object evaluation can hide them", () => {
|
||||
expect(() => readExtensionLocale('{"a":{"message":"one"},"a":{"message":"two"}}')).toThrow("Duplicate key: a");
|
||||
expect(() => readExtensionLocale('{"a":{"message":"one","message":"two"}}')).toThrow("Duplicate key: message");
|
||||
expect(() => readWebsiteLocale(websiteSource('home: { name: "One", name: "Two" }'))).toThrow("Duplicate key: name");
|
||||
});
|
||||
|
||||
test("extension input uses strict JSON syntax", () => {
|
||||
expect(() => readExtensionLocale('{"a":{"message":"one",}}')).toThrow();
|
||||
expect(() => readExtensionLocale('{a:{message:"one"}}')).toThrow();
|
||||
});
|
||||
|
||||
test("website comparison finds nested missing keys and wrong shapes", () => {
|
||||
const base = { links: { name: "Links", added: "Added" } };
|
||||
expect(compareWebsite(base, { links: { name: "Liens" } }, "fr").errors).toEqual(["links.added: missing key"]);
|
||||
expect(compareWebsite(base, { links: [] }, "fr").errors).toEqual([
|
||||
"links.name: missing key",
|
||||
"links.added: missing key",
|
||||
"links: value must be a nonempty string",
|
||||
]);
|
||||
});
|
||||
|
||||
test("website interpolation checks multiplicity and retains legitimate brand advisories", () => {
|
||||
const base = { count: "{0} of {1} ({0})", brand: "Firefox" };
|
||||
expect(compareWebsite(base, { count: "{1}: {0}, {0}", brand: "Firefox" }, "fr")).toEqual({
|
||||
errors: [],
|
||||
extra: [],
|
||||
identical: ["brand"],
|
||||
});
|
||||
expect(compareWebsite(base, { count: "{0} of {1}", brand: "Firefox" }, "fr").errors).toContain(
|
||||
"count: placeholder tokens differ from English",
|
||||
);
|
||||
});
|
||||
|
||||
test("empty website exceptions apply only to the existing sentence fragments", () => {
|
||||
const base = { help: { bullet11: "right now", name: "Help" } };
|
||||
expect(compareWebsite(base, { help: { bullet11: "", name: "Hilfe" } }, "de").errors).toEqual([]);
|
||||
expect(compareWebsite(base, { help: { bullet11: " ", name: "Hilfe" } }, "de").errors).toHaveLength(1);
|
||||
expect(compareWebsite(base, { help: { bullet11: "", name: "Aide" } }, "fr").errors).toHaveLength(1);
|
||||
expect(compareWebsite(base, { help: { bullet11: "", name: "" } }, "de").errors).toEqual([
|
||||
"help.name: value must be a nonempty string",
|
||||
]);
|
||||
});
|
||||
|
||||
const config = (registered = "en, fr") => `import en from "./_locales/en"; import fr from "./_locales/fr";
|
||||
export default { vuetify: { lang: { locales: { ${registered} } } } };`;
|
||||
const layout = (locales = '"en", "fr"') =>
|
||||
`<script>export default {data: () => ({langs: [${locales
|
||||
.split(", ")
|
||||
.map((locale) => `{locale: ${locale}}`)
|
||||
.join(",")} ]})};</script>`;
|
||||
|
||||
test("validates website registration, matching imports, picker coverage, and duplicate codes", () => {
|
||||
expect(checkWebsiteRegistration(config(), layout(), ["en", "fr"])).toEqual([]);
|
||||
expect(checkWebsiteRegistration(config("en"), layout(), ["en", "fr"])).toEqual(["fr: locale is not registered"]);
|
||||
expect(checkWebsiteRegistration(config(), layout('"en"'), ["en", "fr"])).toEqual([
|
||||
"fr: locale is missing from the picker",
|
||||
]);
|
||||
expect(checkWebsiteRegistration(config("en, fr: en"), layout(), ["en", "fr"])).toEqual([
|
||||
"fr: registration must use its matching locale import",
|
||||
]);
|
||||
expect(checkWebsiteRegistration(config(), layout('"en", "fr", "fr"'), ["en", "fr"])).toEqual([
|
||||
"fr: duplicate picker entry",
|
||||
]);
|
||||
expect(checkWebsiteRegistration(config(), layout(), ["en"])).toEqual(["fr: locale file is missing"]);
|
||||
});
|
||||
|
||||
test("the filesystem checker reports missing messages and rejects a missing or empty English source", () => {
|
||||
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "ryd-locales-test-"));
|
||||
const log = jest.spyOn(console, "log").mockImplementation(() => {});
|
||||
const error = jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
try {
|
||||
const directory = path.join(temporary, "Extensions/combined/_locales");
|
||||
for (const language of ["en", "fr"]) fs.mkdirSync(path.join(directory, language), { recursive: true });
|
||||
const english = path.join(directory, "en/messages.json");
|
||||
fs.writeFileSync(english, JSON.stringify({ first: message("First"), added: message("New") }));
|
||||
fs.writeFileSync(path.join(directory, "fr/messages.json"), JSON.stringify({ first: message("Premier") }));
|
||||
expect(checkCatalogs(temporary, "extension").find((report) => report.name === "extension/fr").errors).toEqual([
|
||||
"added: missing key",
|
||||
]);
|
||||
expect(main(["--extension"], temporary)).toBe(1);
|
||||
expect(error).toHaveBeenCalledWith("ERROR extension/fr: added: missing key");
|
||||
fs.writeFileSync(
|
||||
path.join(directory, "fr/messages.json"),
|
||||
JSON.stringify({ first: message("Premier"), added: message("Nouveau") }),
|
||||
);
|
||||
expect(main(["--extension"], temporary)).toBe(0);
|
||||
fs.writeFileSync(english, "{}");
|
||||
expect(() => checkCatalogs(temporary, "extension")).toThrow("English locale must contain messages");
|
||||
const withoutEnglish = path.join(temporary, "without-english");
|
||||
fs.mkdirSync(path.join(withoutEnglish, "Extensions/combined/_locales/fr"), { recursive: true });
|
||||
expect(() => checkCatalogs(withoutEnglish, "extension")).toThrow("English locale is missing");
|
||||
} finally {
|
||||
log.mockRestore();
|
||||
error.mockRestore();
|
||||
const actual = fs.realpathSync(temporary);
|
||||
expect(path.dirname(actual)).toBe(fs.realpathSync(os.tmpdir()));
|
||||
expect(path.basename(actual).startsWith("ryd-locales-test-")).toBe(true);
|
||||
fs.rmSync(actual, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user