logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: c059f4a7ee16c0128c348c43c9d468e7cfdb5ef7
parent e0b8ad9f141f418ab3d8ebc7a9e68bcb755c820a
Author: Henry Jameson <me@hjkos.com>
Date:   Mon, 13 Nov 2023 17:26:53 +0200

Merge remote-tracking branch 'origin/develop' into notifications-thru-sw

Diffstat:

MCHANGELOG.md25+++++++++++++++++++++++++
Dchangelog.d/add-taiwanese-aka-hokkien-i18n-support.add2--
Dchangelog.d/adminfe.add1-
Dchangelog.d/check-changelog.skip0
Dchangelog.d/custom-emoji-notif-width.fix1-
Dchangelog.d/edit-profile-button.fix1-
Dchangelog.d/emoji-picker-button-accessible.fix1-
Dchangelog.d/export-subst-hash.fix1-
Achangelog.d/extra-notifications.add1+
Achangelog.d/fix-admin-crash-when-no-primary-fe-set.fix1+
Dchangelog.d/html-attribute-parsing.fix1-
Dchangelog.d/mention-twice.fix1-
Dchangelog.d/mentionsline-shouldbreak.fix1-
Dchangelog.d/nonascii-tags.fix1-
Dchangelog.d/oauth2-token-linger.fix1-
Dchangelog.d/parser.fix1-
Dchangelog.d/quote-hide-oops.fix1-
Dchangelog.d/quote-hide.fix1-
Dchangelog.d/quote.add1-
Dchangelog.d/react-button-safari.fix1-
Dchangelog.d/react-button.fix1-
Achangelog.d/react-more-actions-fix.fix1+
Dchangelog.d/reload-user-pinned.fix1-
Dchangelog.d/scroll-emoji-selector-safari.fix1-
Achangelog.d/show-recent-scrobble.skip1+
Mpackage.json2+-
Msrc/components/emoji_input/emoji_input.js3++-
Msrc/components/emoji_picker/emoji_picker.vue2+-
Msrc/components/extra_buttons/extra_buttons.js13++++++++++++-
Msrc/components/extra_buttons/extra_buttons.vue19++++++++++++++++++-
Asrc/components/extra_notifications/extra_notifications.js48++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/extra_notifications/extra_notifications.vue113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/components/interactions/interactions.vue1+
Msrc/components/mobile_nav/mobile_nav.js7+++++--
Msrc/components/notifications/notifications.js23++++++++++++++++++++---
Msrc/components/notifications/notifications.vue11+++++++++--
Msrc/components/poll/poll.js3++-
Msrc/components/post_status_form/post_status_form.js3++-
Msrc/components/react_button/react_button.vue2++
Msrc/components/report/report.js5++++-
Msrc/components/settings_modal/admin_tabs/frontends_tab.vue4++--
Msrc/components/settings_modal/tabs/filtering_tab.vue5+++++
Msrc/components/settings_modal/tabs/notifications_tab.vue41+++++++++++++++++++++++++++++++++++++++++
Msrc/components/status/status.js12++++++++++--
Msrc/components/status/status.vue18++++++++++++++++++
Msrc/i18n/en.json17+++++++++++++++--
Msrc/i18n/eo.json9++++++---
Msrc/i18n/ko.json144++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/i18n/nan-TW.json580+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/i18n/uk.json158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/modules/config.js6++++++
Msrc/modules/instance.js5+++++
Msrc/modules/statuses.js17+++++++++++++++++
Msrc/services/api/api.service.js19+++++++++++++++++++
Msrc/services/notification_utils/notification_utils.js14++++++++++++++
Asrc/services/random_seed/random_seed.service.js3+++
Atools/collect-changelog27+++++++++++++++++++++++++++
57 files changed, 1296 insertions(+), 87 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -3,6 +3,31 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 2.6.0 +### Added +- add the initial i18n translation file for Taiwanese (Hokkien), and modify some related files. +- Implemented a very basic instance administration screen +- Implement quoting + +### Fixed +- Keep aspect ratio of custom emoji reaction in notification +- Fix openSettingsModalTab so that it correctly opens Settings modal instead of Admin modal +- Add alt text to emoji picker buttons +- Use export-subst gitattribute to allow tarball builds +- fix reports now showing reason/content +- Fix HTML attribute parsing, discard attributes not strating with a letter +- Make MentionsLine aware of line breaking by non-br elements +- Fix a bug where mentioning a user twice will not fill the mention into the textarea +- Fix parsing non-ascii tags +- Fix OAuth2 token lingering after revocation +- fix regex issue in HTML parser/renderer +- don't display quoted status twice +- fix typo in code that prevented cards from showing at all +- Fix react button not working if reaction accounts are not loaded +- Fix react button misalignment on safari ios +- Fix pinned statuses gone when reloading user timeline +- Fix scrolling emoji selector in modal in safari ios + ## 2.5.1 ### Fixed - Checkboxes in settings can now work with screenreaders diff --git a/changelog.d/add-taiwanese-aka-hokkien-i18n-support.add b/changelog.d/add-taiwanese-aka-hokkien-i18n-support.add @@ -1 +0,0 @@ -add the initial i18n translation file for Taiwanese (Hokkien), and modify some related files. -\ No newline at end of file diff --git a/changelog.d/adminfe.add b/changelog.d/adminfe.add @@ -1 +0,0 @@ -Implemented a very basic instance administration screen diff --git a/changelog.d/check-changelog.skip b/changelog.d/check-changelog.skip diff --git a/changelog.d/custom-emoji-notif-width.fix b/changelog.d/custom-emoji-notif-width.fix @@ -1 +0,0 @@ -Keep aspect ratio of custom emoji reaction in notification diff --git a/changelog.d/edit-profile-button.fix b/changelog.d/edit-profile-button.fix @@ -1 +0,0 @@ -Fix openSettingsModalTab so that it correctly opens Settings modal instead of Admin modal diff --git a/changelog.d/emoji-picker-button-accessible.fix b/changelog.d/emoji-picker-button-accessible.fix @@ -1 +0,0 @@ -Add alt text to emoji picker buttons diff --git a/changelog.d/export-subst-hash.fix b/changelog.d/export-subst-hash.fix @@ -1 +0,0 @@ -Use export-subst gitattribute to allow tarball builds diff --git a/changelog.d/extra-notifications.add b/changelog.d/extra-notifications.add @@ -0,0 +1 @@ +Support showing extra notifications in the notifications column diff --git a/changelog.d/fix-admin-crash-when-no-primary-fe-set.fix b/changelog.d/fix-admin-crash-when-no-primary-fe-set.fix @@ -0,0 +1 @@ +Fix frontend admin tab crashing when no primary frontend is set diff --git a/changelog.d/html-attribute-parsing.fix b/changelog.d/html-attribute-parsing.fix @@ -1 +0,0 @@ -Fix HTML attribute parsing, discard attributes not strating with a letter diff --git a/changelog.d/mention-twice.fix b/changelog.d/mention-twice.fix @@ -1 +0,0 @@ -Fix a bug where mentioning a user twice will not fill the mention into the textarea diff --git a/changelog.d/mentionsline-shouldbreak.fix b/changelog.d/mentionsline-shouldbreak.fix @@ -1 +0,0 @@ -Make MentionsLine aware of line breaking by non-br elements diff --git a/changelog.d/nonascii-tags.fix b/changelog.d/nonascii-tags.fix @@ -1 +0,0 @@ -Fix parsing non-ascii tags diff --git a/changelog.d/oauth2-token-linger.fix b/changelog.d/oauth2-token-linger.fix @@ -1 +0,0 @@ -Fix OAuth2 token lingering after revocation diff --git a/changelog.d/parser.fix b/changelog.d/parser.fix @@ -1 +0,0 @@ -fix regex issue in HTML parser/renderer diff --git a/changelog.d/quote-hide-oops.fix b/changelog.d/quote-hide-oops.fix @@ -1 +0,0 @@ -fix typo in code that prevented cards from showing at all diff --git a/changelog.d/quote-hide.fix b/changelog.d/quote-hide.fix @@ -1 +0,0 @@ -don't display quoted status twice diff --git a/changelog.d/quote.add b/changelog.d/quote.add @@ -1 +0,0 @@ -Implement quoting diff --git a/changelog.d/react-button-safari.fix b/changelog.d/react-button-safari.fix @@ -1 +0,0 @@ -Fix react button misalignment on safari ios diff --git a/changelog.d/react-button.fix b/changelog.d/react-button.fix @@ -1 +0,0 @@ -Fix react button not working if reaction accounts are not loaded diff --git a/changelog.d/react-more-actions-fix.fix b/changelog.d/react-more-actions-fix.fix @@ -0,0 +1 @@ +Add aria attributes to react and extra buttons diff --git a/changelog.d/reload-user-pinned.fix b/changelog.d/reload-user-pinned.fix @@ -1 +0,0 @@ -Fix pinned statuses gone when reloading user timeline diff --git a/changelog.d/scroll-emoji-selector-safari.fix b/changelog.d/scroll-emoji-selector-safari.fix @@ -1 +0,0 @@ -Fix scrolling emoji selector in modal in safari ios diff --git a/changelog.d/show-recent-scrobble.skip b/changelog.d/show-recent-scrobble.skip @@ -0,0 +1 @@ +Shows the most recent scrobble under each post when available diff --git a/package.json b/package.json @@ -1,6 +1,6 @@ { "name": "pleroma_fe", - "version": "2.5.0", + "version": "2.6.0", "description": "Pleroma frontend, the default frontend of Pleroma social network server", "author": "Pleroma contributors <https://git.pleroma.social/pleroma/pleroma-fe/-/blob/develop/CONTRIBUTORS.md>", "private": false, diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js @@ -1,4 +1,5 @@ import Completion from '../../services/completion/completion.js' +import genRandomSeed from '../../services/random_seed/random_seed.service.js' import EmojiPicker from '../emoji_picker/emoji_picker.vue' import Popover from 'src/components/popover/popover.vue' import ScreenReaderNotice from 'src/components/screen_reader_notice/screen_reader_notice.vue' @@ -110,7 +111,7 @@ const EmojiInput = { }, data () { return { - randomSeed: `${Math.random()}`.replace('.', '-'), + randomSeed: genRandomSeed(), input: undefined, caretEl: undefined, highlighted: -1, diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue @@ -3,7 +3,7 @@ ref="popover" trigger="click" popover-class="emoji-picker popover-default" - :trigger-attrs="{ 'aria-hidden': true }" + :trigger-attrs="{ 'aria-hidden': true, tabindex: -1 }" @show="onPopoverShown" @close="onPopoverClosed" > diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js @@ -1,4 +1,5 @@ import Popover from '../popover/popover.vue' +import genRandomSeed from '../../services/random_seed/random_seed.service.js' import ConfirmModal from '../confirm_modal/confirm_modal.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { @@ -40,7 +41,8 @@ const ExtraButtons = { data () { return { expanded: false, - showingDeleteDialog: false + showingDeleteDialog: false, + randomSeed: genRandomSeed() } }, methods: { @@ -152,6 +154,15 @@ const ExtraButtons = { editingAvailable () { return this.$store.state.instance.editingAvailable }, shouldConfirmDelete () { return this.$store.getters.mergedConfig.modalOnDelete + }, + triggerAttrs () { + return { + title: this.$t('status.more_actions'), + id: `popup-trigger-${this.randomSeed}`, + 'aria-controls': `popup-menu-${this.randomSeed}`, + 'aria-expanded': this.expanded, + 'aria-haspopup': 'menu' + } } } } diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue @@ -2,6 +2,7 @@ <Popover class="ExtraButtons" trigger="click" + :trigger-attrs="triggerAttrs" placement="top" :offset="{ y: 5 }" :bound-to="{ x: 'container' }" @@ -10,10 +11,15 @@ @close="onClose" > <template #content="{close}"> - <div class="dropdown-menu"> + <div + class="dropdown-menu" + role="menu" + :id="`popup-menu-${randomSeed}`" + > <button v-if="canMute && !status.thread_muted" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="muteConversation" > <FAIcon @@ -24,6 +30,7 @@ <button v-if="canMute && status.thread_muted" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="unmuteConversation" > <FAIcon @@ -34,6 +41,7 @@ <button v-if="!status.pinned && canPin" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="pinStatus" @click="close" > @@ -45,6 +53,7 @@ <button v-if="status.pinned && canPin" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="unpinStatus" @click="close" > @@ -57,6 +66,7 @@ <button v-if="!status.bookmarked" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="bookmarkStatus" @click="close" > @@ -68,6 +78,7 @@ <button v-if="status.bookmarked" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="unbookmarkStatus" @click="close" > @@ -80,6 +91,7 @@ <button v-if="ownStatus && editingAvailable" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="editStatus" @click="close" > @@ -91,6 +103,7 @@ <button v-if="isEdited && editingAvailable" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="showStatusHistory" @click="close" > @@ -102,6 +115,7 @@ <button v-if="canDelete" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="deleteStatus" @click="close" > @@ -112,6 +126,7 @@ </button> <button class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="copyLink" @click="close" > @@ -123,6 +138,7 @@ <a v-if="!status.is_local" class="button-default dropdown-item dropdown-item-icon" + role="menuitem" title="Source" :href="status.external_url" target="_blank" @@ -134,6 +150,7 @@ </a> <button class="button-default dropdown-item dropdown-item-icon" + role="menuitem" @click.prevent="reportStatus" @click="close" > diff --git a/src/components/extra_notifications/extra_notifications.js b/src/components/extra_notifications/extra_notifications.js @@ -0,0 +1,48 @@ +import { mapGetters } from 'vuex' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faUserPlus, + faComments, + faBullhorn +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faUserPlus, + faComments, + faBullhorn +) + +const ExtraNotifications = { + computed: { + shouldShowChats () { + return this.mergedConfig.showExtraNotifications && this.mergedConfig.showChatsInExtraNotifications && this.unreadChatCount + }, + shouldShowAnnouncements () { + return this.mergedConfig.showExtraNotifications && this.mergedConfig.showAnnouncementsInExtraNotifications && this.unreadAnnouncementCount + }, + shouldShowFollowRequests () { + return this.mergedConfig.showExtraNotifications && this.mergedConfig.showFollowRequestsInExtraNotifications && this.followRequestCount + }, + hasAnythingToShow () { + return this.shouldShowChats || this.shouldShowAnnouncements || this.shouldShowFollowRequests + }, + shouldShowCustomizationTip () { + return this.mergedConfig.showExtraNotificationsTip && this.hasAnythingToShow + }, + currentUser () { + return this.$store.state.users.currentUser + }, + ...mapGetters(['unreadChatCount', 'unreadAnnouncementCount', 'followRequestCount', 'mergedConfig']) + }, + methods: { + openNotificationSettings () { + return this.$store.dispatch('openSettingsModalTab', 'notifications') + }, + dismissConfigurationTip () { + return this.$store.dispatch('setOption', { name: 'showExtraNotificationsTip', value: false }) + } + } +} + +export default ExtraNotifications diff --git a/src/components/extra_notifications/extra_notifications.vue b/src/components/extra_notifications/extra_notifications.vue @@ -0,0 +1,113 @@ +<template> + <div class="ExtraNotifications"> + <div + v-if="shouldShowChats" + class="notification unseen" + > + <div class="notification-overlay" /> + <router-link + class="button-unstyled -link extra-notification" + :to="{ name: 'chats', params: { username: currentUser.screen_name } }" + > + <FAIcon + fixed-width + class="fa-scale-110 icon" + icon="comments" + /> + {{ $tc('notifications.unread_chats', unreadChatCount, { num: unreadChatCount }) }} + </router-link> + </div> + <div + v-if="shouldShowAnnouncements" + class="notification unseen" + > + <div class="notification-overlay" /> + <router-link + class="button-unstyled -link extra-notification" + :to="{ name: 'announcements' }" + > + <FAIcon + fixed-width + class="fa-scale-110 icon" + icon="bullhorn" + /> + {{ $tc('notifications.unread_announcements', unreadAnnouncementCount, { num: unreadAnnouncementCount }) }} + </router-link> + </div> + <div + v-if="shouldShowFollowRequests" + class="notification unseen" + > + <div class="notification-overlay" /> + <router-link + class="button-unstyled -link extra-notification" + :to="{ name: 'friend-requests' }" + > + <FAIcon + fixed-width + class="fa-scale-110 icon" + icon="user-plus" + /> + {{ $tc('notifications.unread_follow_requests', followRequestCount, { num: followRequestCount }) }} + </router-link> + </div> + <i18n-t + v-if="shouldShowCustomizationTip" + tag="span" + class="notification tip extra-notification" + keypath="notifications.configuration_tip" + > + <template #theSettings> + <button + class="button-unstyled -link" + @click="openNotificationSettings" + > + {{ $t('notifications.configuration_tip_settings') }} + </button> + </template> + <template #dismiss> + <button + class="button-unstyled -link" + @click="dismissConfigurationTip" + > + {{ $t('notifications.configuration_tip_dismiss') }} + </button> + </template> + </i18n-t> + </div> +</template> + +<script src="./extra_notifications.js" /> + +<style lang="scss"> +@import "../../variables"; + +.ExtraNotifications { + width: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + + .notification { + width: 100%; + border-bottom: 1px solid; + border-color: $fallback--border; + border-color: var(--border, $fallback--border); + display: flex; + flex-direction: column; + align-items: stretch; + } + + .extra-notification { + padding: 1em; + } + + .icon { + margin-right: 0.5em; + } + + .tip { + display: inline; + } +} +</style> diff --git a/src/components/interactions/interactions.vue b/src/components/interactions/interactions.vue @@ -39,6 +39,7 @@ <Notifications ref="notifications" :no-heading="true" + :no-extra="true" :minimal-mode="true" :filter-mode="filterMode" /> diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js @@ -1,7 +1,10 @@ import SideDrawer from '../side_drawer/side_drawer.vue' import Notifications from '../notifications/notifications.vue' import ConfirmModal from '../confirm_modal/confirm_modal.vue' -import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils' +import { + unseenNotificationsFromStore, + countExtraNotifications +} from '../../services/notification_utils/notification_utils' import GestureService from '../../services/gesture_service/gesture_service' import NavigationPins from 'src/components/navigation/navigation_pins.vue' import { mapGetters } from 'vuex' @@ -50,7 +53,7 @@ const MobileNav = { return unseenNotificationsFromStore(this.$store) }, unseenNotificationsCount () { - return this.unseenNotifications.length + return this.unseenNotifications.length + countExtraNotifications(this.$store) }, hideSitename () { return this.$store.state.instance.hideSitename }, sitename () { return this.$store.state.instance.name }, diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js @@ -1,12 +1,14 @@ import { computed } from 'vue' import { mapGetters } from 'vuex' import Notification from '../notification/notification.vue' +import ExtraNotifications from '../extra_notifications/extra_notifications.vue' import NotificationFilters from './notification_filters.vue' import notificationsFetcher from '../../services/notifications_fetcher/notifications_fetcher.service.js' import { notificationsFromStore, filteredNotificationsFromStore, - unseenNotificationsFromStore + unseenNotificationsFromStore, + countExtraNotifications } from '../../services/notification_utils/notification_utils.js' import FaviconService from '../../services/favicon_service/favicon_service.js' import { library } from '@fortawesome/fontawesome-svg-core' @@ -23,7 +25,8 @@ const DEFAULT_SEEN_TO_DISPLAY_COUNT = 30 const Notifications = { components: { Notification, - NotificationFilters + NotificationFilters, + ExtraNotifications }, props: { // Disables panel styles, unread mark, potentially other notification-related actions @@ -31,6 +34,11 @@ const Notifications = { minimalMode: Boolean, // Custom filter mode, an array of strings, possible values 'mention', 'repeat', 'like', 'follow', used to override global filter for use in "Interactions" timeline filterMode: Array, + // Do not show extra notifications + noExtra: { + type: Boolean, + default: false + }, // Disable teleporting (i.e. for /users/user/notifications) disableTeleport: Boolean }, @@ -65,11 +73,17 @@ const Notifications = { filteredNotifications () { return filteredNotificationsFromStore(this.$store, this.filterMode) }, + unseenCountBadgeText () { + return `${this.unseenCount ? this.unseenCount : ''}${this.extraNotificationsCount ? '*' : ''}` + }, unseenCount () { return this.unseenNotifications.length }, + extraNotificationsCount () { + return countExtraNotifications(this.$store) + }, unseenCountTitle () { - return this.unseenCount + (this.unreadChatCount) + this.unreadAnnouncementCount + return this.unseenNotifications.length + (this.unreadChatCount) + this.unreadAnnouncementCount }, loading () { return this.$store.state.statuses.notifications.loading @@ -94,6 +108,9 @@ const Notifications = { return this.filteredNotifications.slice(0, this.unseenCount + this.seenToDisplayCount) }, noSticky () { return this.$store.getters.mergedConfig.disableStickyHeaders }, + showExtraNotifications () { + return !this.noExtra + }, ...mapGetters(['unreadChatCount', 'unreadAnnouncementCount']) }, mounted () { diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue @@ -17,9 +17,9 @@ <div class="title"> {{ $t('notifications.notifications') }} <span - v-if="unseenCount" + v-if="unseenCountBadgeText" class="badge badge-notification unseen-count" - >{{ unseenCount }}</span> + >{{ unseenCountBadgeText }}</span> </div> <div v-if="showScrollTop" @@ -55,6 +55,13 @@ role="feed" > <div + v-if="showExtraNotifications" + role="listitem" + class="notification" + > + <extra-notifications /> + </div> + <div v-for="notification in notificationsToDisplay" :key="notification.id" role="listitem" diff --git a/src/components/poll/poll.js b/src/components/poll/poll.js @@ -1,4 +1,5 @@ import Timeago from 'components/timeago/timeago.vue' +import genRandomSeed from '../../services/random_seed/random_seed.service.js' import RichContent from 'components/rich_content/rich_content.jsx' import { forEach, map } from 'lodash' @@ -13,7 +14,7 @@ export default { return { loading: false, choices: [], - randomSeed: `${Math.random()}`.replace('.', '-') + randomSeed: genRandomSeed() } }, created () { diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js @@ -1,4 +1,5 @@ import statusPoster from '../../services/status_poster/status_poster.service.js' +import genRandomSeed from '../../services/random_seed/random_seed.service.js' import MediaUpload from '../media_upload/media_upload.vue' import ScopeSelector from '../scope_selector/scope_selector.vue' import EmojiInput from '../emoji_input/emoji_input.vue' @@ -162,7 +163,7 @@ const PostStatusForm = { } return { - randomSeed: `${Math.random()}`.replace('.', '-'), + randomSeed: genRandomSeed(), dropFiles: [], uploadingFiles: false, error: null, diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue @@ -11,6 +11,8 @@ /> <span class="button-unstyled popover-trigger" + role="button" + :tabindex="0" :title="$t('tool_tip.add_reaction')" @click.stop.prevent="show" > diff --git a/src/components/report/report.js b/src/components/report/report.js @@ -1,6 +1,7 @@ import Select from '../select/select.vue' import StatusContent from '../status_content/status_content.vue' import Timeago from '../timeago/timeago.vue' +import RichContent from 'src/components/rich_content/rich_content.jsx' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' const Report = { @@ -10,10 +11,12 @@ const Report = { components: { Select, StatusContent, - Timeago + Timeago, + RichContent }, computed: { report () { + console.log(this.$store.state.reports.reports[this.reportId] || {}) return this.$store.state.reports.reports[this.reportId] || {} }, state: { diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.vue b/src/components/settings_modal/admin_tabs/frontends_tab.vue @@ -33,9 +33,9 @@ > <strong>{{ frontend.name }}</strong> {{ ' ' }} - <span v-if="adminDraft[':pleroma'][':frontends'][':primary'].name === frontend.name"> + <span v-if="adminDraft[':pleroma'][':frontends'][':primary']?.name === frontend.name"> <i18n-t - v-if="adminDraft[':pleroma'][':frontends'][':primary'].ref === frontend.refs[0]" + v-if="adminDraft[':pleroma'][':frontends'][':primary']?.ref === frontend.refs[0]" keypath="admin_dash.frontend.is_default" /> <i18n-t diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue @@ -91,6 +91,11 @@ {{ $t('settings.hide_attachments_in_convo') }} </BooleanSetting> </li> + <li> + <BooleanSetting path="hideScrobbles"> + {{ $t('settings.hide_scrobbles') }} + </BooleanSetting> + </li> </ul> </div> <div diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue @@ -51,6 +51,47 @@ </li> </ul> </li> + <li> + <BooleanSetting path="showExtraNotifications"> + {{ $t('settings.notification_show_extra') }} + </BooleanSetting> + </li> + <li> + <ul class="setting-list suboptions"> + <li> + <BooleanSetting + path="showChatsInExtraNotifications" + :disabled="!mergedConfig.showExtraNotifications" + > + {{ $t('settings.notification_extra_chats') }} + </BooleanSetting> + </li> + <li> + <BooleanSetting + path="showAnnouncementsInExtraNotifications" + :disabled="!mergedConfig.showExtraNotifications" + > + {{ $t('settings.notification_extra_announcements') }} + </BooleanSetting> + </li> + <li> + <BooleanSetting + path="showFollowRequestsInExtraNotifications" + :disabled="!mergedConfig.showExtraNotifications" + > + {{ $t('settings.notification_extra_follow_requests') }} + </BooleanSetting> + </li> + <li> + <BooleanSetting + path="showExtraNotificationsTip" + :disabled="!mergedConfig.showExtraNotifications" + > + {{ $t('settings.notification_extra_tip') }} + </BooleanSetting> + </li> + </ul> + </li> </ul> </div> diff --git a/src/components/status/status.js b/src/components/status/status.js @@ -39,7 +39,8 @@ import { faThumbtack, faChevronUp, faChevronDown, - faAngleDoubleRight + faAngleDoubleRight, + faPlay } from '@fortawesome/free-solid-svg-icons' library.add( @@ -59,7 +60,8 @@ library.add( faThumbtack, faChevronUp, faChevronDown, - faAngleDoubleRight + faAngleDoubleRight, + faPlay ) const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1) @@ -415,6 +417,12 @@ const Status = { }, shouldDisplayQuote () { return this.quotedStatus && this.displayQuote + }, + scrobblePresent () { + return !this.mergedConfig.hideScrobbles && this.status.user.latestScrobble && this.status.user.latestScrobble.artist + }, + scrobble () { + return this.status.user.latestScrobble } }, methods: { diff --git a/src/components/status/status.vue b/src/components/status/status.vue @@ -249,6 +249,24 @@ </button> </span> </div> + <div class="status-rich-presence" v-if="scrobblePresent"> + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="music" + /> + {{ scrobble.artist }} — {{ scrobble.title }} + <FAIcon + class="fa-scale-110 fa-old-padding" + icon="play" + /> + <span class="status-rich-presence-time"> + <Timeago + template-key="time.in_past" + :time="scrobble.created_at" + :auto-update="60" + /> + </span> + </div> <div v-if="isReply || hasMentionsLine" class="heading-reply-row" diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -205,7 +205,13 @@ "migrated_to": "migrated to", "reacted_with": "reacted with {0}", "submitted_report": "submitted a report", - "poll_ended": "poll has ended" + "poll_ended": "poll has ended", + "unread_announcements": "{num} unread announcement | {num} unread announcements", + "unread_chats": "{num} unread chat | {num} unread chats", + "unread_follow_requests": "{num} new follow request | {num} new follow requests", + "configuration_tip": "You can customize what to display here in {theSettings}. {dismiss}", + "configuration_tip_settings": "the settings", + "configuration_tip_dismiss": "Do not show again" }, "polls": { "add_poll": "Add poll", @@ -489,6 +495,7 @@ "hide_muted_posts": "Hide posts of muted users", "mute_bot_posts": "Mute bot posts", "hide_bot_indication": "Hide bot indication in posts", + "hide_scrobbles": "Hide scrobbles", "hide_all_muted_posts": "Hide muted posts", "max_thumbnails": "Maximum amount of thumbnails per post (empty = no limit)", "hide_isp": "Hide instance-specific panel", @@ -561,6 +568,11 @@ "notification_visibility_moves": "User Migrates", "notification_visibility_emoji_reactions": "Reactions", "notification_visibility_polls": "Ends of polls you voted in", + "notification_show_extra": "Show extra notifications in the notifications column", + "notification_extra_chats": "Show unread chats", + "notification_extra_announcements": "Show unread announcements", + "notification_extra_follow_requests": "Show new follow requests", + "notification_extra_tip": "Show the customization tip for extra notifications", "no_rich_text_description": "Strip rich text formatting from all posts", "no_blocks": "No blocks", "no_mutes": "No mutes", @@ -1033,7 +1045,8 @@ "reaction_count_label": "{num} person reacted | {num} people reacted", "hide_quote": "Hide the quoted status", "display_quote": "Display the quoted status", - "invisible_quote": "Quoted status unavailable: {link}" + "invisible_quote": "Quoted status unavailable: {link}", + "more_actions": "More actions on this status" }, "user_card": { "approve": "Approve", diff --git a/src/i18n/eo.json b/src/i18n/eo.json @@ -172,12 +172,14 @@ "direct_warning_to_first_only": "Ĉi tiu afiŝo estas nur videbla al uzantoj menciitaj je la komenco de la mesaĝo.", "direct_warning_to_all": "Ĉi tiu afiŝo estos videbla al ĉiuj menciitaj uzantoj.", "media_description": "Priskribo de vidaŭdaĵo", - "post": "Afiŝo", + "post": "Afiŝi", "edit_remote_warning": "Aliaj foraj nodoj eble ne subtenas redaktadon, kaj ne povos ricevi pli novan version de via afiŝo.", "edit_unsupported_warning": "Pleroma ne subtenas redaktadon de mencioj aŭ enketoj.", "edit_status": "Redakti afiŝon", "content_type_selection": "Formo de afiŝo", - "scope_notice_dismiss": "Fermi ĉi tiun avizon" + "scope_notice_dismiss": "Fermi ĉi tiun avizon", + "reply_option": "Respondi al ĉi tiu afiŝo", + "quote_option": "Citi ĉi tiun afiŝon" }, "registration": { "bio": "Priskribo", @@ -873,7 +875,8 @@ "symbols": "Simboloj", "travel-and-places": "Vojaĝoj kaj lokoj" }, - "regional_indicator": "Regiona marko {letter}" + "regional_indicator": "Regiona marko {letter}", + "unpacked": "Malpakitaj bildosignoj" }, "polls": { "not_enough_options": "Tro malmultaj unikaj elektebloj en la enketo", diff --git a/src/i18n/ko.json b/src/i18n/ko.json @@ -558,7 +558,7 @@ "discoverable": "검색 결과나 다른 서비스들에서 이 계정을 찾을 수 있도록 허용", "pad_emoji": "에모지를 선택창에서 고를 때 띄어쓰기를 집어넣기", "wordfilter": "단어 필터", - "word_filter_and_more": "단어 필터 그리고 더보기...", + "word_filter_and_more": "단어 필터 및 기타 설정...", "accent": "강조", "hide_media_previews": "미디어 미리보기 숨기기", "max_thumbnails": "게시물 하나 당 최대로 보여질 섬네일 개수 (비워두면 제한을 두지 않습니다)", @@ -686,7 +686,15 @@ "remove_language": "삭제", "primary_language": "주 언어:", "fallback_language": "보조 언어 {index}:", - "confirm_dialogs_logout": "로그아웃" + "confirm_dialogs_logout": "로그아웃", + "url": "URL", + "preview": "미리보기", + "commit_value": "저장", + "commit_value_tooltip": "값이 저장되지 않았습니다, 버튼을 눌러 변경사항을 반영하세요", + "reset_value": "초기화", + "reset_value_tooltip": "변경사항 초기화", + "hard_reset_value": "완전 초기화", + "hard_reset_value_tooltip": "스토리지에서 설정을 제거하고, 기본값을 사용하도록 강제합니다" }, "timeline": { "collapse": "접기", @@ -703,7 +711,8 @@ "no_more_statuses": "새 게시물 없음", "socket_reconnected": "실시간 연결 됨", "socket_broke": "실시간 연결이 끊어짐: CloseEvent 코드 {0}", - "quick_filter_settings": "빠른 필터 설정" + "quick_filter_settings": "빠른 필터 설정", + "quick_view_settings": "빠른 뷰 설정" }, "user_card": { "approve": "승인", @@ -774,7 +783,33 @@ "approve_confirm_accept_button": "승인", "approve_confirm_cancel_button": "승인 안 함", "approve_confirm": "{user}의 팔로우 요청을 승인할까요?", - "block_confirm_title": "차단 확인" + "block_confirm_title": "차단 확인", + "note": "노트", + "unfollow_confirm": "정말 {user}를 팔로우 해제하시겠습니까?", + "unfollow_confirm_accept_button": "팔로우 해제", + "unfollow_confirm_cancel_button": "취소", + "remove_follower_confirm_title": "팔로워 삭제 확인", + "remove_follower_confirm_cancel_button": "냅두기", + "remove_follower_confirm_accept_button": "치우기", + "edit_note_cancel": "취소", + "birthday": "{birthday}에 태어남", + "edit_note": "노트 수정", + "edit_note_apply": "적용", + "deny_confirm_cancel_button": "취소", + "unfollow_confirm_title": "팔로우 해제 확인", + "mute_confirm_accept_button": "뮤트", + "remove_follower_confirm": "정말 {user}를 팔로워에서 치울까요?", + "deny_confirm_accept_button": "거절", + "mute_confirm_title": "뮤트 확인", + "mute_confirm": "정말 {user}를 뮤트할까요?", + "block_confirm_cancel_button": "취소", + "deny_confirm_title": "거절 확인", + "block_confirm": "정말 {user}를 차단할까요?", + "block_confirm_accept_button": "차단", + "mute_confirm_cancel_button": "취소", + "mute_duration_prompt": "이 사용자를 뮤트할 시간 (0으로 두면 무한히):", + "deny_confirm": "{user}의 팔로 요청을 거절할까요?", + "note_blank": "(없음)" }, "user_profile": { "timeline_title": "사용자 타임라인", @@ -794,7 +829,10 @@ "add_reaction": "반응 추가", "accept_follow_request": "팔로우 요청 승인", "reject_follow_request": "팔로우 요청 거절", - "bookmark": "북마크" + "bookmark": "북마크", + "autocomplete_available": "{number}개의 결과가 있습니다. 위 또는 아래 화살표 키로 탐색할 수 있습니다. | {number}개의 결과가 있습니다. 위 또는 아래 화살표 키로 탐색할 수 있습니다.", + "toggle_expand": "알림을 펼치거나 접어서 전체 게시물을 보기", + "toggle_mute": "알림을 펼치거나 접어서 뮤트한 내용 보기" }, "upload": { "error": { @@ -840,7 +878,8 @@ "symbols": "기호" }, "keep_open": "열린 채로 두기", - "regional_indicator": "지역 표시기 {letter}" + "regional_indicator": "지역 표시기 {letter}", + "unpacked": "미분류 에모지" }, "polls": { "add_poll": "투표를 추가", @@ -1049,7 +1088,8 @@ "update_changelog_here": "변경 내역", "update_changelog": "무엇이 바뀌었는지 자세히 알아보시려면, {theFullChangelog}을 참조하세요.", "big_update_content": "저희가 한동안 릴리즈를 안 해서, 익숙하셨던 생김새나 경험과 많이 달라졌을 수 있습니다.", - "update_bugs": "저희가 비록 테스트를 많이 하고 직접 개발 버전을 쓰기도 하지만, 많이 바꾸기도 했고, 몇몇 가지 놓친 점들이 있을 터이니, 사용하면서 불편한 점이나 문제는 {pleromaGitlab}에 제보해주시면 감사하겠습니다. 저희는 겪으신 문제점이나 Pleroma와 Pleroma-FE에 대한 피드백과 제안을 환영합니다." + "update_bugs": "저희가 비록 테스트를 많이 하고 직접 개발 버전을 쓰기도 하지만, 많이 바꾸기도 했고, 몇몇 가지 놓친 점들이 있을 터이니, 사용하면서 불편한 점이나 문제는 {pleromaGitlab}에 제보해주시면 감사하겠습니다. 저희는 겪으신 문제점이나 Pleroma와 Pleroma-FE에 대한 피드백과 제안을 환영합니다.", + "art_by": "{linkToArtist} 그림" }, "unicode_domain_indicator": { "tooltip": "이 도메인은 아스키 문자가 아닌 문자를 포함하고 있습니다." @@ -1115,7 +1155,9 @@ "repeat_confirm_cancel_button": "리핏 안 함", "delete_confirm_title": "삭제 확인", "delete_confirm_accept_button": "삭제", - "delete_confirm_cancel_button": "냅두기" + "delete_confirm_cancel_button": "냅두기", + "delete_error": "게시물 삭제 에러: {0}", + "reaction_count_label": "{num}명이 반응함 | {num}명이 반응함" }, "errors": { "storage_unavailable": "Pleroma가 브라우저 저장소에 접근할 수 없습니다. 로그인이 풀리거나 로컬 설정이 초기화 되는 등 예상치 못한 문제를 겪을 수 있습니다. 쿠키를 활성화 해보세요." @@ -1159,5 +1201,91 @@ "submit_edit_action": "수정본 반영", "cancel_edit_action": "취소", "inactive_message": "이 공지사항은 비활성화 되었습니다" + }, + "admin_dash": { + "window_title": "관리", + "wip_notice": "이 관리자 대시보드는 실험적이며 개발 중에 있습니다, {adminFeLink}.", + "old_ui_link": "대신 구 관리자 UI를 사용할 수 있습니다", + "reset_all": "전부 초기화", + "commit_all": "전부 저장", + "tabs": { + "nodb": "DB 설정 불가", + "instance": "인스턴스", + "frontends": "프론트엔드", + "limits": "제한" + }, + "nodb": { + "heading": "데이터베이스 설정 기능이 비활성화 되어 있습니다", + "documentation": "관련 문서", + "text2": "대부분의 설정을 건드릴 수 없습니다.", + "text": "백엔드 설정 파일에서 {property}를 {value}로 바꿔야 합니다, {documentation}를 참고하세요." + }, + "captcha": { + "kocaptcha": "KoCaptcha", + "native": "내장" + }, + "instance": { + "registrations": "유저 가입", + "captcha_header": "캡차", + "kocaptcha": "KoCaptcha 설정", + "access": "인스턴스 접근", + "restrict": { + "timelines": "타임라인 접근", + "profiles": "사용자 프로필 접근", + "activities": "게시물/활동 접근", + "header": "로그인하지 않은 방문자의 접근을 제한", + "description": "특정 API의 접근을 허용할지 말지에 대한 세부 설정입니다. 기본적으로(애매한 체크 표시) 인스턴스가 비공개이면 접근을 차단합니다, 체크 표시는 인스턴스가 공개여도 차단함을 의미합니다, 체크 해제는 인스턴스가 비공개여도 접근을 허용함을 의미합니다. 설정을 바꾸면 예기치 않은 동작이 일어날 수 있음을 유의하세요, 예로 프로필 접근이 차단되면 프로필 정보 없이 게시물이 보여집니다." + }, + "instance": "인스턴스 정보" + }, + "limits": { + "arbitrary_limits": "임의 제한", + "posts": "게시물 제한", + "uploads": "첨부파일 제한", + "users": "사용자 프로필 제한", + "profile_fields": "프로필 필드 제한", + "user_uploads": "프로필 미디어 제한" + }, + "frontend": { + "repository": "리포지토리 링크", + "versions": "사용 가능한 버전", + "build_url": "빌드 URL", + "reinstall": "재설치", + "is_default": "(기본)", + "is_default_custom": "(기본, 버전: {version})", + "install": "설치", + "install_version": "설치된 버전 {version}", + "more_install_options": "설치 옵션 더 보기", + "more_default_options": "기본 설정 옵션 더 보기", + "set_default": "기본으로 설정", + "set_default_version": "버전 {version}을 기본으로 설정", + "wip_notice": "이 부분은 프론트엔드 관리에 대한 백엔드 구현이 미완성이기 때문에 개발 중이고 몇몇 기능이 빠져 있습니다.", + "default_frontend": "기본 프론트엔드", + "default_frontend_tip2": "개발 중: 아직 Pleroma 백엔드가 모든 설치된 프론트엔드 목록을 알려주지 않기 때문에 이름과 ref을 직접 입력해야 합니다. 아래에 있는 목록은 여기 값을 입력하기 위한 단축 버튼입니다.", + "available_frontends": "설치 가능", + "default_frontend_tip": "기본 프론트엔드는 모든 유저에게 보입니다. 현재로썬 유저가 개인적으로 프론트엔드를 선택할 수 있진 않습니다. PleromaFE에서 벗어난다면 저희가 완전히 대체할 때까지는 인스턴스 설정을 위해서 아마도 낡고 버그투성이인 AdminFE를 쓰셔야 할 겁니다." + }, + "temp_overrides": { + ":pleroma": { + ":instance": { + ":public": { + "label": "인스턴스를 공개", + "description": "이것을 끄면 모든 API가 로그인한 유저만 사용 가능하게 되며, 로그인하지 않은 사용자에겐 공개와 연합 타임라인이 보이지 않게 됩니다." + }, + ":limit_to_local_content": { + "label": "로컬 컨텐츠만 검색하도록 제한", + "description": "로그인하지 않은 사람 (기본값), 모두 또는 없음에게 전역 검색을 비활성화합니다" + }, + ":description_limit": { + "label": "글자수 제한", + "description": "첨부파일 설명문의 글자수 제한" + }, + ":background_image": { + "label": "배경 이미지", + "description": "배경 이미지 (주로 PleromaFE에서 쓰임)" + } + } + } + } } } diff --git a/src/i18n/nan-TW.json b/src/i18n/nan-TW.json @@ -248,12 +248,12 @@ "regional_indicator": "地區指引 {letter}" }, "errors": { - "storage_unavailable": "Pleroma buē-tàng the̍h 著瀏覽器儲存 ê。Lí ê 登入狀態抑是局部設定 buē 儲存,mā 凡勢 tú 著意料外 ê 問題。拍開 cookie 看覓。" + "storage_unavailable": "Pleroma buē-tàng the̍h 著瀏覽器儲存 ê。Lí ê 登入狀態抑是局部設定 buē 儲存,mā 凡勢 tú 著意料外 ê 問題。拍開 cookie 看māi。" }, "interactions": { "favs_repeats": "轉送 kap kah 意", "follows": "最近綴 lí ê", - "emoji_reactions": "繪文字 ê 回應", + "emoji_reactions": "繪文字 ê 反應", "reports": "檢舉", "moves": "用者 ê 移民", "load_older": "載入 koh khah 早 ê 互動" @@ -273,13 +273,13 @@ }, "content_type_selection": "貼 ê 形式", "content_warning": "主旨(毋是必要)", - "default": "Tú 正 kàu 高雄 ah。", + "default": "Tú正kàu高雄ah。", "direct_warning_to_all": "Tsit ê PO 文通 hōo 逐 ê 提起 ê 用者看見。", - "direct_warning_to_first_only": "Tsit ê PO 文,kan-ta 短信 tú 開始提起 ê 用者,tsiah 通看見。", + "direct_warning_to_first_only": "Tsit ê PO 文,kan-ta佇短phue tú開始提起ê用者,tsiah通看見。", "edit_remote_warning": "別 ê 站臺可能無支援編輯,無法度收著 PO 文上新 ê 版本。", "edit_unsupported_warning": "Pleroma 無支持編輯 the̍h 起 hām 投票。", "posting": "PO 文", - "preview": "Sing 看覓", + "preview": "Sing看māi", "preview_empty": "空 ê", "empty_status_error": "無法度 PO 無檔案 koh 空 ê 狀態", "media_description_error": "更新媒體失敗,請 koh 試一 kái", @@ -295,7 +295,9 @@ "public": "公開 - PO kàu 公開時間線", "unlisted": "Mài 列出來 - Mài PO tī 公開時間線" }, - "post": "PO 上去" + "post": "PO 上去", + "reply_option": "應tsit ê狀態", + "quote_option": "引用tsit ê狀態" }, "registration": { "bio_optional": "介紹(毋是必要)", @@ -360,7 +362,16 @@ "color": "色彩", "opacity": "無透明度", "contrast": { - "hint": "色彩ê對比率:{ratio}。{level}、 {context}" + "hint": "色彩ê對比率:{ratio}。{level}、 {context}", + "level": { + "aa": "合AA級ê準則(上kē ê)", + "aaa": "合AAA級ê準則(建議ê)", + "bad": "無合半ê無障礙準則" + }, + "context": { + "18pt": "大(18pt 以上)ê文字", + "text": "文字" + } } }, "switcher": { @@ -370,7 +381,7 @@ "keep_roundness": "保留邊á角ê khà-buh", "keep_fonts": "保持字型", "reset": "重頭設定", - "clear_all": "攏清掉", + "clear_all": "Lóng清掉", "clear_opacity": "清掉無透明度", "load_theme": "載入主題", "keep_as_is": "Mài振動", @@ -380,8 +391,116 @@ "upgraded_from_v2": "PleromaFE升級ah,主題huân-sè kap lí知影ê無kâng。", "v2_imported": "Lí輸入ê檔案是舊版本ê前端用ê。Guán盡量予版本相通,毋過可能有所在buē-tàng。", "older_version_imported": "Lí輸入ê檔案是予舊ê前端用ê。", - "future_version_imported": "Lí輸入ê檔案是新ê前端所用ê。" + "future_version_imported": "Lí輸入ê檔案是新ê前端所用ê。", + "snapshot_missing": "無主題ê快相佇檔案內,所以,伊看起來凡勢kap原來預料ê無kâng。", + "snapshot_present": "主題ê快相有載入,所以逐ê值lóng khàm過去ah。Lí 通改載入主題實際ê資料。", + "fe_upgraded": "版本更新了後,Pleroma前端ê ia̋n-jín 升級ah。", + "fe_downgraded": "Pleroma ê前端滾tńg去ah。", + "migration_snapshot_ok": "為著保險,主題快相載入去ah。Lí ē當試載入主題資料。", + "migration_napshot_gone": "快相因故無去ah,tsi̍t-kuá所在看起來可能hām lí所想ê無kâng。", + "snapshot_source_mismatch": "版本tshia̋ng-póng:上可能因為前端滾轉去koh更新ah,若因為用舊版本ê前端,主題tsiah改變,lí有可能beh用舊ê版本。無,著用新ê。" + }, + "save_load_hint": "佇揀iah是載入主題ê時,「保存」選項保留現tsú時設定ê選項;mā佇輸出主題ê時tsūn,儲存頭拄á講ê選項。若是逐ê選擇框á無設定,逐項設定就ē khǹg佇輸出ê主題。" + }, + "common_colors": { + "_tab_label": "一般", + "main": "一般ê色彩", + "foreground_hint": "請看「進階」分頁,來調整khah幼ê所在", + "rgbo": "標頭、強調、徽章" + }, + "advanced_colors": { + "_tab_label": "進階", + "alert": "警告ê背景", + "alert_error": "錯誤", + "alert_warning": "警告", + "alert_neutral": "其他ê", + "post": "PO文/用者紹介", + "badge": "徽章ê背景", + "popover": "提示、目錄、跳出來ê", + "badge_notification": "通知", + "panel_header": "面枋ê標題", + "top_bar": "頂 liâu-á", + "borders": "框á邊", + "buttons": "鈕仔", + "inputs": "輸入框á", + "faint_text": "淺ê文字", + "underlay": "Tshū-á", + "wallpaper": "壁紙", + "poll": "投票數ê圖", + "icons": "標á", + "highlight": "強調ê要素", + "pressed": "Tshi̍h ê 時", + "selectedPost": "選擇ê PO文", + "selectedMenu": "選擇ê目錄項目", + "disabled": "關ê", + "toggled": "切換ê時", + "tabs": "分頁", + "chat": { + "incoming": "收著ê", + "outgoing": "送出ê", + "border": "框á邊" + } + }, + "radii": { + "_tab_label": "邊á角ê khà-buh" + }, + "shadows": { + "_tab_label": "影kap光", + "override": "Khàm掉", + "shadow_id": "影 #{value}", + "blur": "予n̄g-n̄g", + "spread": "Hōo 闊", + "inset": "內pîng", + "filter_hint": { + "always_drop_shadow": "警告,tsit ê 影一直用 {0},若是瀏覽器支援tsē。", + "drop_shadow_syntax": "{0} 無支援參數 {1} kap 關鍵字 {2}。", + "avatar_inset": "請注意,結合內pîng kap外pîng ê影佇標頭,可能佇透明ê標頭現無預料ê結果。", + "spread_zero": "若是「hōo 闊」ê值比0較大,影ê顯示ē kap hōo 闊設做0 kâng款", + "inset_classic": "內pîng ê影ē用{0}" + }, + "component": "部件", + "hintV3": "針對影,lí mā ē當用 {0} 標示法,來用其他ê色彩 khang (slot)。", + "components": { + "panelHeader": "面枋ê標題", + "topBar": "頂 liâu-á", + "avatar": "用者ê標頭(佇個人資料欄位)", + "popup": "跳出來ê kap提醒", + "button": "鈕仔", + "buttonHover": "鈕仔(滑鼠ê指標khǹg佇面頂)", + "panel": "面枋", + "avatarStatus": "用者ê標頭(佇PO文ê顯示)", + "buttonPressedHover": "鈕仔(滑鼠指標leh khǹg 佇頂懸,koh tshi̍h ê時)", + "buttonPressed": "鈕仔(leh tshi̍h ê時)", + "input": "輸入框á" } + }, + "fonts": { + "_tab_label": "字型", + "components": { + "interface": "界面", + "input": "輸入框á", + "post": "PO文", + "postCode": "RTF ê PO文ê平闊文字" + }, + "family": "字型ê名", + "help": "揀界面元件所用ê字型。若是揀「家己指定」,lí著輸入系統內ê字型正確ê名。", + "size": "Sài-suh(單位:畫素)", + "weight": "字ê重(粗度)", + "custom": "家己指定" + }, + "preview": { + "header": "先看māi", + "content": "內容", + "error": "錯誤ê例", + "button": "鈕á", + "text": "Tsē是{0}kap{1} ê例", + "mono": "內容", + "input": "Tú正kàu高雄ah。", + "faint_link": "有幫tsān ê手冊", + "fine_print": "讀guán ê {0},毋過學無有路用ê!", + "header_faint": "Tsē OK", + "checkbox": "我有讀過使用條款", + "link": "好ê細ê連結" } }, "upload": { @@ -598,7 +717,7 @@ "navbar_column_stretch": "伸導覽liâu,kah 欄平闊", "always_show_post_button": "一直顯示「新ê PO文」ê鈕仔", "hide_wallpaper": "Khàm站臺ê壁紙", - "use_one_click_nsfw": "Tshi̍h 一ê就會當拍開敏感內容", + "use_one_click_nsfw": "Tshi̍h chi̍t 下就ē當拍開敏感內容", "hide_post_stats": "Khàm PO文ê統計數據(比如:kah 意ê額數)", "hide_filtered_statuses": "Khàm 逐ê過濾掉êPO文", "hide_wordfiltered_statuses": "Khàm詞語過濾掉ê狀態", @@ -627,7 +746,7 @@ "mute_bot_posts": "Kā 機器lâng ê PO文消音", "hide_shoutbox": "Khàm 站臺ê留話pang", "account_backup_description": "Tse 予 lí ē當 kā lín 口座 ê 資訊 kap PO 文載落來,毋過 in 猶無法度輸入kàu Pleroma口座 ê 內底。", - "theme_help_v2_1": "拍開選擇框á就 ē 當改掉一寡組件ê色彩kap無透明度。Ji̍h「清掉所有ê」,ē 恢復原來ê款。", + "theme_help_v2_1": "拍開選擇框á就 ē 當改掉一寡組件ê色彩kap無透明度。Ji̍h「Lóng清掉」,ē 恢復原來ê款。", "preload_images": "Kā 圖片先載入", "hide_user_stats": "Khàm 掉用者ê統計數據(比如:綴ê lâng額)", "interfaceLanguage": "界面ê語言", @@ -678,7 +797,7 @@ "notification_visibility_mentions": "提起", "notification_visibility_repeats": "轉送", "notification_visibility_moves": "用者suá位", - "notification_visibility_emoji_reactions": "回應", + "notification_visibility_emoji_reactions": "反應", "notification_visibility_polls": "Lí參與ê選舉辦suah佇", "no_rich_text_description": "Po文mài用RTF格式", "no_blocks": "無封鎖", @@ -690,7 +809,7 @@ "show_moderator_badge": "佇我ê個人資料顯示「管理員」證章", "nsfw_clickthrough": "Khàm掉敏感ê媒體內容", "oauth_tokens": "OAuth token", - "refresh_token": "對頭the̍h token", + "refresh_token": "重頭the̍h token", "valid_until": "到期佇", "revoke_token": "撤回", "panelRadius": "面pang", @@ -716,12 +835,12 @@ "set_new_avatar": "設定新ê標頭", "set_new_profile_background": "設定新ê個人資料ê背景", "set_new_profile_banner": "設定新ê個人資料ê條á", - "reset_avatar": "Tuì頭設定標頭", - "reset_profile_background": "Tuì頭設個人資料ê背景", - "reset_profile_banner": "Tuì頭設個人資料ê條á", - "reset_avatar_confirm": "Lí敢確實beh tuì頭設定標頭?", - "reset_banner_confirm": "Lí敢確實beh tuì頭設定條á?", - "reset_background_confirm": "Lí敢確實beh tuì頭設定背景?", + "reset_avatar": "重頭設定標頭", + "reset_profile_background": "重頭設個人資料ê背景", + "reset_profile_banner": "重頭設個人資料ê條á", + "reset_avatar_confirm": "Lí敢確實beh 重頭設定標頭?", + "reset_banner_confirm": "Lí敢確實beh 重頭設定條á?", + "reset_background_confirm": "Lí敢確實beh 重頭設定背景?", "settings": "設定", "subject_input_always_show": "一直顯示主旨ê格á", "subject_line_behavior": "回應ê時,khóo-pih主旨", @@ -792,15 +911,430 @@ "notification_mutes": "若tsún無愛收tuì指定用者來ê通知,著用消音。", "notification_blocks": "封鎖用者ē停止所有i hia來ê通知,mā取消訂伊。", "enable_web_push_notifications": "拍開網頁sak通知ê功能", - "more_settings": "Koh較tsē ê設定" + "more_settings": "Koh較tsē ê設定", + "version": { + "title": "版本", + "backend_version": "後端ê版本", + "frontend_version": "前端ê版本" + }, + "commit_value": "儲存", + "commit_value_tooltip": "值無儲存,tshi̍h tsit ê 鈕仔來送出你改變ê", + "hard_reset_value": "硬ê重頭設", + "hard_reset_value_tooltip": "Suá掉儲存內底ê設定,強制用預設ê值", + "reset_value": "重頭設", + "reset_value_tooltip": "重頭設草稿" }, "status": { - "favorites": "收藏" + "favorites": "收藏", + "repeat_confirm_cancel_button": "Mài轉送", + "delete_confirm_title": "Thâi掉ê確認", + "edit": "編輯狀態", + "edited_at": "(頂kái編輯佇:{time})", + "pin": "釘佇個人資料", + "unpin": "Tuì個人資料拆掉", + "pinned": "釘入去ê", + "bookmark": "加入冊籤", + "unbookmark": "Tuì冊籤the̍h掉", + "delete_confirm": "Lí kám真ê beh thâi掉tsit ê狀態?", + "delete_confirm_accept_button": "Thâi掉", + "delete_confirm_cancel_button": "保留", + "reply_to": "回應", + "replies_list": "回應:", + "repeats": "轉送", + "repeat_confirm_accept_button": "轉送", + "repeat_confirm_title": "轉送ê確認", + "repeat_confirm": "Lí kám真ê beh轉送tsit ê狀態?", + "delete": "Thâi掉身份", + "delete_error": "Thâi狀態ê時出tshê:{0}", + "mentions": "提起", + "move_down": "Kā附件suá kàu正pîng", + "thread_show_full": "展示tsit 條討論線ê所有(lóng總有{numStatus}ê狀態,深度上限:{depth})", + "thread_follow": "看討論線tshūn ê部份(lóng總有{numStatus}ê狀態)", + "replies_list_with_others": "回應(+其他{numReplies}ê):", + "mute_conversation": "Kā會話消音", + "unmute_conversation": "Kā會話取消消音", + "status_unavailable": "狀態bē當用", + "copy_link": "Khóo-pih 狀態ê連結", + "external_source": "外口ê來源", + "thread_muted": "討論線消音ah", + "thread_muted_and_words": ",有詞語:", + "hide_full_subject": "Khàm掉主題ê全文", + "show_full_subject": "顯示標題ê全文", + "show_content": "顯示內容", + "hide_content": "Khàm掉內容", + "status_deleted": "Tsit篇PO文thâi掉ah", + "nsfw": "敏感ê內容", + "expand": "Thián開", + "you": "(Lí)", + "plus_more": "Koh有{number}ê", + "many_attachments": "PO文有{number}ê附件", + "collapse_attachments": "Kā附件tshàng起來", + "show_all_attachments": "顯示逐ê附件", + "show_attachment_in_modal": "佇媒體模式顯示", + "show_attachment_description": "Kā敘述先看māi(拍開附件會當看kui ê敘述)", + "hide_attachment": "Khàm掉附件", + "attachment_stop_flash": "停止Flash ê播放器", + "remove_attachment": "Kā附件suá走", + "move_up": "Kā附件suá kàu倒pîng", + "open_gallery": "拍開畫廊", + "thread_hide": "Khàm掉討論線", + "thread_show": "顯示討論線", + "thread_show_full_with_icon": "{icon} {text}", + "thread_follow_with_icon": "{icon} {text}", + "ancestor_follow": "看其他{numReplies}ê佇tsit ê狀態ê回應", + "ancestor_follow_with_icon": "{icon} {text}", + "show_all_conversation_with_icon": "{icon} {text}", + "show_all_conversation": "看kui ê會話(有其他{numStatus}ê狀態)", + "show_only_conversation_under_this": "Kan-ta顯示tsit ê狀態ê回應", + "status_history": "狀態ê歷史", + "reaction_count_label": "{num}ê lâng用表情反應", + "hide_quote": "Khàm條引用ê狀態", + "display_quote": "顯示引用ê狀態", + "invisible_quote": "引用ê狀態bē當用:{link}" }, "user_card": { - "favorites": "收藏" + "favorites": "收藏", + "show_repeats": "顯示轉送", + "hide_repeats": "Khàm掉轉送", + "remove_follower_confirm": "Lí kám真正想beh kā {user} tuì lí所跟綴ê suá走?", + "statuses": "狀態", + "admin_menu": { + "activate_account": "啟動口座", + "deactivate_account": "予口座失效", + "delete_account": "Thâi掉口座", + "force_nsfw": "Kā逐ê PO文標做敏感內容", + "strip_media": "Tuì PO文thâi掉媒體", + "force_unlisted": "強制PO文mài列佇公共時間線", + "disable_remote_subscription": "Mài允准tuì其他站臺跟tuè用者", + "sandbox": "強制PO文kan-ta予跟tuè ê看", + "disable_any_subscription": "Mài允准跟tuè任何用者", + "quarantine": "Tuì聯邦禁止用者ê PO文", + "delete_user": "Thâi掉用者ê口座", + "delete_user_data_and_deactivate_confirmation": "Án-ne ē永永thâi掉tsit ê口座ê資料兼hōo失效。Lí kám完全確定?", + "grant_admin": "授與行政員ê權", + "revoke_admin": "撤掉行政員ê權", + "moderation": "仲裁", + "grant_moderator": "授與仲裁員ê權", + "revoke_moderator": "撤掉仲裁員ê權" + }, + "highlight": { + "disabled": "Mài強調", + "side": "邊á ê花tsuā", + "solid": "孤色ê背景", + "striped": "花tsuā ê背景" + }, + "note": "筆記", + "note_blank": "(無)", + "edit_note": "編輯筆記", + "edit_note_apply": "適用", + "approve": "核准", + "approve_confirm_title": "核准ê確認", + "approve_confirm_accept_button": "核准", + "approve_confirm_cancel_button": "Mài核准", + "block": "封鎖", + "blocked": "封鎖ah!", + "block_confirm_title": "封鎖ê確認", + "approve_confirm": "Lí kám想beh核准{user}ê跟tuè請求?", + "block_confirm": "Lí kám 真正想beh封鎖{user}?", + "block_confirm_accept_button": "封鎖", + "block_confirm_cancel_button": "Mài封鎖", + "deactivated": "停止使用ah", + "deny": "拒絕", + "deny_confirm_title": "拒絕ê確認", + "deny_confirm_accept_button": "拒絕", + "deny_confirm_cancel_button": "Mài拒絕", + "deny_confirm": "Lí kám想beh拒絕{user}ê跟tuè請求?", + "edit_profile": "編輯個人資料", + "follow": "跟tuè", + "follow_cancel": "取消請求", + "follow_sent": "請求送ah!", + "follow_progress": "Teh請求……", + "follow_unfollow": "無愛跟tuè", + "unfollow_confirm_title": "無愛跟tuè ê確認", + "unfollow_confirm": "lí kám真正無beh跟tuè {user}?", + "unfollow_confirm_accept_button": "無愛跟綴", + "unfollow_confirm_cancel_button": "繼續跟tuè", + "followees": "Teh跟綴", + "followers": "跟綴ê", + "following": "Teh跟tuè!", + "follows_you": "跟tuè lí!", + "hidden": "Tshàng起來ê", + "its_you": "Tse是lí!", + "media": "媒體", + "mention": "提起", + "message": "短phue", + "mute": "消音", + "muted": "消音ê", + "mute_confirm_title": "消音ê確認", + "mute_confirm": "Lí確定想beh kā {user}消音?", + "mute_confirm_accept_button": "消音", + "mute_confirm_cancel_button": "Mài消音", + "mute_duration_prompt": "消音tsit ê用戶ê期限(0表示永遠):", + "per_day": "/kang", + "remote_follow": "遠距離ê關注", + "remove_follower": "Suá走跟綴ê", + "remove_follower_confirm_title": "Suá走跟tuè者ê確認", + "remove_follower_confirm_accept_button": "Suá走", + "remove_follower_confirm_cancel_button": "保留", + "report": "檢舉", + "subscribe": "注文", + "unsubscribe": "取消注文", + "unblock": "Mài封鎖", + "unblock_progress": "Teh取消封鎖……", + "block_progress": "Leh封鎖……", + "unmute": "Mài消音", + "mute_progress": "Leh消音……", + "unmute_progress": "Leh取消消音……", + "bot": "機器lâng", + "birthday": "出世佇{birthday}", + "edit_note_cancel": "取消" }, "tool_tip": { - "favorite": "收藏" + "favorite": "收藏", + "repeat": "轉送", + "media_upload": "Kā媒體傳起去", + "reply": "回應", + "add_reaction": "加反應", + "user_settings": "用者ê設定", + "accept_follow_request": "允准跟tuè ê請求", + "reject_follow_request": "拒絕跟tuè ê請求", + "bookmark": "冊籤", + "toggle_expand": "Thián開á是tshàng通知,顯示kui篇PO文", + "toggle_mute": "Thián開á是tshàng通知,顯露消音ê內容", + "autocomplete_available": "{number} ê結果通用。用頂kap下ê key來看結果。" + }, + "password_reset": { + "instruction": "輸入你ê email地址iah是用者ê名。阮ē寄予lí連結,通重頭設你ê密碼。", + "password_reset_disabled": "密碼重頭設ê功能無開放。請聯絡lín站臺ê行政員。", + "password_reset_required_but_mailer_is_disabled": "Lí著重設密碼,M̄-koh重頭設密碼ê功能無開放。請聯絡lín站臺ê行政員。", + "forgot_password": "Buē記得密碼?", + "password_reset": "密碼重頭設", + "placeholder": "你ê email iah是用者ê名", + "check_email": "檢查你ê電子phue箱,有重頭設密碼ê連結ê phue無。", + "return_home": "Tńg去頭頁", + "too_many_requests": "Lí已經kàu 試ê回數限制 ah,小等leh koh試。", + "password_reset_required": "Lí著重設密碼,tsiah通登入。" + }, + "admin_dash": { + "window_title": "行政員", + "reset_all": "Kui ê重頭設", + "wip_notice": "Tsit ê 管理 la-jí-báng (dashboard) 是試驗ê,koh teh 起做,{adminFeLink}.", + "old_ui_link": "舊ê管理界面佇tsia", + "commit_all": "Lóng總儲存", + "tabs": { + "nodb": "無資料庫ê設置", + "instance": "站臺", + "limits": "限制", + "frontends": "前端" + }, + "nodb": { + "heading": "資料庫設置無開放", + "text": "Lí需要改後端ê設置檔案,tsiah ē當kā{property}設做{value},請佇{documentation}了解詳細。", + "documentation": "文件", + "text2": "大部份ê設定ē無開放。" + }, + "limits": { + "user_uploads": "個人資料ê媒體限制", + "arbitrary_limits": "任何限制", + "posts": "PO文ê限制", + "uploads": "附件ê限制", + "users": "用者個人資料ê限制", + "profile_fields": "個人資料欄位ê限制" + }, + "captcha": { + "native": "在來ê", + "kocaptcha": "KoCaptcha" + }, + "instance": { + "instance": "站臺ê資訊", + "registrations": "用者ê註冊", + "kocaptcha": "KoCaptcha ê設定", + "restrict": { + "header": "管制無落名ê訪客使用", + "timelines": "讀取時間線", + "profiles": "讀取用者ê個人資料", + "activities": "讀取狀態/活動", + "description": "(無)允准一kuá方面ê API the̍h取資源ê詳細設定。預設(無定ê狀態),若是站臺毋是公開ê,ē無允准the̍h取;選擇框á若勾,就算站臺是公開ê,iáu是無允准the̍h取;若無勾,就算站臺是私人ê,mā是允准the̍h取。請注意,若是設一kuá設定,無預料ê行為可能產生。比如講,若是the̍h取個人資料無開放,PO文buē顯示個人資料。" + }, + "access": "讀取實體", + "captcha_header": "CAPTCHA" + }, + "frontend": { + "repository": "原始碼庫ê連結", + "versions": "通用ê版本", + "build_url": "起做URL", + "reinstall": "重頭安裝", + "is_default": "(預設)", + "is_default_custom": "(預設,版本:{version})", + "install": "安裝", + "install_version": "安裝ê版本:{version}", + "more_install_options": "其他ê安裝選項", + "more_default_options": "其他ê預設設定ê選項", + "set_default": "設做預設ê", + "set_default_version": "Kā版本{version}設做預設ê", + "default_frontend_tip": "預設ê前端ē展示予逐ê用者。現在,用者無法度揀個人ê前端。若是lí變換,無beh用PleromaFE,上有可能ē用舊koh問題tsē ê AdminFE 做站臺ê設置,佇阮iáu-bē kā伊取代以前。", + "wip_notice": "請注意,tsit ê段落iáu teh起做,欠缺一寡特點,因為後端tuì前端管理ê實做無齊備。", + "default_frontend": "預設ê前端", + "default_frontend_tip2": "Teh起做:因為Pleroma後端無適當列出逐ê安裝ê前端,lí著手動輸入名字kap引用。下kha ê列單提供寫tsiah-ê 值ê近路。", + "available_frontends": "Ē當安裝" + }, + "temp_overrides": { + ":pleroma": { + ":instance": { + ":public": { + "description": "無開放tse,ē 控制逐êAPI,干焦予登入ê用者用,mā ē予公開kap聯邦ê時間線,buē當予無落名ê訪客the̍h著。", + "label": "站臺是公開ê" + }, + ":limit_to_local_content": { + "label": "Kan-ta會當tshuē在地ê內容", + "description": "無開放無認證ê用者、逐儂,猶是lóng總開放tshuē全球ê網路" + }, + ":description_limit": { + "label": "限制", + "description": "附件說明ê字元限制" + }, + ":background_image": { + "label": "背景ê影像", + "description": "背景ê影像(主要予PleromaFE用)" + } + } + } + } + }, + "timeline": { + "up_to_date": "是上新ê", + "collapse": "疊起來", + "conversation": "會話", + "error": "佇the̍h時間線ê時出tshê:{0}", + "load_older": "載入舊ê狀態", + "repeated": "轉送ah", + "no_retweet_hint": "PO文hőng標做限定跟綴ê,á是私人phue,無法度轉送", + "show_new": "看新ê", + "reload": "重新載入", + "no_more_statuses": "無其他ê狀態", + "no_statuses": "無狀態", + "socket_reconnected": "實時ê連結成立ah", + "socket_broke": "實時連結拍m̄見ah:CloseEvent代碼{0}", + "quick_view_settings": "快速 view ê設定", + "quick_filter_settings": "快速過濾器ê設定" + }, + "time": { + "unit": { + "days": "{0}工", + "days_short": "{0}工", + "hours": "{0}點鐘", + "hours_short": "{0}點鐘", + "minutes": "{0}分鐘", + "minutes_short": "{0}分", + "months": "{0}個月", + "months_short": "{0}個月", + "seconds": "{0}秒鐘", + "seconds_short": "{0}秒", + "weeks": "{0}禮拜", + "weeks_short": "{0}週", + "years": "{0}年", + "years_short": "{0}年" + }, + "in_future": "koh有{0}", + "in_past": "{0}進前", + "now": "tú正", + "now_short": "tsit-má" + }, + "user_reporting": { + "title": "檢舉 {0}", + "forward_description": "Tsit ê口座是別ê站臺ê。Mā kám beh寄報告ê khóo-pih kàu hit ê站?", + "add_comment_description": "本檢舉ē 寄kàu你ê站臺ê仲裁員。Lí會當佇下kha解說檢舉tsit ê口座ê原因:", + "additional_comments": "其他ê意見", + "forward_to": "轉送kàu{0}", + "submit": "送出", + "generic_error": "佇處理lí ê請求ê時出tshê。" + }, + "lists": { + "really_delete": "Kám真正 beh thâi列單?", + "search": "Tshiau-tshuē用者", + "create": "建立", + "save": "保存改變", + "delete": "Thâi列單", + "lists": "列單", + "new": "新ê列單", + "title": "列單ê標題", + "following_only": "限制佇跟tuè ê", + "manage_lists": "管理列單", + "manage_members": "管理列單ê成員", + "add_members": "Tshiau-tshuē其他ê用者", + "remove_from_list": "Tuì列單suá走", + "add_to_list": "Ke-thinn kàu列單", + "is_in_list": "已經佇列單內底", + "editing_list": "編輯列單 {listTitle}", + "creating_list": "開新ê列單", + "update_title": "保存標題", + "error": "佇操作列單ê時出tshê:{0}" + }, + "update": { + "update_bugs": "請報告任何問題kap錯誤佇 {pleromaGitlab},因為已經改變真tsē。雖bóng guán徹底試過,ka-kī mā用開發版,iáu是有可能有無注意ê所在。Guán歡迎lí tuì所tú tio̍h ê問題,提出意見kap建議,或者是改進Pleroma kap Pleroma-FE ê方法。", + "big_update_title": "請sió等tsi̍t ê", + "update_bugs_gitlab": "Pleroma GitLab", + "big_update_content": "Guán已經有tsi̍t段時間無推出發行,所以外觀kap感覺kap lí所慣勢ê,凡勢無kâng。", + "update_changelog": "Beh知影改變ê詳細,請看{theFullChangelog}。", + "update_changelog_here": "Changelog全文", + "art_by": "美術製作:{linkToArtist}" + }, + "user_profile": { + "timeline_title": "用者ê時間線", + "profile_does_not_exist": "Pháinn勢,tsit ê個人資料無佇leh。", + "profile_loading_error": "Pháinn勢,佇載入tsit ê個人資料ê時出tshê。" + }, + "who_to_follow": { + "more": "詳情", + "who_to_follow": "Siáng通tuè" + }, + "upload": { + "error": { + "base": "傳起去ê時失敗。", + "message": "傳起去ê時失敗:{0}", + "file_too_big": "檔案siūnn大[{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]", + "default": "Koh試tsi̍t kái" + }, + "file_size_units": { + "B": "B", + "KiB": "KiB", + "MiB": "MiB", + "GiB": "GiB", + "TiB": "TiB" + } + }, + "search": { + "people": "Lâng", + "hashtags": "井字ê標籤", + "person_talking": "{count}ê lâng teh開講", + "people_talking": "{count}ê lâng teh開講", + "no_results": "無結果", + "no_more_results": "無其他結果", + "load_more": "載入其他結果" + }, + "chats": { + "you": "Lí:", + "message_user": "送短phue予:{nickname}", + "delete": "Thâi掉", + "chats": "開講", + "new": "新ê開講", + "empty_message_error": "Bē當PO空ê短phue", + "more": "其他", + "delete_confirm": "Lí kám真正beh thâi tsit ê短phue?", + "error_loading_chat": "佇載入開講ê時出問題。", + "error_sending_message": "佇送短phue ê時出問題。", + "empty_chat_list_placeholder": "Lí iáu buē開講過。開始開講!" + }, + "file_type": { + "audio": "聲音", + "video": "影片", + "image": "影像", + "file": "檔案" + }, + "display_date": { + "today": "今á日" + }, + "unicode_domain_indicator": { + "tooltip": "Tsit ê域名含m̄是ascii ê字元。" } } diff --git a/src/i18n/uk.json b/src/i18n/uk.json @@ -121,7 +121,8 @@ "placeholder": "напр. stepan", "logout_confirm": "Ви дійсно хочете вийти?", "logout_confirm_accept_button": "Вийти", - "logout_confirm_cancel_button": "Ні, хочу назад!" + "logout_confirm_cancel_button": "Ні, хочу назад!", + "logout_confirm_title": "Вихід" }, "importer": { "error": "Під час імпортування файлу сталася помилка.", @@ -164,7 +165,13 @@ "broken_favorite": "Невідомий допис, шукаю його…", "error": "Помилка при оновленні сповіщень: {0}", "poll_ended": "опитування закінчено", - "submitted_report": "подав скаргу" + "submitted_report": "подав скаргу", + "unread_announcements": "{num} непрочитане оголошення | {num} непрочитаних оголошень", + "unread_chats": "{num} непрочитаний чат | {num} непрочитаних чатів", + "unread_follow_requests": "{num} новий запит на підписку | {num} нових запитів на підписку", + "configuration_tip": "Ви можете налаштувати, що відображати тут у {theSettings}. {dismiss}", + "configuration_tip_settings": "налаштування", + "configuration_tip_dismiss": "Не показувати знову" }, "nav": { "chats": "Чати", @@ -267,7 +274,8 @@ "activities": "Активності", "symbols": "Символи", "travel-and-places": "Подорожі та Місця" - } + }, + "unpacked": "Розпаковані емоджі" }, "post_status": { "content_type": { @@ -304,7 +312,11 @@ "post": "Опублікувати", "edit_unsupported_warning": "Pleroma не підтримує редагування згадувань чи голосувань.", "edit_status": "Редагувати допис", - "edit_remote_warning": "Інші віддалені інстанси можуть не підтримувати редагування та вони можуть не отримати актуальну версію допису." + "edit_remote_warning": "Інші віддалені інстанси можуть не підтримувати редагування та вони можуть не отримати актуальну версію допису.", + "content_type_selection": "Форматування допису", + "scope_notice_dismiss": "Закрити це сповіщення", + "reply_option": "Відповісти на цей допис", + "quote_option": "Процитувати допис" }, "settings": { "blocks_imported": "Блокування імпортовані! Їх обробка триватиме певний час.", @@ -730,7 +742,7 @@ "conversation_display_tree_quick": "Вигляд дерева", "disable_sticky_headers": "Не закріплювати заголовок колонки зверху на сторінці", "third_column_mode_none": "Не показувати третю колонку взагалі", - "third_column_mode_notifications": "Колонка сповіщень", + "third_column_mode_notifications": "Колонку сповіщень", "columns": "Колонки", "auto_update": "Автоматично показувати нові дописи", "use_websockets": "Використовувати вебсокети (Оновлення в реальному часі)", @@ -743,7 +755,38 @@ "wordfilter": "Фільтр слів", "mention_links": "Посилання для згадування", "user_profiles": "Профілі користувачів", - "notification_visibility_polls": "Закінчення опитувань, в яких ви проголосували" + "notification_visibility_polls": "Закінчення опитувань, в яких ви проголосували", + "remove_language": "Вилучити", + "primary_language": "Основна мова:", + "fallback_language": "Резервна мова {index}:", + "confirm_dialogs_deny_follow": "тим, як відмовити у запиті на підписку", + "confirm_dialogs_remove_follower": "видаленням підписника", + "notification_show_extra": "Показувати додаткові сповіщення в панелі сповіщень", + "notification_extra_chats": "Показувати непрочитані чати", + "notification_extra_announcements": "Показувати непрочитані оголошення", + "notification_extra_follow_requests": "Показувати нові запити на підписку", + "third_column_mode_postform": "Форму відправки повідомлень та панель навігації", + "notification_extra_tip": "Показати пораду з налаштувань для додаткових сповіщень", + "backup_running": "Резервне копіювання триває, оброблено {number} записи. | Резервне копіювання триває, оброблено {number} записів.", + "backup_failed": "Резервне копіювання не вдалося.", + "preview": "Попередній перегляд", + "url": "URL", + "birthday": { + "label": "День народження", + "show_birthday": "Показувати мій день народження" + }, + "confirm_dialogs": "Запитувати підтвердження перед", + "confirm_dialogs_repeat": "поширенням допису", + "confirm_dialogs_unfollow": "скасуванням підписки", + "confirm_dialogs_block": "блокуванням користувача", + "confirm_dialogs_mute": "тим, як заглушити користувача", + "show_scrollbars": "Показувати смугу прокрутки на бічних панелях", + "column_sizes": "Розміри панелей", + "column_sizes_sidebar": "Бічна панель", + "add_language": "Додати резервну мову", + "confirm_dialogs_delete": "видаленням допису", + "confirm_dialogs_logout": "виходом із системи", + "confirm_dialogs_approve_follow": "схваленням запиту на підписку" }, "selectable_list": { "select_all": "Вибрати все" @@ -760,7 +803,8 @@ "password_required": "не може бути порожнім", "email_required": "не може бути порожнім", "fullname_required": "не може бути порожнім", - "username_required": "не може бути порожнім" + "username_required": "не може бути порожнім", + "birthday_required": "не може бути пустим" }, "bio_placeholder": "напр.\nНаш народ завжди прагне волі для себе і бажає її для інших народів. Він боровся і бореться за правду і справедливість. Ми хочемо жити у згоді і взаємному шануванні з усіми народами доброї волі. Такі самі права визнаємо за іншими народами, за які боремося для себе.", "fullname_placeholder": "напр. Степан Бандера", @@ -778,7 +822,9 @@ "reason": "Причина реєстрації", "bio_optional": "Біографія (необов'язково)", "email_language": "Якою мовою ви бажаєте отримувати електронні листи від сервера?", - "email_optional": "Ел. пошта (необов'язково)" + "email_optional": "Ел. пошта (необов'язково)", + "birthday": "День народження:", + "birthday_optional": "День народження (необов'язково):" }, "who_to_follow": { "who_to_follow": "На кого підписатися", @@ -890,7 +936,8 @@ "grant_moderator": "Надати права модератора", "revoke_admin": "Позбавити прав адміністратора", "grant_admin": "Надати права адміністратора", - "quarantine": "Не розповсюджувати дописи на інших інстансах" + "quarantine": "Не розповсюджувати дописи на інших інстансах", + "delete_user_data_and_deactivate_confirmation": "Це назовсім видалить дані обліковки й вимкне її. Точно продовжити?" }, "deny": "Відмовити", "block": "Заблокувати", @@ -929,7 +976,32 @@ "bot": "Бот", "edit_profile": "Редагувати профіль", "deactivated": "Деактивований", - "follow_cancel": "Скасувати запит" + "follow_cancel": "Скасувати запит", + "block_confirm_title": "Блокування", + "block_confirm": "Точно заблокувати {user}?", + "mute_confirm_cancel_button": "Ні, не приглушувати", + "note_blank": "(Пусто)", + "edit_note_apply": "Застосувати", + "edit_note_cancel": "Скасувати", + "block_confirm_accept_button": "Так, заблокувати", + "block_confirm_cancel_button": "Ні, не блокувати", + "deny_confirm_title": "Відхилити запит на підписку", + "mute_confirm_accept_button": "Так, приглушити", + "mute_confirm": "Точно приглушити {user}?", + "edit_note": "Редагувати нотатку", + "mute_confirm_title": "Приглушення", + "mute_duration_prompt": "Приглушити користувача на (0 якщо назавжди):", + "approve_confirm_title": "Дозвіл підписатись", + "approve_confirm_accept_button": "Так, дозволити", + "approve_confirm_cancel_button": "Ні, скасувати", + "deny_confirm_accept_button": "Так, відхилити", + "deny_confirm_cancel_button": "Ні, скасувати", + "deny_confirm": "Ви точно хочете відхилити запит на підписку від {user}?", + "unfollow_confirm_title": "Відписка", + "unfollow_confirm": "Точно відписатись від {user}?", + "unfollow_confirm_accept_button": "Так, відписатись", + "unfollow_confirm_cancel_button": "Ні, не відписуватись", + "note": "Приватна нотатка" }, "status": { "copy_link": "Скопіювати посилання на допис", @@ -965,7 +1037,38 @@ "plus_more": "+{number} більше", "thread_show_full_with_icon": "{icon} {text}", "show_only_conversation_under_this": "Показати всі відповіді на цей допис", - "status_history": "Історія змін" + "status_history": "Історія змін", + "thread_hide": "Сховати гілку", + "open_gallery": "Відкрити галерею", + "repeat_confirm": "Точно поширити допис?", + "repeat_confirm_title": "Підтвердьте поширення", + "repeat_confirm_accept_button": "Так, поширити", + "repeat_confirm_cancel_button": "Ні, не поширювати", + "delete_error": "Помилка при видаленні допису: {0}", + "delete_confirm_accept_button": "Так, видалити", + "delete_confirm_cancel_button": "Ні, лишити", + "delete_confirm_title": "Підтвердьте видалення", + "you": "(ви)", + "collapse_attachments": "Згорнути вкладення", + "show_all_attachments": "Показати всі вкладення", + "hide_attachment": "Сховати вкладення", + "many_attachments": "Вкладень: {number} | Вкладень: {number}", + "attachment_stop_flash": "Зупинити Flash-плеєр", + "thread_follow": "Ще відповідей: {numStatus} | Ще відповідей: {numStatus}", + "remove_attachment": "Видалити вкладення", + "ancestor_follow": "Переглянути ще {numReplies} під цим дописом | Переглянути ще {numReplies} під цим дописом", + "show_all_conversation": "Показати всю розмову (ще дописів: {numStatus}) | Показати всю розмову (ще дописів: {numStatus})", + "move_up": "Посунути вкладення ліворуч", + "move_down": "Посунути вкладення праворуч", + "thread_show": "Показати гілку", + "mentions": "Згадки", + "thread_show_full": "Показати відповіді: {numStatus} | Показати відповіді: {numStatus}", + "hide_quote": "Сховати процитований допис", + "display_quote": "Показати процитований допис", + "invisible_quote": "Процитований допис недоступний: {link}", + "replies_list_with_others": "Ще відповідей: {numReplies} | Ще відповідей: {numReplies}:", + "show_attachment_in_modal": "Показати вкладення у вікні", + "show_attachment_description": "Переглянути опис (натисніть саме вкладення, якщо опис не вміщається)" }, "timeline": { "no_more_statuses": "Більше немає дописів", @@ -980,7 +1083,8 @@ "repeated": "поширив(-ла)", "no_retweet_hint": "Запис, позначено як \"тільки для підписників\" або \"особисте\" і тому не може бути поширений", "socket_broke": "Втрачено з'єднання у реальному часі: код {0}", - "socket_reconnected": "Встановлено з'єднання у реальному часі" + "socket_reconnected": "Встановлено з'єднання у реальному часі", + "quick_view_settings": "Налаштування швидкого перегляду" }, "user_reporting": { "submit": "Відправити", @@ -1026,5 +1130,35 @@ "submit_edit_action": "Надіслати", "cancel_edit_action": "Скасувати", "inactive_message": "Це оголошення неактивне" + }, + "lists": { + "really_delete": "Дійсно видалити список?", + "error": "Помилка при роботі зі списками: {0}", + "is_in_list": "Вже є у списку", + "editing_list": "Редагування списку {listTitle}", + "creating_list": "Створення нового списку", + "search": "Знайти користувачів", + "create": "Створити", + "save": "Зберегти зміни", + "manage_members": "Керувати учасниками списку", + "new": "Новий список", + "title": "Назва списку", + "delete": "Видалити список", + "following_only": "Лише за ким ви стежите", + "lists": "Списки", + "manage_lists": "Керувати списками", + "remove_from_list": "Видалити зі списку", + "add_to_list": "Додати до списку" + }, + "update": { + "update_changelog": "Щоб дізнатись більше інформації, дивіться {theFullChangelog}.", + "update_bugs": "Будь ласка, повідомляйте про будь-які проблеми та помилки на {pleromaGitlab}, оскільки ми внесли багато змін, і навіть після ретельно проведених перевірок, ми можемо щось пропустити. Ми заздалегідь вдячні за ваші відгуки щодо проблем, з якими ви можете зіткнутися, а також пропозиції щодо вдосконалення Pleroma та Pleroma-FE.", + "update_changelog_here": "повний список змін", + "big_update_title": "Хвилинку уваги", + "update_bugs_gitlab": "Pleroma GitLab", + "big_update_content": "У нас не було оновлень протягом тривалого часу, тому речі можуть мати інакший вигляд, аніж ви звикли." + }, + "unicode_domain_indicator": { + "tooltip": "Цей домен містить не-ASCII символи." } } diff --git a/src/modules/config.js b/src/modules/config.js @@ -40,6 +40,7 @@ export const defaultState = { padEmoji: true, hideAttachments: false, hideAttachmentsInConv: false, + hideScrobbles: false, maxThumbnails: 16, hideNsfw: true, preloadImage: true, @@ -120,6 +121,11 @@ export const defaultState = { conversationTreeAdvanced: undefined, // instance default conversationOtherRepliesButton: undefined, // instance default conversationTreeFadeAncestors: undefined, // instance default + showExtraNotifications: undefined, // instance default + showExtraNotificationsTip: undefined, // instance default + showChatsInExtraNotifications: undefined, // instance default + showAnnouncementsInExtraNotifications: undefined, // instance default + showFollowRequestsInExtraNotifications: undefined, // instance default maxDepthInThread: undefined, // instance default autocompleteSelect: undefined // instance default } diff --git a/src/modules/instance.js b/src/modules/instance.js @@ -103,6 +103,11 @@ const defaultState = { conversationTreeAdvanced: false, conversationOtherRepliesButton: 'below', conversationTreeFadeAncestors: false, + showExtraNotifications: true, + showExtraNotificationsTip: true, + showChatsInExtraNotifications: true, + showAnnouncementsInExtraNotifications: true, + showFollowRequestsInExtraNotifications: true, maxDepthInThread: 6, autocompleteSelect: false, diff --git a/src/modules/statuses.js b/src/modules/statuses.js @@ -47,6 +47,7 @@ const emptyNotifications = () => ({ export const defaultState = () => ({ allStatuses: [], + scrobblesNextFetch: {}, allStatusesObject: {}, conversationsObject: {}, maxId: 0, @@ -120,8 +121,24 @@ const sortTimeline = (timeline) => { return timeline } +const getLatestScrobble = (state, user) => { + if (state.scrobblesNextFetch[user.id] && state.scrobblesNextFetch[user.id] > Date.now()) { + return + } + + state.scrobblesNextFetch[user.id] = Date.now() + 24 * 60 * 60 * 1000 + apiService.fetchScrobbles({ accountId: user.id }).then((scrobbles) => { + if (scrobbles.length > 0) { + user.latestScrobble = scrobbles[0] + + state.scrobblesNextFetch[user.id] = Date.now() + 60 * 1000 + } + }) +} + // Add status to the global storages (arrays and objects maintaining statuses) except timelines const addStatusToGlobalStorage = (state, data) => { + getLatestScrobble(state, data.user) const result = mergeOrAdd(state.allStatuses, state.allStatusesObject, data) if (result.new) { // Add to conversation diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js @@ -107,6 +107,7 @@ const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements' const PLEROMA_POST_ANNOUNCEMENT_URL = '/api/v1/pleroma/admin/announcements' const PLEROMA_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}` const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}` +const PLEROMA_SCROBBLES_URL = id => `/api/v1/pleroma/accounts/${id}/scrobbles` const PLEROMA_ADMIN_CONFIG_URL = '/api/pleroma/admin/config' const PLEROMA_ADMIN_DESCRIPTIONS_URL = '/api/pleroma/admin/config/descriptions' @@ -1765,6 +1766,23 @@ const installFrontend = ({ credentials, payload }) => { }) } +const fetchScrobbles = ({ accountId, limit = 1 }) => { + let url = PLEROMA_SCROBBLES_URL(accountId) + const params = [['limit', limit]] + const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') + url += `?${queryString}` + return fetch(url, {}) + .then((response) => { + if (response.ok) { + return response.json() + } else { + return { + error: response + } + } + }) +} + const apiService = { verifyCredentials, fetchTimeline, @@ -1878,6 +1896,7 @@ const apiService = { postAnnouncement, editAnnouncement, deleteAnnouncement, + fetchScrobbles, adminFetchAnnouncements, fetchInstanceDBConfig, fetchInstanceConfigDescriptions, diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js @@ -133,3 +133,17 @@ export const prepareNotificationObject = (notification, i18n) => { return notifObj } + +export const countExtraNotifications = (store) => { + const mergedConfig = store.getters.mergedConfig + + if (!mergedConfig.showExtraNotifications) { + return 0 + } + + return [ + mergedConfig.showChatsInExtraNotifications ? store.getters.unreadChatCount : 0, + mergedConfig.showAnnouncementsInExtraNotifications ? store.getters.unreadAnnouncementCount : 0, + mergedConfig.showFollowRequestsInExtraNotifications ? store.getters.followRequestCount : 0 + ].reduce((a, c) => a + c, 0) +} diff --git a/src/services/random_seed/random_seed.service.js b/src/services/random_seed/random_seed.service.js @@ -0,0 +1,3 @@ +const genRandomSeed = () => `${Math.random()}`.replace('.', '-') + +export default genRandomSeed diff --git a/tools/collect-changelog b/tools/collect-changelog @@ -0,0 +1,27 @@ +#!/bin/sh + +collectType() { + local suffix="$1" + local header="$2" + local printed=0 + for file in changelog.d/*."$suffix"; do + if [ '!' -f "$file" ]; then + continue + fi + if [ "$printed" = 0 ]; then + echo + echo "### $header" + printed=1 + fi + # Normalize any trailing newlines/spaces, etc. + echo "- $(cat "$file")" + done +} + +collectType security Security +collectType change Changed +collectType add Added +collectType fix Fixed +collectType remove Removed + +rm changelog.d/*