Merge remote-tracking branch 'upstream/develop' into neckbeard
This commit is contained in:
commit
b4ad6c5e63
26
package.json
26
package.json
|
@ -34,7 +34,6 @@
|
|||
"escape-html": "1.0.3",
|
||||
"js-cookie": "3.0.1",
|
||||
"localforage": "1.10.0",
|
||||
"lozad": "1.16.0",
|
||||
"parse-link-header": "2.0.0",
|
||||
"phoenix": "1.6.2",
|
||||
"punycode.js": "2.1.0",
|
||||
|
@ -46,6 +45,7 @@
|
|||
"vue-i18n": "9.2.2",
|
||||
"vue-router": "4.1.6",
|
||||
"vue-template-compiler": "2.7.14",
|
||||
"vue-virtual-scroller": "^2.0.0-beta.7",
|
||||
"vuex": "4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -59,26 +59,26 @@
|
|||
"@vue/babel-helper-vue-jsx-merge-props": "1.4.0",
|
||||
"@vue/babel-plugin-jsx": "1.1.1",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"@vue/test-utils": "2.2.6",
|
||||
"@vue/test-utils": "2.2.7",
|
||||
"autoprefixer": "10.4.13",
|
||||
"babel-loader": "8.3.0",
|
||||
"babel-loader": "9.1.0",
|
||||
"babel-plugin-lodash": "3.3.4",
|
||||
"chai": "4.3.7",
|
||||
"chalk": "1.1.3",
|
||||
"chromedriver": "104.0.0",
|
||||
"chromedriver": "108.0.0",
|
||||
"connect-history-api-fallback": "2.0.0",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"css-loader": "6.7.3",
|
||||
"css-minimizer-webpack-plugin": "4.2.2",
|
||||
"custom-event-polyfill": "1.0.7",
|
||||
"eslint": "8.30.0",
|
||||
"eslint": "8.31.0",
|
||||
"eslint-config-standard": "17.0.0",
|
||||
"eslint-formatter-friendly": "7.0.0",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-n": "15.6.0",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-vue": "9.7.0",
|
||||
"eslint-plugin-vue": "9.8.0",
|
||||
"eslint-webpack-plugin": "3.2.0",
|
||||
"eventsource-polyfill": "0.9.6",
|
||||
"express": "4.18.2",
|
||||
|
@ -97,27 +97,27 @@
|
|||
"karma-spec-reporter": "0.0.36",
|
||||
"karma-webpack": "5.0.0",
|
||||
"lodash": "4.17.21",
|
||||
"mini-css-extract-plugin": "2.6.1",
|
||||
"mocha": "10.0.0",
|
||||
"nightwatch": "2.3.3",
|
||||
"mini-css-extract-plugin": "2.7.2",
|
||||
"mocha": "10.2.0",
|
||||
"nightwatch": "2.6.6",
|
||||
"opn": "5.5.0",
|
||||
"ora": "0.4.1",
|
||||
"postcss": "8.4.20",
|
||||
"postcss-loader": "7.0.2",
|
||||
"sass": "1.55.0",
|
||||
"sass-loader": "13.0.2",
|
||||
"sass": "1.57.1",
|
||||
"sass-loader": "13.2.0",
|
||||
"selenium-server": "2.53.1",
|
||||
"semver": "7.3.8",
|
||||
"serviceworker-webpack5-plugin": "2.0.0",
|
||||
"shelljs": "0.8.5",
|
||||
"sinon": "14.0.2",
|
||||
"sinon": "15.0.1",
|
||||
"sinon-chai": "3.7.0",
|
||||
"stylelint": "13.13.1",
|
||||
"stylelint-config-standard": "20.0.0",
|
||||
"stylelint-rscss": "0.4.0",
|
||||
"vue-loader": "17.0.1",
|
||||
"vue-style-loader": "4.1.3",
|
||||
"webpack": "5.74.0",
|
||||
"webpack": "5.75.0",
|
||||
"webpack-dev-middleware": "3.7.3",
|
||||
"webpack-hot-middleware": "2.25.3",
|
||||
"webpack-merge": "0.20.0"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { createApp } from 'vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import vClickOutside from 'click-outside-vue3'
|
||||
import VueVirtualScroller from 'vue-virtual-scroller'
|
||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||
|
||||
import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
|
@ -397,6 +399,7 @@ const afterStoreSetup = async ({ store, i18n }) => {
|
|||
|
||||
app.use(vClickOutside)
|
||||
app.use(VBodyScrollLock)
|
||||
app.use(VueVirtualScroller)
|
||||
|
||||
app.component('FAIcon', FontAwesomeIcon)
|
||||
app.component('FALayers', FontAwesomeLayers)
|
||||
|
|
|
@ -27,6 +27,9 @@ const Announcement = {
|
|||
...mapState({
|
||||
currentUser: state => state.users.currentUser
|
||||
}),
|
||||
canEditAnnouncement () {
|
||||
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
|
||||
},
|
||||
content () {
|
||||
return this.announcement.content
|
||||
},
|
||||
|
|
|
@ -45,14 +45,14 @@
|
|||
{{ $t('announcements.mark_as_read_action') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="currentUser && currentUser.role === 'admin'"
|
||||
v-if="canEditAnnouncement"
|
||||
class="btn button-default"
|
||||
@click="enterEditMode"
|
||||
>
|
||||
{{ $t('announcements.edit_action') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="currentUser && currentUser.role === 'admin'"
|
||||
v-if="canEditAnnouncement"
|
||||
class="btn button-default"
|
||||
@click="deleteAnnouncement"
|
||||
>
|
||||
|
|
|
@ -28,6 +28,9 @@ const AnnouncementsPage = {
|
|||
}),
|
||||
announcements () {
|
||||
return this.$store.state.announcements.announcements
|
||||
},
|
||||
canPostAnnouncement () {
|
||||
return this.currentUser && this.currentUser.privileges.includes('announcements_manage_announcements')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</div>
|
||||
<div class="panel-body">
|
||||
<section
|
||||
v-if="currentUser && currentUser.role === 'admin'"
|
||||
v-if="canPostAnnouncement"
|
||||
>
|
||||
<div class="post-form">
|
||||
<div class="heading">
|
||||
|
|
|
@ -3,7 +3,6 @@ import Checkbox from '../checkbox/checkbox.vue'
|
|||
import Popover from 'src/components/popover/popover.vue'
|
||||
import StillImage from '../still-image/still-image.vue'
|
||||
import { ensureFinalFallback } from '../../i18n/languages.js'
|
||||
import lozad from 'lozad'
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import {
|
||||
faBoxOpen,
|
||||
|
@ -19,7 +18,7 @@ import {
|
|||
faCode,
|
||||
faFlag
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { debounce, trim } from 'lodash'
|
||||
import { debounce, trim, chunk } from 'lodash'
|
||||
|
||||
library.add(
|
||||
faBoxOpen,
|
||||
|
@ -82,6 +81,17 @@ const filterByKeyword = (list, keyword = '', languages, nameLocalizer) => {
|
|||
return orderedEmojiList.flat()
|
||||
}
|
||||
|
||||
const getOffset = (elem) => {
|
||||
const style = elem.style.transform
|
||||
const res = /translateY\((\d+)px\)/.exec(style)
|
||||
if (!res) { return 0 }
|
||||
return res[1]
|
||||
}
|
||||
|
||||
const toHeaderId = id => {
|
||||
return id.replace(/^row-\d+-/, '')
|
||||
}
|
||||
|
||||
const EmojiPicker = {
|
||||
props: {
|
||||
enableStickerPicker: {
|
||||
|
@ -102,7 +112,8 @@ const EmojiPicker = {
|
|||
contentLoaded: false,
|
||||
groupRefs: {},
|
||||
emojiRefs: {},
|
||||
filteredEmojiGroups: []
|
||||
filteredEmojiGroups: [],
|
||||
width: 0
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
@ -125,9 +136,6 @@ const EmojiPicker = {
|
|||
setGroupRef (name) {
|
||||
return el => { this.groupRefs[name] = el }
|
||||
},
|
||||
setEmojiRef (name) {
|
||||
return el => { this.emojiRefs[name] = el }
|
||||
},
|
||||
onPopoverShown () {
|
||||
this.$emit('show')
|
||||
},
|
||||
|
@ -147,18 +155,21 @@ const EmojiPicker = {
|
|||
}
|
||||
this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })
|
||||
},
|
||||
onScroll (e) {
|
||||
const target = (e && e.target) || this.$refs['emoji-groups']
|
||||
this.updateScrolledClass(target)
|
||||
this.scrolledGroup(target)
|
||||
onScroll (startIndex, endIndex, visibleStartIndex, visibleEndIndex) {
|
||||
const target = this.$refs['emoji-groups'].$el
|
||||
this.scrolledGroup(target, visibleStartIndex, visibleEndIndex)
|
||||
},
|
||||
scrolledGroup (target) {
|
||||
scrolledGroup (target, start, end) {
|
||||
const top = target.scrollTop + 5
|
||||
this.$nextTick(() => {
|
||||
this.allEmojiGroups.forEach(group => {
|
||||
this.emojiItems.slice(start, end + 1).forEach(group => {
|
||||
const headerId = toHeaderId(group.id)
|
||||
const ref = this.groupRefs['group-' + group.id]
|
||||
if (ref && ref.offsetTop <= top) {
|
||||
this.activeGroup = group.id
|
||||
if (!ref) { return }
|
||||
const elem = ref.$el.parentElement
|
||||
if (!elem) { return }
|
||||
if (elem && getOffset(elem) <= top) {
|
||||
this.activeGroup = headerId
|
||||
}
|
||||
})
|
||||
this.scrollHeader()
|
||||
|
@ -181,14 +192,10 @@ const EmojiPicker = {
|
|||
setScroll(right + margin - headerCont.clientWidth)
|
||||
}
|
||||
},
|
||||
highlight (key) {
|
||||
const ref = this.groupRefs['group-' + key]
|
||||
const top = ref.offsetTop
|
||||
highlight (groupId) {
|
||||
this.setShowStickers(false)
|
||||
this.activeGroup = key
|
||||
this.$nextTick(() => {
|
||||
this.$refs['emoji-groups'].scrollTop = top + 1
|
||||
})
|
||||
const indexInList = this.emojiItems.findIndex(k => k.id === groupId)
|
||||
this.$refs['emoji-groups'].scrollToItem(indexInList)
|
||||
},
|
||||
updateScrolledClass (target) {
|
||||
if (target.scrollTop <= 5) {
|
||||
|
@ -208,43 +215,13 @@ const EmojiPicker = {
|
|||
filterByKeyword (list, keyword) {
|
||||
return filterByKeyword(list, keyword, this.languages, this.maybeLocalizedEmojiName)
|
||||
},
|
||||
initializeLazyLoad () {
|
||||
this.destroyLazyLoad()
|
||||
this.$nextTick(() => {
|
||||
this.$lozad = lozad('.still-image.emoji-picker-emoji', {
|
||||
load: el => {
|
||||
const name = el.getAttribute('data-emoji-name')
|
||||
const vn = this.emojiRefs[name]
|
||||
if (!vn) {
|
||||
return
|
||||
}
|
||||
|
||||
vn.loadLazy()
|
||||
}
|
||||
})
|
||||
this.$lozad.observe()
|
||||
})
|
||||
},
|
||||
waitForDomAndInitializeLazyLoad () {
|
||||
this.$nextTick(() => this.initializeLazyLoad())
|
||||
},
|
||||
destroyLazyLoad () {
|
||||
if (this.$lozad) {
|
||||
if (this.$lozad.observer) {
|
||||
this.$lozad.observer.disconnect()
|
||||
}
|
||||
if (this.$lozad.mutationObserver) {
|
||||
this.$lozad.mutationObserver.disconnect()
|
||||
}
|
||||
}
|
||||
},
|
||||
onShowing () {
|
||||
const oldContentLoaded = this.contentLoaded
|
||||
this.recalculateItemPerRow()
|
||||
this.$nextTick(() => {
|
||||
this.$refs.search.focus()
|
||||
})
|
||||
this.contentLoaded = true
|
||||
this.waitForDomAndInitializeLazyLoad()
|
||||
this.filteredEmojiGroups = this.getFilteredEmojiGroups()
|
||||
if (!oldContentLoaded) {
|
||||
this.$nextTick(() => {
|
||||
|
@ -261,6 +238,14 @@ const EmojiPicker = {
|
|||
emojis: this.filterByKeyword(group.emojis, trim(this.keyword))
|
||||
}))
|
||||
.filter(group => group.emojis.length > 0)
|
||||
},
|
||||
recalculateItemPerRow () {
|
||||
this.$nextTick(() => {
|
||||
if (!this.$refs['emoji-groups']) {
|
||||
return
|
||||
}
|
||||
this.width = this.$refs['emoji-groups'].$el.offsetWidth
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -269,14 +254,22 @@ const EmojiPicker = {
|
|||
this.debouncedHandleKeywordChange()
|
||||
},
|
||||
allCustomGroups () {
|
||||
this.waitForDomAndInitializeLazyLoad()
|
||||
this.filteredEmojiGroups = this.getFilteredEmojiGroups()
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
this.destroyLazyLoad()
|
||||
},
|
||||
computed: {
|
||||
minItemSize () {
|
||||
return this.emojiHeight
|
||||
},
|
||||
emojiHeight () {
|
||||
return 32 + 4
|
||||
},
|
||||
emojiWidth () {
|
||||
return 32 + 4
|
||||
},
|
||||
itemPerRow () {
|
||||
return this.width ? Math.floor(this.width / this.emojiWidth - 1) : 6
|
||||
},
|
||||
activeGroupView () {
|
||||
return this.showingStickers ? '' : this.activeGroup
|
||||
},
|
||||
|
@ -287,7 +280,11 @@ const EmojiPicker = {
|
|||
return 0
|
||||
},
|
||||
allCustomGroups () {
|
||||
return this.$store.getters.groupedCustomEmojis
|
||||
const emojis = this.$store.getters.groupedCustomEmojis
|
||||
if (emojis.unpacked) {
|
||||
emojis.unpacked.text = this.$t('emoji.unpacked')
|
||||
}
|
||||
return emojis
|
||||
},
|
||||
defaultGroup () {
|
||||
return Object.keys(this.allCustomGroups)[0]
|
||||
|
@ -310,10 +307,20 @@ const EmojiPicker = {
|
|||
},
|
||||
debouncedHandleKeywordChange () {
|
||||
return debounce(() => {
|
||||
this.waitForDomAndInitializeLazyLoad()
|
||||
this.filteredEmojiGroups = this.getFilteredEmojiGroups()
|
||||
}, 500)
|
||||
},
|
||||
emojiItems () {
|
||||
return this.filteredEmojiGroups.map(group =>
|
||||
chunk(group.emojis, this.itemPerRow)
|
||||
.map((items, index) => ({
|
||||
...group,
|
||||
id: index === 0 ? group.id : `row-${index}-${group.id}`,
|
||||
emojis: items,
|
||||
isFirstRow: index === 0
|
||||
})))
|
||||
.reduce((a, c) => a.concat(c), [])
|
||||
},
|
||||
languages () {
|
||||
return ensureFinalFallback(this.$store.getters.mergedConfig.interfaceLanguage)
|
||||
},
|
||||
|
|
|
@ -74,6 +74,7 @@ $emoji-picker-emoji-size: 32px;
|
|||
}
|
||||
|
||||
.emoji-groups {
|
||||
height: 100%;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,45 +74,56 @@
|
|||
@input="$event.target.composing = false"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
<DynamicScroller
|
||||
ref="emoji-groups"
|
||||
class="emoji-groups"
|
||||
:class="groupsScrolledClass"
|
||||
@scroll="onScroll"
|
||||
:min-item-size="minItemSize"
|
||||
:items="emojiItems"
|
||||
:emit-update="true"
|
||||
@update="onScroll"
|
||||
@visible="recalculateItemPerRow"
|
||||
>
|
||||
<div
|
||||
v-for="group in filteredEmojiGroups"
|
||||
:key="group.id"
|
||||
class="emoji-group"
|
||||
>
|
||||
<h6
|
||||
<template #default="{ item: group, index, active }">
|
||||
<DynamicScrollerItem
|
||||
:ref="setGroupRef('group-' + group.id)"
|
||||
class="emoji-group-title"
|
||||
:item="group"
|
||||
:active="active"
|
||||
:data-index="index"
|
||||
:size-dependencies="[group.emojis.length]"
|
||||
>
|
||||
{{ group.text }}
|
||||
</h6>
|
||||
<span
|
||||
v-for="emoji in group.emojis"
|
||||
:key="group.id + emoji.displayText"
|
||||
:title="maybeLocalizedEmojiName(emoji)"
|
||||
class="emoji-item"
|
||||
@click.stop.prevent="onEmoji(emoji)"
|
||||
>
|
||||
<span
|
||||
v-if="!emoji.imageUrl"
|
||||
class="emoji-picker-emoji -unicode"
|
||||
>{{ emoji.replacement }}</span>
|
||||
<still-image
|
||||
v-else
|
||||
:ref="setEmojiRef(group.id + emoji.displayText)"
|
||||
class="emoji-picker-emoji -custom"
|
||||
:data-src="emoji.imageUrl"
|
||||
:data-emoji-name="group.id + emoji.displayText"
|
||||
/>
|
||||
</span>
|
||||
<span :ref="setGroupRef('group-end-' + group.id)" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="emoji-group"
|
||||
>
|
||||
<h6
|
||||
v-if="group.isFirstRow"
|
||||
class="emoji-group-title"
|
||||
>
|
||||
{{ group.text }}
|
||||
</h6>
|
||||
<span
|
||||
v-for="emoji in group.emojis"
|
||||
:key="group.id + emoji.displayText"
|
||||
:title="maybeLocalizedEmojiName(emoji)"
|
||||
class="emoji-item"
|
||||
@click.stop.prevent="onEmoji(emoji)"
|
||||
>
|
||||
<span
|
||||
v-if="!emoji.imageUrl"
|
||||
class="emoji-picker-emoji -unicode"
|
||||
>{{ emoji.replacement }}</span>
|
||||
<still-image
|
||||
v-else
|
||||
class="emoji-picker-emoji -custom"
|
||||
loading="lazy"
|
||||
:src="emoji.imageUrl"
|
||||
:data-emoji-name="group.id + emoji.displayText"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
<div class="keep-open">
|
||||
<Checkbox v-model="keepOpen">
|
||||
{{ $t('emoji.keep_open') }}
|
||||
|
|
|
@ -95,10 +95,10 @@ const ListsNew = {
|
|||
return this.addedUserIds.has(user.id)
|
||||
},
|
||||
addUser (user) {
|
||||
this.$store.dispatch('addListAccount', { accountId: this.user.id, listId: this.id })
|
||||
this.$store.dispatch('addListAccount', { accountId: user.id, listId: this.id })
|
||||
},
|
||||
removeUser (userId) {
|
||||
this.$store.dispatch('removeListAccount', { accountId: this.user.id, listId: this.id })
|
||||
this.$store.dispatch('removeListAccount', { accountId: userId, listId: this.id })
|
||||
},
|
||||
onSearchLoading (results) {
|
||||
this.searchLoading = true
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
@import '../../variables';
|
||||
|
||||
.RichContent {
|
||||
blockquote {
|
||||
margin: 0.2em 0 0.2em 2em;
|
||||
margin: 0.2em 0 0.2em 0.2em;
|
||||
font-style: italic;
|
||||
border-left: 0.2em solid var(--faint, $fallback--faint);
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
pre {
|
||||
|
|
|
@ -77,6 +77,16 @@
|
|||
>
|
||||
{{ $t('settings.download_backup') }}
|
||||
</a>
|
||||
<span
|
||||
v-else-if="backup.state === 'running'"
|
||||
>
|
||||
{{ $tc('settings.backup_running', backup.processed_number, { number: backup.processed_number }) }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="backup.state === 'failed'"
|
||||
>
|
||||
{{ $t('settings.backup_failed') }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
>
|
||||
|
|
|
@ -8,7 +8,8 @@ const StillImage = {
|
|||
'alt',
|
||||
'height',
|
||||
'width',
|
||||
'dataSrc'
|
||||
'dataSrc',
|
||||
'loading'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
:data-src="dataSrc"
|
||||
:src="realSrc"
|
||||
:referrerpolicy="referrerpolicy"
|
||||
:loading="loading"
|
||||
@load="onLoad"
|
||||
@error="onError"
|
||||
>
|
||||
|
|
|
@ -225,6 +225,7 @@
|
|||
"search_emoji": "Search for an emoji",
|
||||
"add_emoji": "Insert emoji",
|
||||
"custom": "Custom emoji",
|
||||
"unpacked": "Unpacked emoji",
|
||||
"unicode": "Unicode emoji",
|
||||
"unicode_groups": {
|
||||
"activities": "Activities",
|
||||
|
@ -390,6 +391,8 @@
|
|||
"account_backup_table_head": "Backup",
|
||||
"download_backup": "Download",
|
||||
"backup_not_ready": "This backup is not ready yet.",
|
||||
"backup_running": "This backup is in progress, processed {number} record. | This backup is in progress, processed {number} records.",
|
||||
"backup_failed": "This backup has failed.",
|
||||
"remove_backup": "Remove",
|
||||
"list_backups_error": "Error fetching backup list: {error}",
|
||||
"add_backup": "Create a new backup",
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
"friend_requests": "Petoj pri abono",
|
||||
"mentions": "Mencioj",
|
||||
"dms": "Rektaj mesaĝoj",
|
||||
"public_tl": "Loka historio",
|
||||
"public_tl": "Noda historio",
|
||||
"timeline": "Historio",
|
||||
"twkn": "Federa historio",
|
||||
"user_search": "Serĉi uzantojn",
|
||||
|
@ -112,16 +112,19 @@
|
|||
"edit_pinned": "Redakti fiksitajn erojn",
|
||||
"lists": "Listoj",
|
||||
"edit_nav_mobile": "Adapti navigan breton",
|
||||
"edit_finish": "Fini redakton"
|
||||
"edit_finish": "Fini redakton",
|
||||
"mobile_notifications": "Malfermi sciigojn (estas nelegitaj)",
|
||||
"mobile_notifications_close": "Fermi sciigojn",
|
||||
"announcements": "Anoncoj"
|
||||
},
|
||||
"notifications": {
|
||||
"broken_favorite": "Nekonata stato, serĉante ĝin…",
|
||||
"favorited_you": "ŝatis vian staton",
|
||||
"broken_favorite": "Nekonata afiŝo, serĉante ĝin…",
|
||||
"favorited_you": "ŝatis vian afiŝon",
|
||||
"followed_you": "ekabonis vin",
|
||||
"load_older": "Enlegi pli malnovajn sciigojn",
|
||||
"notifications": "Sciigoj",
|
||||
"read": "Legite!",
|
||||
"repeated_you": "ripetis vian staton",
|
||||
"repeated_you": "ripetis vian afiŝon",
|
||||
"no_more_notifications": "Neniuj pliaj sciigoj",
|
||||
"reacted_with": "reagis per {0}",
|
||||
"migrated_to": "migris al",
|
||||
|
@ -131,7 +134,7 @@
|
|||
"poll_ended": "enketo finiĝis"
|
||||
},
|
||||
"post_status": {
|
||||
"new_status": "Afiŝi novan staton",
|
||||
"new_status": "Afiŝi",
|
||||
"account_not_locked_warning": "Via konto ne estas {0}. Iu ajn povas vin aboni por vidi eĉ viajn afiŝoj nur por abonantoj.",
|
||||
"account_not_locked_warning_link": "ŝlosita",
|
||||
"attachments_sensitive": "Marki kunsendaĵojn konsternaj",
|
||||
|
@ -152,12 +155,12 @@
|
|||
"unlisted": "Nelistigita – ne afiŝi al publikaj historioj"
|
||||
},
|
||||
"scope_notice": {
|
||||
"unlisted": "Ĉi tiu afiŝo ne estos videbla en la Loka historio kaj la Federa historio",
|
||||
"unlisted": "Ĉi tiu afiŝo ne estos videbla en la Noda kaj la Federa historioj",
|
||||
"private": "Ĉi tiu afiŝo estos videbla nur al viaj abonantoj",
|
||||
"public": "Ĉi tiu afiŝo estos videbla al ĉiuj"
|
||||
},
|
||||
"media_description_error": "Malsukcesis afiŝo de vidaŭdaĵoj; reprovu",
|
||||
"empty_status_error": "Ne povas afiŝi malplenan staton sen dosieroj",
|
||||
"empty_status_error": "Ne povas fari malplenan afiŝon sen dosieroj",
|
||||
"preview_empty": "Malplena",
|
||||
"preview": "Antaŭrigardo",
|
||||
"direct_warning_to_first_only": "Ĉi tiu afiŝo estas nur videbla al uzantoj menciitaj je la komenco de la mesaĝo.",
|
||||
|
@ -166,7 +169,7 @@
|
|||
"post": "Afiŝo",
|
||||
"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": "Stato de redakto"
|
||||
"edit_status": "Redakti afiŝon"
|
||||
},
|
||||
"registration": {
|
||||
"bio": "Priskribo",
|
||||
|
@ -228,7 +231,7 @@
|
|||
"avatar_size_instruction": "La rekomendata minimuma grando de profilbildoj estas 150×150 bilderoj.",
|
||||
"export_theme": "Konservi antaŭagordon",
|
||||
"filtering": "Filtrado",
|
||||
"filtering_explanation": "Ĉiuj statoj kun tiuj ĉi vortoj silentiĝos; skribu po unu linie",
|
||||
"filtering_explanation": "Ĉiuj afiŝoj kun tiuj ĉi vortoj silentiĝos; skribu po unu linie",
|
||||
"follow_export": "Elporto de abonoj",
|
||||
"follow_export_button": "Elporti viajn abonojn al CSV-dosiero",
|
||||
"follow_export_processing": "Traktante; baldaŭ vi ricevos peton elŝuti la dosieron",
|
||||
|
@ -245,7 +248,7 @@
|
|||
"use_one_click_nsfw": "Malfermi konsternajn kunsendaĵojn per nur unu klako",
|
||||
"hide_post_stats": "Kaŝi statistikon de afiŝoj (ekz. nombron de ŝatoj)",
|
||||
"hide_user_stats": "Kaŝi statistikon de uzantoj (ekz. nombron de abonantoj)",
|
||||
"hide_filtered_statuses": "Kaŝi filtritajn statojn",
|
||||
"hide_filtered_statuses": "Kaŝi ĉiujn filtritajn afiŝojn",
|
||||
"import_followers_from_a_csv_file": "Enporti abonojn el CSV-dosiero",
|
||||
"import_theme": "Enlegi antaŭagordojn",
|
||||
"inputRadius": "Enigaj kampoj",
|
||||
|
@ -278,7 +281,7 @@
|
|||
"hide_followers_description": "Ne montri kiu min sekvas",
|
||||
"show_admin_badge": "Montri la insignon de administranto en mia profilo",
|
||||
"show_moderator_badge": "Montri la insignon de reguligisto en mia profilo",
|
||||
"nsfw_clickthrough": "Ŝalti traklakan kaŝadon de kunsendaĵoj kaj antaŭmontroj de ligiloj por konsternaj statoj",
|
||||
"nsfw_clickthrough": "Ŝalti traklakan kaŝadon de kunsendaĵoj kaj antaŭmontroj de ligiloj por konsternaj afiŝoj",
|
||||
"oauth_tokens": "Pecoj de OAuth",
|
||||
"token": "Peco",
|
||||
"refresh_token": "Aktualiga peco",
|
||||
|
@ -627,14 +630,14 @@
|
|||
"word_filter_and_more": "Vortofiltrado kaj pli…",
|
||||
"mute_bot_posts": "Silentigi afiŝojn de robotoj",
|
||||
"hide_bot_indication": "Kaŝi markon de roboteco en afiŝoj",
|
||||
"hide_wordfiltered_statuses": "Kaŝi vorte filtritajn statojn",
|
||||
"hide_wordfiltered_statuses": "Kaŝi vorte filtritajn afiŝojn",
|
||||
"hide_muted_threads": "Kaŝi silentigitajn fadenojn",
|
||||
"account_privacy": "Privateco",
|
||||
"user_profiles": "Profiloj de uzantoj",
|
||||
"hide_favorites_description": "Ne montri liston de miaj ŝatatoj (oni tamen sciiĝas)",
|
||||
"conversation_display_tree": "Arba stilo",
|
||||
"conversation_display_tree_quick": "Arba vido",
|
||||
"show_scrollbars": "Montri rulumajn bretojn de flankaj kolumnoj",
|
||||
"show_scrollbars": "Montri rulumskalojn de flankaj kolumnoj",
|
||||
"third_column_mode_none": "Neniam montri trian kolumnon",
|
||||
"third_column_mode_notifications": "Kolumno de sciigoj",
|
||||
"columns": "Kolumnoj",
|
||||
|
@ -644,9 +647,9 @@
|
|||
"column_sizes_notifs": "Sciigoj",
|
||||
"tree_advanced": "Permesi pli flekseblan navigadon en arba vido",
|
||||
"conversation_display_linear": "Linia stilo",
|
||||
"conversation_other_replies_button": "Montri la butonon «aliaj respondoj»",
|
||||
"conversation_other_replies_button_below": "Sub statoj",
|
||||
"conversation_other_replies_button_inside": "En statoj",
|
||||
"conversation_other_replies_button": "Montri la butonon pri «aliaj respondoj»",
|
||||
"conversation_other_replies_button_below": "Sub afiŝoj",
|
||||
"conversation_other_replies_button_inside": "En afiŝoj",
|
||||
"max_depth_in_thread": "Maksimuma nombro de niveloj implicite montrataj en fadeno",
|
||||
"auto_update": "Montri novajn afiŝojn memage",
|
||||
"use_at_icon": "Montri simbolon {'@'} kiel bildon anstataŭ teksto",
|
||||
|
@ -662,19 +665,20 @@
|
|||
"user_popover_avatar_action_open": "Malfermi la profilon",
|
||||
"user_popover_avatar_overlay": "Aperigi ŝprucaĵon pri uzanto sur profilbildo",
|
||||
"show_yous": "Montri la markon «(Vi)»",
|
||||
"user_popover_avatar_action_zoom": "Zomi la profilbildon"
|
||||
"user_popover_avatar_action_zoom": "Zomi la profilbildon",
|
||||
"third_column_mode": "Kun sufiĉo da spaco, montri trian kolumnon kun"
|
||||
},
|
||||
"timeline": {
|
||||
"collapse": "Maletendi",
|
||||
"conversation": "Interparolo",
|
||||
"error_fetching": "Eraris ĝisdatigo",
|
||||
"load_older": "Montri pli malnovajn statojn",
|
||||
"load_older": "Montri pli malnovajn afiŝojn",
|
||||
"no_retweet_hint": "Afiŝo estas markita kiel rekta aŭ nur por abonantoj, kaj ne eblas ĝin ripeti",
|
||||
"repeated": "ripetis",
|
||||
"show_new": "Montri novajn",
|
||||
"up_to_date": "Ĝisdata",
|
||||
"no_more_statuses": "Neniuj pliaj statoj",
|
||||
"no_statuses": "Neniuj statoj",
|
||||
"no_more_statuses": "Neniuj pliaj afiŝoj",
|
||||
"no_statuses": "Neniuj afiŝoj",
|
||||
"reload": "Enlegi ree",
|
||||
"error": "Eraris akirado de historio: {0}",
|
||||
"socket_reconnected": "Realtempa konekto fariĝis",
|
||||
|
@ -700,7 +704,7 @@
|
|||
"muted": "Silentigita",
|
||||
"per_day": "tage",
|
||||
"remote_follow": "Fore aboni",
|
||||
"statuses": "Statoj",
|
||||
"statuses": "Afiŝoj",
|
||||
"unblock": "Malbloki",
|
||||
"unblock_progress": "Malblokante…",
|
||||
"block_progress": "Blokante…",
|
||||
|
@ -744,7 +748,12 @@
|
|||
"edit_profile": "Redakti profilon",
|
||||
"deactivated": "Malaktiva",
|
||||
"follow_cancel": "Nuligi peton",
|
||||
"remove_follower": "Forigi abonanton"
|
||||
"remove_follower": "Forigi abonanton",
|
||||
"note": "Noto",
|
||||
"note_blank": "(Neniu)",
|
||||
"edit_note_apply": "Apliki",
|
||||
"edit_note_cancel": "Nuligi",
|
||||
"edit_note": "Redakti noton"
|
||||
},
|
||||
"user_profile": {
|
||||
"timeline_title": "Historio de uzanto",
|
||||
|
@ -764,7 +773,9 @@
|
|||
"bookmark": "Legosigno",
|
||||
"reject_follow_request": "Rifuzi abonpeton",
|
||||
"accept_follow_request": "Akcepti abonpeton",
|
||||
"add_reaction": "Aldoni reagon"
|
||||
"add_reaction": "Aldoni reagon",
|
||||
"toggle_expand": "Etendi aŭ maletendi sciigon por montri plenan afiŝon",
|
||||
"toggle_mute": "Etendi aŭ maletendi afiŝon por montri silentigitan enhavon"
|
||||
},
|
||||
"upload": {
|
||||
"error": {
|
||||
|
@ -893,19 +904,19 @@
|
|||
"show_full_subject": "Montri plenan temon",
|
||||
"thread_muted_and_words": ", enhavas vortojn:",
|
||||
"thread_muted": "Fadeno silentigita",
|
||||
"copy_link": "Kopii ligilon al stato",
|
||||
"status_unavailable": "Stato ne estas disponebla",
|
||||
"copy_link": "Kopii ligilon al afiŝo",
|
||||
"status_unavailable": "Afiŝo ne estas disponebla",
|
||||
"unmute_conversation": "Malsilentigi interparolon",
|
||||
"mute_conversation": "Silentigi interparolon",
|
||||
"replies_list": "Respondoj:",
|
||||
"reply_to": "Responde al",
|
||||
"delete_confirm": "Ĉu vi certe volas forigi ĉi tiun staton?",
|
||||
"delete_confirm": "Ĉu vi certe volas forigi ĉi tiun afiŝon?",
|
||||
"unbookmark": "Senlegosigni",
|
||||
"bookmark": "Legosigni",
|
||||
"pinned": "Fiksita",
|
||||
"unpin": "Malfiksi de profilo",
|
||||
"pin": "Fiksi al profilo",
|
||||
"delete": "Forigi staton",
|
||||
"delete": "Forigi afiŝon",
|
||||
"repeats": "Ripetoj",
|
||||
"favorites": "Ŝatoj",
|
||||
"status_deleted": "Ĉi tiu afiŝo foriĝis",
|
||||
|
@ -939,7 +950,8 @@
|
|||
"ancestor_follow_with_icon": "{icon} {text}",
|
||||
"show_all_conversation_with_icon": "{icon} {text}",
|
||||
"show_only_conversation_under_this": "Montri nur respondojn al ĉi tiu afiŝo",
|
||||
"status_history": "Historio de afiŝo"
|
||||
"status_history": "Historio de afiŝo",
|
||||
"open_gallery": "Malfermi galerion"
|
||||
},
|
||||
"time": {
|
||||
"years_short": "{0}j",
|
||||
|
@ -996,7 +1008,9 @@
|
|||
"no_results": "Neniuj rezultoj",
|
||||
"people_talking": "{count} personoj parolas",
|
||||
"person_talking": "{count} persono parolas",
|
||||
"hashtags": "Kradvortoj"
|
||||
"hashtags": "Kradvortoj",
|
||||
"no_more_results": "Neniuj pliaj rezultoj",
|
||||
"load_more": "Enlegi pliajn rezultojn"
|
||||
},
|
||||
"display_date": {
|
||||
"today": "Hodiaŭ"
|
||||
|
@ -1047,9 +1061,9 @@
|
|||
"report": {
|
||||
"reporter": "Raportinto:",
|
||||
"reported_user": "Raportito:",
|
||||
"reported_statuses": "Raportitaj statoj:",
|
||||
"reported_statuses": "Raportitaj afiŝoj:",
|
||||
"notes": "Notoj:",
|
||||
"state": "Stato:",
|
||||
"state": "Afiŝo:",
|
||||
"state_open": "Malfermita",
|
||||
"state_closed": "Fermita",
|
||||
"state_resolved": "Solvita"
|
||||
|
|
138
src/i18n/uk.json
138
src/i18n/uk.json
|
@ -32,7 +32,13 @@
|
|||
"private": "Лише читачі",
|
||||
"public": "Публічне",
|
||||
"unlisted": "Непублічне"
|
||||
}
|
||||
},
|
||||
"undo": "Відмінити",
|
||||
"yes": "Так",
|
||||
"no": "Ні",
|
||||
"unpin": "Відкріпити",
|
||||
"scroll_to_top": "Вгору",
|
||||
"pin": "Прикріпити"
|
||||
},
|
||||
"finder": {
|
||||
"error_fetching_user": "Користувача не знайдено",
|
||||
|
@ -48,7 +54,7 @@
|
|||
"media_proxy": "Посередник медіа-даних",
|
||||
"text_limit": "Ліміт символів",
|
||||
"upload_limit": "Обмеження завантажень",
|
||||
"shout": "Оголошення"
|
||||
"shout": "Гучномовець"
|
||||
},
|
||||
"exporter": {
|
||||
"processing": "Опрацьовую, скоро ви зможете завантажити файл",
|
||||
|
@ -61,7 +67,7 @@
|
|||
"mute": "Ігнорувати"
|
||||
},
|
||||
"shoutbox": {
|
||||
"title": "Оголошення"
|
||||
"title": "Гучномовець"
|
||||
},
|
||||
"about": {
|
||||
"staff": "Адміністрація",
|
||||
|
@ -81,7 +87,8 @@
|
|||
"accept_desc": "Поточний інстанс приймає повідомлення тільки з перелічених інстансів:",
|
||||
"simple_policies": "Правила поточного інстансу",
|
||||
"reason": "Причина",
|
||||
"not_applicable": "н/в"
|
||||
"not_applicable": "н/в",
|
||||
"instance": "Інстанс"
|
||||
},
|
||||
"mrf_policies_desc": "Правила MRF розповсюджуються на даний інстанс. Наступні правила активні:",
|
||||
"mrf_policies": "Активувати правила MRF (модуль переписування повідомлень)",
|
||||
|
@ -153,7 +160,8 @@
|
|||
"favorited_you": "вподобав(-ла) ваш допис",
|
||||
"broken_favorite": "Невідомий допис, шукаю його…",
|
||||
"error": "Помилка при оновленні сповіщень: {0}",
|
||||
"poll_ended": "опитування закінчено"
|
||||
"poll_ended": "опитування закінчено",
|
||||
"submitted_report": "подав скаргу"
|
||||
},
|
||||
"nav": {
|
||||
"chats": "Чати",
|
||||
|
@ -174,7 +182,14 @@
|
|||
"back": "Назад",
|
||||
"administration": "Адміністрування",
|
||||
"home_timeline": "Домашня стрічка",
|
||||
"lists": "Списки"
|
||||
"lists": "Списки",
|
||||
"edit_pinned": "Редагувати прикріплене",
|
||||
"edit_finish": "Завершити редагування",
|
||||
"mobile_sidebar": "Ввімкнути бокову панель",
|
||||
"mobile_notifications": "Відкрити сповіщення (є непрочитані)",
|
||||
"mobile_notifications_close": "Закрити сповіщення",
|
||||
"edit_nav_mobile": "Редагувати панель навігації",
|
||||
"announcements": "Анонси"
|
||||
},
|
||||
"media_modal": {
|
||||
"next": "Наступна",
|
||||
|
@ -221,7 +236,8 @@
|
|||
"follows": "Нові підписки",
|
||||
"favs_repeats": "Поширення та вподобайки",
|
||||
"moves": "Міграції користувачів",
|
||||
"emoji_reactions": "Емоджі реакції"
|
||||
"emoji_reactions": "Емоджі реакції",
|
||||
"reports": "Скарги"
|
||||
},
|
||||
"errors": {
|
||||
"storage_unavailable": "Pleroma не змогла отримати доступ до сховища браузеру. Ваша сесія та налаштування не будуть збережені, це може спричинити непередбачувані проблеми. Спробуйте увімкнути cookie."
|
||||
|
@ -235,7 +251,19 @@
|
|||
"emoji": "Емодзі",
|
||||
"load_all": "Всі {emojiAmount} эмодзі завантажуються",
|
||||
"load_all_hint": "Завантажені перші {saneAmount} емодзі, завантаження всіх емодзі може призвести до проблем з продуктивністю.",
|
||||
"unicode": "Стандартні емодзі"
|
||||
"unicode": "Стандартні емодзі",
|
||||
"regional_indicator": "Регіональний індикатор {letter}",
|
||||
"unicode_groups": {
|
||||
"animals-and-nature": "Тварини і Рослини",
|
||||
"flags": "Прапори",
|
||||
"food-and-drink": "Їжа та Напої",
|
||||
"objects": "Об'єкти",
|
||||
"people-and-body": "Люди та Тіло",
|
||||
"smileys-and-emotion": "Смайлики та Емотікони",
|
||||
"activities": "Активності",
|
||||
"symbols": "Символи",
|
||||
"travel-and-places": "Подорожі та Місця"
|
||||
}
|
||||
},
|
||||
"post_status": {
|
||||
"content_type": {
|
||||
|
@ -269,7 +297,10 @@
|
|||
"preview_empty": "Пустий",
|
||||
"media_description_error": "Не вдалось оновити медіа, спробуйте ще раз",
|
||||
"media_description": "Опис медіа",
|
||||
"post": "Опублікувати"
|
||||
"post": "Опублікувати",
|
||||
"edit_unsupported_warning": "Pleroma не підтримує редагування згадувань чи голосувань.",
|
||||
"edit_status": "Редагувати допис",
|
||||
"edit_remote_warning": "Інші віддалені інстанси можуть не підтримувати редагування та вони можуть не отримати актуальну версію допису."
|
||||
},
|
||||
"settings": {
|
||||
"blocks_imported": "Блокування імпортовані! Їх обробка триватиме певний час.",
|
||||
|
@ -654,7 +685,7 @@
|
|||
"backup_restore": "Резервне копіювання налаштувань"
|
||||
},
|
||||
"right_sidebar": "Показувати бокову панель справа",
|
||||
"hide_shoutbox": "Приховати оголошення інстансу",
|
||||
"hide_shoutbox": "Приховати гучномовець",
|
||||
"setting_server_side": "Цей параметр прив’язаний до вашого профілю та впливає на всі сеанси та клієнти",
|
||||
"lists_navigation": "Показувати списки в навігації",
|
||||
"account_backup": "Резервне копіювання облікового запису",
|
||||
|
@ -682,7 +713,33 @@
|
|||
"move_account": "Перемістити обліковий запис",
|
||||
"move_account_target": "Цільовий обліковий запис (напр. {example})",
|
||||
"moved_account": "Обліковий запис переміщено.",
|
||||
"move_account_error": "Помилка під час переміщення облікового запису: {error}"
|
||||
"move_account_error": "Помилка під час переміщення облікового запису: {error}",
|
||||
"word_filter_and_more": "Фільтр слів та більше...",
|
||||
"hide_bot_indication": "Сховати позначку бот у дописах",
|
||||
"navbar_column_stretch": "Розтягнути панель навігації на ширину колонок",
|
||||
"hide_wordfiltered_statuses": "Ховати фільтровані статуси",
|
||||
"hide_muted_threads": "Ховати приглушені треди",
|
||||
"posts": "Дописи",
|
||||
"account_privacy": "Безпека",
|
||||
"conversation_display": "Стиль відображення розмови",
|
||||
"conversation_display_tree": "Деревоподібне",
|
||||
"conversation_display_tree_quick": "Вигляд дерева",
|
||||
"disable_sticky_headers": "Не закріплювати заголовок колонки зверху на сторінці",
|
||||
"third_column_mode_none": "Не показувати третю колонку взагалі",
|
||||
"third_column_mode_notifications": "Колонка сповіщень",
|
||||
"columns": "Колонки",
|
||||
"auto_update": "Автоматично показувати нові дописи",
|
||||
"use_websockets": "Використовувати вебсокети (Оновлення в реальному часі)",
|
||||
"use_at_icon": "Показувати {'@'} символ як іконку замість тексту",
|
||||
"mute_bot_posts": "Приховати дописи ботів",
|
||||
"always_show_post_button": "Завжди показувати плаваючу кнопку «Новий Допис»",
|
||||
"hide_favorites_description": "Не показувати список моїх вподобань (люди все одно отримують сповіщення)",
|
||||
"third_column_mode": "Коли достатньо місця, показувати третю колонку, що містить",
|
||||
"user_popover_avatar_action_open": "Відкрити профіль",
|
||||
"wordfilter": "Фільтр слів",
|
||||
"mention_links": "Посилання для згадування",
|
||||
"user_profiles": "Профілі користувачів",
|
||||
"notification_visibility_polls": "Закінчення опитувань, в яких ви проголосували"
|
||||
},
|
||||
"selectable_list": {
|
||||
"select_all": "Вибрати все"
|
||||
|
@ -781,7 +838,23 @@
|
|||
"day": "{0} день",
|
||||
"seconds_short": "{0}с",
|
||||
"seconds": "{0} секунди",
|
||||
"in_future": "через {0}"
|
||||
"in_future": "через {0}",
|
||||
"unit": {
|
||||
"months": "{0} місяць | {0} місяців",
|
||||
"minutes": "{0} хвилина | {0} хвилин",
|
||||
"hours_short": "{0}год",
|
||||
"minutes_short": "{0}хв",
|
||||
"months_short": "{0}міс",
|
||||
"seconds": "{0} секунда | {0} секунд",
|
||||
"seconds_short": "{0}с",
|
||||
"weeks_short": "{0}тижд",
|
||||
"years": "{0} рік | {0} років",
|
||||
"years_short": "{0}р.",
|
||||
"days": "{0} день | {0} днів",
|
||||
"days_short": "{0}д",
|
||||
"hours": "{0} година | {0} годин",
|
||||
"weeks": "{0} тиждень | {0} тижнів"
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"no_results": "Немає результатів",
|
||||
|
@ -850,7 +923,9 @@
|
|||
"disabled": "Не виділяти"
|
||||
},
|
||||
"bot": "Бот",
|
||||
"edit_profile": "Редагувати профіль"
|
||||
"edit_profile": "Редагувати профіль",
|
||||
"deactivated": "Деактивований",
|
||||
"follow_cancel": "Скасувати запит"
|
||||
},
|
||||
"status": {
|
||||
"copy_link": "Скопіювати посилання на допис",
|
||||
|
@ -877,7 +952,16 @@
|
|||
"thread_muted": "Нитка заглушена",
|
||||
"unmute_conversation": "Припинити глушити розмову",
|
||||
"external_source": "Зовнішнє джерело",
|
||||
"expand": "Розгорнути"
|
||||
"expand": "Розгорнути",
|
||||
"edit": "Редагувати допис",
|
||||
"edited_at": "(змінено: {time})",
|
||||
"thread_follow_with_icon": "{icon} {text}",
|
||||
"ancestor_follow_with_icon": "{icon} {text}",
|
||||
"show_all_conversation_with_icon": "{icon} {text}",
|
||||
"plus_more": "+{number} більше",
|
||||
"thread_show_full_with_icon": "{icon} {text}",
|
||||
"show_only_conversation_under_this": "Показати всі відповіді на цей допис",
|
||||
"status_history": "Історія змін"
|
||||
},
|
||||
"timeline": {
|
||||
"no_more_statuses": "Більше немає дописів",
|
||||
|
@ -913,6 +997,30 @@
|
|||
"state": "Статус:",
|
||||
"state_open": "відкритий",
|
||||
"state_closed": "закритий",
|
||||
"state_resolved": "вирішений"
|
||||
"state_resolved": "вирішений",
|
||||
"reported_statuses": "Дописи, на які подано скаргу:",
|
||||
"reporter": "Позивач:",
|
||||
"reported_user": "Відповідач:"
|
||||
},
|
||||
"announcements": {
|
||||
"delete_action": "Видалити",
|
||||
"page_header": "Анонси",
|
||||
"title": "Анонси",
|
||||
"mark_as_read_action": "Позначити як прочитане",
|
||||
"post_form_header": "Розмістити оголошення",
|
||||
"post_placeholder": "Введіть текст вашого оголошення тут...",
|
||||
"post_action": "Пост",
|
||||
"post_error": "Помилка: {error}",
|
||||
"close_error": "Закрити",
|
||||
"start_time_prompt": "Початок: ",
|
||||
"end_time_prompt": "Кінець: ",
|
||||
"all_day_prompt": "Це захід на цілий день",
|
||||
"published_time_display": "Опубліковано в {time}",
|
||||
"start_time_display": "Початок о {time}",
|
||||
"end_time_display": "Кінець о {time}",
|
||||
"edit_action": "Редагувати",
|
||||
"submit_edit_action": "Надіслати",
|
||||
"cancel_edit_action": "Скасувати",
|
||||
"inactive_message": "Це оголошення неактивне"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ const announcements = {
|
|||
}
|
||||
|
||||
const currentUser = store.rootState.users.currentUser
|
||||
const isAdmin = currentUser && currentUser.role === 'admin'
|
||||
const isAdmin = currentUser && currentUser.privileges.includes('announcements_manage_announcements')
|
||||
|
||||
const getAnnouncements = async () => {
|
||||
if (!isAdmin) {
|
||||
|
|
|
@ -181,15 +181,28 @@ const instance = {
|
|||
},
|
||||
groupedCustomEmojis (state) {
|
||||
const packsOf = emoji => {
|
||||
return emoji.tags
|
||||
const packs = emoji.tags
|
||||
.filter(k => k.startsWith('pack:'))
|
||||
.map(k => k.slice(5)) // remove 'pack:' prefix
|
||||
.map(k => {
|
||||
const packName = k.slice(5) // remove 'pack:' prefix
|
||||
return {
|
||||
id: `custom-${packName}`,
|
||||
text: packName
|
||||
}
|
||||
})
|
||||
|
||||
if (!packs.length) {
|
||||
return [{
|
||||
id: 'unpacked'
|
||||
}]
|
||||
} else {
|
||||
return packs
|
||||
}
|
||||
}
|
||||
|
||||
return state.customEmoji
|
||||
.reduce((res, emoji) => {
|
||||
packsOf(emoji).forEach(packName => {
|
||||
const packId = `custom-${packName}`
|
||||
packsOf(emoji).forEach(({ id: packId, text: packName }) => {
|
||||
if (!res[packId]) {
|
||||
res[packId] = ({
|
||||
id: packId,
|
||||
|
@ -290,9 +303,22 @@ const instance = {
|
|||
const lb = b.toLowerCase()
|
||||
return la > lb ? 1 : (la < lb ? -1 : 0)
|
||||
}
|
||||
const noPackLast = (a, b) => {
|
||||
const aNull = a === ''
|
||||
const bNull = b === ''
|
||||
if (aNull === bNull) {
|
||||
return 0
|
||||
} else if (aNull && !bNull) {
|
||||
return 1
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
const byPackThenByName = (a, b) => {
|
||||
const packOf = emoji => (emoji.tags.filter(k => k.startsWith('pack:'))[0] || '').slice(5)
|
||||
return caseInsensitiveStrCmp(packOf(a), packOf(b)) || caseInsensitiveStrCmp(a.displayText, b.displayText)
|
||||
const packOfA = packOf(a)
|
||||
const packOfB = packOf(b)
|
||||
return noPackLast(packOfA, packOfB) || caseInsensitiveStrCmp(packOfA, packOfB) || caseInsensitiveStrCmp(a.displayText, b.displayText)
|
||||
}
|
||||
|
||||
const emoji = Object.entries(values).map(([key, value]) => {
|
||||
|
|
|
@ -164,7 +164,7 @@ const updateNotificationSettings = ({ credentials, settings }) => {
|
|||
form.append(key, value)
|
||||
})
|
||||
|
||||
return fetch(NOTIFICATION_SETTINGS_URL, {
|
||||
return fetch(`${NOTIFICATION_SETTINGS_URL}?${new URLSearchParams(settings)}`, {
|
||||
headers: authHeaders(credentials),
|
||||
method: 'PUT',
|
||||
body: form
|
||||
|
|
Loading…
Reference in New Issue