Merge pull request '2022.10 stable' (#177) from develop into stable
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Reviewed-on: AkkomaGang/pleroma-fe#177
This commit is contained in:
floatingghost 2022-10-08 11:13:01 +00:00
commit c8c8d40827
48 changed files with 2973 additions and 1755 deletions

View file

@ -1,47 +0,0 @@
# This file is a template, and might need editing before it works on your project.
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/node/tags/
image: node:12
stages:
- lint
- build
- test
- deploy
lint:
stage: lint
script:
- yarn
- npm run lint
- npm run stylelint
test:
stage: test
variables:
APT_CACHE_DIR: apt-cache
script:
- mkdir -pv $APT_CACHE_DIR && apt-get -qq update
- apt install firefox-esr -y --no-install-recommends
- firefox --version
- yarn
- yarn unit
build:
stage: build
script:
- yarn
- npm run build
artifacts:
paths:
- dist/
docs-deploy:
stage: deploy
image: alpine:latest
only:
- develop@pleroma/pleroma-fe
before_script:
- apk add curl
script:
- curl -X POST -F"token=$DOCS_PIPELINE_TRIGGER" -F'ref=master' https://git.pleroma.social/api/v4/projects/673/trigger/pipeline

View file

@ -4,6 +4,33 @@ 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/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased ## Unreleased
### Added
- Implemented remote interaction with statuses
## 2022.09 - 2022-09-10
### Added
- Automatic post translations. Must be configured on the backend in order to work.
- Post editing, including a log of previous edits.
### Changed
- Top bar now has navigation shortcuts. Can be enabled or disabled by admins or users.
- Optional replacement of timeline drop-down with navigation buttons. Also configurable.
- Posts and posts with replies are now separated on user profiles.
- Custom emoji from remote instances on a post can now also be used.
## 2022.08 - 2022-08-12
### Added
- Ability to quote public and unlisted posts
- Bubble timeline
### Changed
- Emoji in emoji picker is separated by packs
### Removed
- Chats, they were half-baked. Just use PMs.
## 2022.07 - 2022-07-16
### Fixed ### Fixed
- AdminFE button no longer scrolls page to top when clicked - AdminFE button no longer scrolls page to top when clicked
- Pinned statuses no longer appear at bottom of user timeline (still appear as part of the timeline when fetched deep enough) - Pinned statuses no longer appear at bottom of user timeline (still appear as part of the timeline when fetched deep enough)
@ -16,6 +43,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Attachments are ALWAYS in same order as user uploaded, no more "videos first" - Attachments are ALWAYS in same order as user uploaded, no more "videos first"
- Attachment description is prefilled with backend-provided default when uploading - Attachment description is prefilled with backend-provided default when uploading
- Proper visual feedback that next image is loading when browsing - Proper visual feedback that next image is loading when browsing
- Misskey-Flavoured Markdown support
- Custom emoji reactions
### Changed ### Changed
- (You)s are optional (opt-in) now, bolding your nickname is also optional (opt-out) - (You)s are optional (opt-in) now, bolding your nickname is also optional (opt-out)

View file

@ -6,6 +6,7 @@ You have several timelines to browse trough
- **Bookmarks** all the posts you've bookmarked. You can bookmark a post by clicking the three dots on the bottom right of the post and choose Bookmark. - **Bookmarks** all the posts you've bookmarked. You can bookmark a post by clicking the three dots on the bottom right of the post and choose Bookmark.
- **Direct Messages** all posts with `direct` scope addressed to you or mentioning you. - **Direct Messages** all posts with `direct` scope addressed to you or mentioning you.
- **Public Timelines** all public posts made by users on the instance you're on - **Public Timelines** all public posts made by users on the instance you're on
- **Bubble Timeline** all public posts from instances recommended by your admin(s) in the instance settings. This won't appear if they haven't set anything up for it.
- **The Whole Known Network** also known as **TWKN** or **Federated Timeline** - all public posts known by your instance. Due to nature of the network your instance may not know *all* the posts on the network, so only posts known by your instance are shown there. - **The Whole Known Network** also known as **TWKN** or **Federated Timeline** - all public posts known by your instance. Due to nature of the network your instance may not know *all* the posts on the network, so only posts known by your instance are shown there.
Note that by default you will see all posts made by other users on your Home Timeline, this contrast behavior of Twitter and Mastodon, which shows you only non-reply posts and replies to people you follow. You can change said behavior in the [settings](settings.md#filtering). Note that by default you will see all posts made by other users on your Home Timeline, this contrast behavior of Twitter and Mastodon, which shows you only non-reply posts and replies to people you follow. You can change said behavior in the [settings](settings.md#filtering).

View file

@ -1,7 +1,7 @@
{ {
"name": "pleroma_fe", "name": "pleroma_fe",
"version": "1.0.0", "version": "3.2.0",
"description": "A Qvitter-style frontend for certain GS servers.", "description": "A frontend for Akkoma instances",
"author": "Roger Braun <roger@rogerbraun.net>", "author": "Roger Braun <roger@rogerbraun.net>",
"private": true, "private": true,
"scripts": { "scripts": {
@ -20,7 +20,7 @@
"@chenfengyuan/vue-qrcode": "2.0.0", "@chenfengyuan/vue-qrcode": "2.0.0",
"@fortawesome/fontawesome-svg-core": "1.3.0", "@fortawesome/fontawesome-svg-core": "1.3.0",
"@fortawesome/free-regular-svg-icons": "^6.1.2", "@fortawesome/free-regular-svg-icons": "^6.1.2",
"@fortawesome/free-solid-svg-icons": "5.15.4", "@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/vue-fontawesome": "3.0.1", "@fortawesome/vue-fontawesome": "3.0.1",
"@kazvmoe-infra/pinch-zoom-element": "1.2.0", "@kazvmoe-infra/pinch-zoom-element": "1.2.0",
"@vuelidate/core": "2.0.0-alpha.42", "@vuelidate/core": "2.0.0-alpha.42",
@ -41,7 +41,7 @@
"qrcode": "1", "qrcode": "1",
"ruffle-mirror": "2021.12.31", "ruffle-mirror": "2021.12.31",
"vue": "^3.2.31", "vue": "^3.2.31",
"vue-i18n": "^9.2.0-beta.39", "vue-i18n": "^9.2.2",
"vue-router": "4.0.14", "vue-router": "4.0.14",
"vue-template-compiler": "2.6.11", "vue-template-compiler": "2.6.11",
"vuex": "4.0.2" "vuex": "4.0.2"

View file

@ -61,7 +61,6 @@
<EditStatusModal v-if="editingAvailable" /> <EditStatusModal v-if="editingAvailable" />
<StatusHistoryModal v-if="editingAvailable" /> <StatusHistoryModal v-if="editingAvailable" />
<SettingsModal /> <SettingsModal />
<UpdateNotification />
<GlobalNoticeList /> <GlobalNoticeList />
</div> </div>
</template> </template>

View file

@ -398,7 +398,6 @@ const afterStoreSetup = async ({ store, i18n }) => {
store.dispatch('startFetchingAnnouncements') store.dispatch('startFetchingAnnouncements')
getTOS({ store }) getTOS({ store })
getStickers({ store }) getStickers({ store })
store.dispatch('getSupportedTranslationlanguages')
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),

View file

@ -20,6 +20,9 @@ const About = {
return this.$store.state.instance.showInstanceSpecificPanel && return this.$store.state.instance.showInstanceSpecificPanel &&
!this.$store.getters.mergedConfig.hideISP && !this.$store.getters.mergedConfig.hideISP &&
this.$store.state.instance.instanceSpecificPanelContent this.$store.state.instance.instanceSpecificPanelContent
},
showLocalBubblePanel () {
return this.$store.state.instance.localBubbleInstances.length > 0
} }
} }
} }

View file

@ -3,7 +3,7 @@
<instance-specific-panel v-if="showInstanceSpecificPanel" /> <instance-specific-panel v-if="showInstanceSpecificPanel" />
<staff-panel /> <staff-panel />
<terms-of-service-panel /> <terms-of-service-panel />
<LocalBubblePanel /> <LocalBubblePanel v-if="showLocalBubblePanel" />
<MRFTransparencyPanel /> <MRFTransparencyPanel />
<features-panel v-if="showFeaturesPanel" /> <features-panel v-if="showFeaturesPanel" />
</div> </div>

View file

@ -52,6 +52,9 @@ const AccountActions = {
unblockUser () { unblockUser () {
this.$store.dispatch('unblockUser', this.user.id) this.$store.dispatch('unblockUser', this.user.id)
}, },
removeUserFromFollowers () {
this.$store.dispatch('removeUserFromFollowers', this.user.id)
},
reportUser () { reportUser () {
this.$store.dispatch('openUserReportingModal', { userId: this.user.id }) this.$store.dispatch('openUserReportingModal', { userId: this.user.id })
} }

View file

@ -28,6 +28,13 @@
class="dropdown-divider" class="dropdown-divider"
/> />
</template> </template>
<button
v-if="relationship.followed_by"
class="btn button-default btn-block dropdown-item"
@click="removeUserFromFollowers"
>
{{ $t('user_card.remove_follower') }}
</button>
<button <button
v-if="relationship.blocking" v-if="relationship.blocking"
class="btn button-default btn-block dropdown-item" class="btn button-default btn-block dropdown-item"

View file

@ -8,7 +8,8 @@ import {
faThumbtack, faThumbtack,
faShareAlt, faShareAlt,
faExternalLinkAlt, faExternalLinkAlt,
faHistory faHistory,
faFilePen
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { import {
faBookmark as faBookmarkReg, faBookmark as faBookmarkReg,
@ -24,7 +25,8 @@ library.add(
faShareAlt, faShareAlt,
faExternalLinkAlt, faExternalLinkAlt,
faFlag, faFlag,
faHistory faHistory,
faFilePen
) )
const ExtraButtons = { const ExtraButtons = {
@ -36,7 +38,8 @@ const ExtraButtons = {
data () { data () {
return { return {
expanded: false, expanded: false,
showingDeleteDialog: false showingDeleteDialog: false,
showingRedraftDialog: false
} }
}, },
methods: { methods: {
@ -122,6 +125,34 @@ const ExtraButtons = {
const stripFieldsList = ['attachments', 'created_at', 'emojis', 'text', 'raw_html', 'nsfw', 'poll', 'summary', 'summary_raw_html'] const stripFieldsList = ['attachments', 'created_at', 'emojis', 'text', 'raw_html', 'nsfw', 'poll', 'summary', 'summary_raw_html']
stripFieldsList.forEach(p => delete originalStatus[p]) stripFieldsList.forEach(p => delete originalStatus[p])
this.$store.dispatch('openStatusHistoryModal', originalStatus) this.$store.dispatch('openStatusHistoryModal', originalStatus)
},
redraftStatus () {
if (this.shouldConfirmDelete) {
this.showRedraftStatusConfirmDialog()
} else {
this.doRedraftStatus()
}
},
doRedraftStatus () {
this.$store.dispatch('fetchStatusSource', { id: this.status.id })
.then(data => this.$store.dispatch('openPostStatusModal', {
isRedraft: true,
statusId: this.status.id,
subject: data.spoiler_text,
statusText: data.text,
statusIsSensitive: this.status.nsfw,
statusPoll: this.status.poll,
statusFiles: [...this.status.attachments],
statusScope: this.status.visibility,
statusContentType: data.content_type
}))
this.doDeleteStatus()
},
showRedraftStatusConfirmDialog () {
this.showingRedraftDialog = true
},
hideRedraftStatusConfirmDialog () {
this.showingRedraftDialog = false
} }
}, },
computed: { computed: {

View file

@ -95,6 +95,17 @@
icon="history" icon="history"
/><span>{{ $t("status.edit_history") }}</span> /><span>{{ $t("status.edit_history") }}</span>
</button> </button>
<button
v-if="ownStatus"
class="button-default dropdown-item dropdown-item-icon"
@click.prevent="redraftStatus"
@click="close"
>
<FAIcon
fixed-width
icon="file-pen"
/><span>{{ $t("status.redraft") }}</span>
</button>
<button <button
v-if="canDelete" v-if="canDelete"
class="button-default dropdown-item dropdown-item-icon" class="button-default dropdown-item dropdown-item-icon"
@ -179,6 +190,16 @@
> >
{{ $t('status.delete_confirm') }} {{ $t('status.delete_confirm') }}
</ConfirmModal> </ConfirmModal>
<ConfirmModal
v-if="showingRedraftDialog"
:title="$t('status.redraft_confirm_title')"
:cancel-text="$t('status.redraft_confirm_cancel_button')"
:confirm-text="$t('status.redraft_confirm_accept_button')"
@cancelled="hideRedraftStatusConfirmDialog"
@accepted="doRedraftStatus"
>
{{ $t('status.redraft_confirm') }}
</ConfirmModal>
</teleport> </teleport>
</template> </template>
</Popover> </Popover>

View file

@ -31,7 +31,10 @@ const FavoriteButton = {
} }
}, },
computed: { computed: {
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig']),
remoteInteractionLink () {
return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
}
} }
} }

View file

@ -13,13 +13,19 @@
:spin="animated" :spin="animated"
/> />
</button> </button>
<span v-else> <a
v-else
class="button-unstyled interactive"
target="_blank"
role="button"
:href="remoteInteractionLink"
>
<FAIcon <FAIcon
class="fa-scale-110 fa-old-padding" class="fa-scale-110 fa-old-padding"
:title="$t('tool_tip.favorite')" :title="$t('tool_tip.favorite')"
:icon="['far', 'star']" :icon="['far', 'star']"
/> />
</span> </a>
<span <span
v-if="!mergedConfig.hidePostStats && status.fave_num > 0" v-if="!mergedConfig.hidePostStats && status.fave_num > 0"
class="action-counter" class="action-counter"

View file

@ -1,6 +1,7 @@
import BasicUserCard from '../basic_user_card/basic_user_card.vue' import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import RemoteFollow from '../remote_follow/remote_follow.vue' import RemoteFollow from '../remote_follow/remote_follow.vue'
import FollowButton from '../follow_button/follow_button.vue' import FollowButton from '../follow_button/follow_button.vue'
import RemoveFollowerButton from '../remove_follower_button/remove_follower_button.vue'
const FollowCard = { const FollowCard = {
props: [ props: [
@ -10,7 +11,8 @@ const FollowCard = {
components: { components: {
BasicUserCard, BasicUserCard,
RemoteFollow, RemoteFollow,
FollowButton FollowButton,
RemoveFollowerButton
}, },
computed: { computed: {
isMe () { isMe () {

View file

@ -22,6 +22,11 @@
class="follow-card-follow-button" class="follow-card-follow-button"
:user="user" :user="user"
/> />
<RemoveFollowerButton
v-if="noFollowsYou && relationship.followed_by"
:relationship="relationship"
class="follow-card-button"
/>
</template> </template>
</div> </div>
</basic-user-card> </basic-user-card>
@ -40,6 +45,12 @@
line-height: 1.5em; line-height: 1.5em;
} }
&-button {
margin-top: 0.5em;
padding: 0 1.5em;
margin-left: 1em;
}
&-follow-button { &-follow-button {
margin-top: 0.5em; margin-top: 0.5em;
margin-left: auto; margin-left: auto;

View file

@ -86,7 +86,8 @@ const PostStatusForm = {
'fileLimit', 'fileLimit',
'submitOnEnter', 'submitOnEnter',
'emojiPickerPlacement', 'emojiPickerPlacement',
'optimisticPosting' 'optimisticPosting',
'isRedraft'
], ],
emits: [ emits: [
'posted', 'posted',
@ -141,7 +142,7 @@ const PostStatusForm = {
contentType contentType
} }
if (this.statusId) { if (this.statusId || this.isRedraft) {
const statusContentType = this.statusContentType || contentType const statusContentType = this.statusContentType || contentType
statusParams = { statusParams = {
spoilerText: this.subject || '', spoilerText: this.subject || '',
@ -259,7 +260,7 @@ const PostStatusForm = {
return this.newStatus.files.length >= this.fileLimit return this.newStatus.files.length >= this.fileLimit
}, },
isEdit () { isEdit () {
return typeof this.statusId !== 'undefined' && this.statusId.trim() !== '' return typeof this.statusId !== 'undefined' && this.statusId.trim() !== '' && !this.isRedraft
}, },
...mapGetters(['mergedConfig']), ...mapGetters(['mergedConfig']),
...mapState({ ...mapState({

View file

@ -28,7 +28,8 @@ const PostStatusModal = {
}, },
watch: { watch: {
params (newVal, oldVal) { params (newVal, oldVal) {
if (get(newVal, 'repliedUser.id') !== get(oldVal, 'repliedUser.id')) { if (get(newVal, 'repliedUser.id') !== get(oldVal, 'repliedUser.id') ||
get(newVal, 'statusId') !== get(oldVal, 'statusId')) {
this.resettingForm = true this.resettingForm = true
this.$nextTick(() => { this.$nextTick(() => {
this.resettingForm = false this.resettingForm = false

View file

@ -0,0 +1,25 @@
export default {
props: ['relationship'],
data () {
return {
inProgress: false
}
},
computed: {
label () {
if (this.inProgress) {
return this.$t('user_card.follow_progress')
} else {
return this.$t('user_card.remove_follower')
}
}
},
methods: {
onClick () {
this.inProgress = true
this.$store.dispatch('removeUserFromFollowers', this.relationship.id).then(() => {
this.inProgress = false
})
}
}
}

View file

@ -0,0 +1,13 @@
<template>
<button
class="btn button-default follow-button"
:class="{ toggled: inProgress }"
:disabled="inProgress"
:title="$t('user_card.remove_follower')"
@click="onClick"
>
{{ label }}
</button>
</template>
<script src="./remove_follower_button.js"></script>

View file

@ -9,6 +9,9 @@ const ReplyButton = {
computed: { computed: {
loggedIn () { loggedIn () {
return !!this.$store.state.users.currentUser return !!this.$store.state.users.currentUser
},
remoteInteractionLink () {
return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
} }
} }
} }

View file

@ -12,13 +12,19 @@
icon="reply" icon="reply"
/> />
</button> </button>
<span v-else> <a
v-else
class="button-unstyled interactive"
target="_blank"
role="button"
:href="remoteInteractionLink"
>
<FAIcon <FAIcon
icon="reply" icon="reply"
class="fa-scale-110 fa-old-padding" class="fa-scale-110 fa-old-padding"
:title="$t('tool_tip.reply')" :title="$t('tool_tip.reply')"
/> />
</span> </a>
<span <span
v-if="status.replies_count > 0" v-if="status.replies_count > 0"
class="action-counter" class="action-counter"

View file

@ -51,6 +51,9 @@ const RetweetButton = {
}, },
shouldConfirmRepeat () { shouldConfirmRepeat () {
return this.mergedConfig.modalOnRepeat return this.mergedConfig.modalOnRepeat
},
remoteInteractionLink () {
return this.$store.getters.remoteInteractionLink({ statusId: this.status.id })
} }
} }
} }

View file

@ -20,13 +20,19 @@
:title="$t('timeline.no_retweet_hint')" :title="$t('timeline.no_retweet_hint')"
/> />
</span> </span>
<span v-else> <a
v-else
class="button-unstyled interactive"
target="_blank"
role="button"
:href="remoteInteractionLink"
>
<FAIcon <FAIcon
class="fa-scale-110 fa-old-padding" class="fa-scale-110 fa-old-padding"
icon="retweet" icon="retweet"
:title="$t('tool_tip.repeat')" :title="$t('tool_tip.repeat')"
/> />
</span> </a>
<span <span
v-if="!mergedConfig.hidePostStats && status.repeat_num > 0" v-if="!mergedConfig.hidePostStats && status.repeat_num > 0"
class="no-event" class="no-event"

View file

@ -12,7 +12,8 @@ export default {
'path', 'path',
'disabled', 'disabled',
'options', 'options',
'expert' 'expert',
'hideDefaultLabel'
], ],
computed: { computed: {
pathDefault () { pathDefault () {

View file

@ -16,7 +16,11 @@
:value="option.value" :value="option.value"
> >
{{ option.label }} {{ option.label }}
{{ option.value === defaultState ? $t('settings.instance_default_simple') : '' }} <template
v-if="hideDefaultLabel !== true"
>
{{ option.value === defaultState ? $t('settings.instance_default_simple') : '' }}
</template>
</option> </option>
</Select> </Select>
<ModifiedIndicator :changed="isChanged" /> <ModifiedIndicator :changed="isChanged" />

View file

@ -19,7 +19,7 @@ const SharedComputedObject = () => ({
.map(key => [key, { .map(key => [key, {
get () { return this.$store.getters.mergedConfig[key] }, get () { return this.$store.getters.mergedConfig[key] },
set (value) { set (value) {
this.$store.dispatch('setOption', { name: key, value }) this.$store.dispatch('setOption', { name: key, value, manual: true })
} }
}]) }])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
@ -27,7 +27,7 @@ const SharedComputedObject = () => ({
.map(key => ['serverSide_' + key, { .map(key => ['serverSide_' + key, {
get () { return this.$store.state.serverSideConfig[key] }, get () { return this.$store.state.serverSideConfig[key] },
set (value) { set (value) {
this.$store.dispatch('setServerSideOption', { name: key, value }) this.$store.dispatch('setServerSideOption', { name: key, value, manual: true })
} }
}]) }])
.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}), .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),

View file

@ -8,11 +8,12 @@ import SharedComputedObject from '../helpers/shared_computed_object.js'
import ServerSideIndicator from '../helpers/server_side_indicator.vue' import ServerSideIndicator from '../helpers/server_side_indicator.vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faGlobe faGlobe, faSync
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
library.add( library.add(
faGlobe faGlobe,
faSync
) )
const GeneralTab = { const GeneralTab = {
@ -48,6 +49,8 @@ const GeneralTab = {
value: tab, value: tab,
label: this.$t(`user_card.${tab}`) label: this.$t(`user_card.${tab}`)
})), })),
profilesExpanded: false,
newProfileName: '',
loopSilentAvailable: loopSilentAvailable:
// Firefox // Firefox
Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') || Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
@ -88,8 +91,22 @@ const GeneralTab = {
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
} }
}, },
settingsProfiles () {
return (this.$store.state.instance.settingsProfiles || [])
},
settingsProfile: {
get: function () { return this.$store.getters.mergedConfig.profile },
set: function (val) {
this.$store.dispatch('setOption', { name: 'profile', value: val })
this.$store.dispatch('getSettingsProfile')
}
},
settingsVersion () {
return this.$store.getters.mergedConfig.profileVersion
},
translationLanguages () { translationLanguages () {
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.target || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name })) const langs = this.$store.state.instance.translationLanguages || []
return (langs || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
}, },
translationLanguage: { translationLanguage: {
get: function () { return this.$store.getters.mergedConfig.translationLanguage }, get: function () { return this.$store.getters.mergedConfig.translationLanguage },
@ -105,6 +122,30 @@ const GeneralTab = {
}, },
setTranslationLanguage (value) { setTranslationLanguage (value) {
this.$store.dispatch('setOption', { name: 'translationLanguage', value }) this.$store.dispatch('setOption', { name: 'translationLanguage', value })
},
toggleExpandedSettings () {
this.profilesExpanded = !this.profilesExpanded
},
loadSettingsProfile (name) {
this.$store.commit('setOption', { name: 'profile', value: name })
this.$store.dispatch('getSettingsProfile', true)
},
createSettingsProfile () {
this.$store.dispatch('setOption', { name: 'profile', value: this.newProfileName })
this.$store.dispatch('setOption', { name: 'profileVersion', value: 1 })
this.$store.dispatch('syncSettings')
this.newProfileName = ''
},
forceSync () {
this.$store.dispatch('getSettingsProfile')
},
refreshProfiles () {
this.$store.dispatch('listSettingsProfiles')
},
deleteSettingsProfile (name) {
if (confirm(this.$t('settings.settings_profile_delete_confirm'))) {
this.$store.dispatch('deleteSettingsProfile', name)
}
} }
} }
} }

View file

@ -1,7 +1,6 @@
<template> <template>
<div :label="$t('settings.general')"> <div :label="$t('settings.general')">
<div class="setting-item"> <div class="setting-item">
<h2>{{ $t('settings.interface') }}</h2>
<ul class="setting-list"> <ul class="setting-list">
<li> <li>
<interface-language-switcher <interface-language-switcher
@ -10,6 +9,94 @@
:set-language="val => language = val" :set-language="val => language = val"
/> />
</li> </li>
<li
v-if="user && (settingsProfiles.length > 0)"
>
<h2>{{ $t('settings.settings_profile') }}</h2>
<p>
{{ $t('settings.settings_profile_currently', { name: settingsProfile, version: settingsVersion }) }}
<button
class="btn button-default"
@click="forceSync()"
>
{{ $t('settings.settings_profile_force_sync') }}
</button>
</p>
<div
@click="toggleExpandedSettings"
>
<template
v-if="profilesExpanded"
>
<button class="btn button-default">
{{ $t('settings.settings_profiles_unshow') }}
</button>
</template>
<template
v-else
>
<button class="btn button-default">
{{ $t('settings.settings_profiles_show') }}
</button>
</template>
</div>
<br>
<template
v-if="profilesExpanded"
>
<div
v-for="profile in settingsProfiles"
:key="profile.id"
class="settings-profile"
>
<h4>{{ profile.name }} ({{ profile.version }})</h4>
<template
v-if="settingsProfile === profile.name"
>
{{ $t('settings.settings_profile_in_use') }}
</template>
<template
v-else
>
<button
class="btn button-default"
@click="loadSettingsProfile(profile.name)"
>
{{ $t('settings.settings_profile_use') }}
</button>
<button
class="btn button-default"
@click="deleteSettingsProfile(profile.name)"
>
{{ $t('settings.settings_profile_delete') }}
</button>
</template>
</div>
<button class="btn button-default" @click="refreshProfiles()">
{{ $t('settings.settings_profiles_refresh') }}
<FAIcon icon="sync" @click="refreshProfiles()" />
</button>
<h3>{{ $t('settings.settings_profile_creation') }}</h3>
<label for="settings-profile-new-name">
{{ $t('settings.settings_profile_creation_new_name_label') }}
</label>
<input v-model="newProfileName" id="settings-profile-new-name">
<button
class="btn button-default"
@click="createSettingsProfile"
>
{{ $t('settings.settings_profile_creation_submit') }}
</button>
</template>
</li>
</ul>
</div>
<div class="setting-item">
<h2>{{ $t('settings.interface') }}</h2>
<ul class="setting-list">
<li v-if="instanceSpecificPanelPresent"> <li v-if="instanceSpecificPanelPresent">
<BooleanSetting path="hideISP"> <BooleanSetting path="hideISP">
{{ $t('settings.hide_isp') }} {{ $t('settings.hide_isp') }}
@ -463,7 +550,6 @@
</BooleanSetting> </BooleanSetting>
</li> </li>
<li> <li>
<!-- <BooleanSetting path="serverSide_defaultNSFW"> -->
<BooleanSetting path="sensitiveByDefault"> <BooleanSetting path="sensitiveByDefault">
{{ $t('settings.sensitive_by_default') }} {{ $t('settings.sensitive_by_default') }}
</BooleanSetting> </BooleanSetting>
@ -546,3 +632,13 @@
</template> </template>
<script src="./general_tab.js"></script> <script src="./general_tab.js"></script>
<style lang="scss">
.settings-profile {
margin-bottom: 1em;
}
#settings-profile-new-name {
margin-left: 1em;
margin-right: 1em;
}
</style>

View file

@ -83,7 +83,7 @@ const StatusContent = {
return this.status.attachments.map(file => fileType.fileType(file.mimetype)) return this.status.attachments.map(file => fileType.fileType(file.mimetype))
}, },
translationLanguages () { translationLanguages () {
return (this.$store.getters.mergedConfig.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name })) return (this.$store.state.instance.supportedTranslationLanguages.source || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name }))
}, },
...mapGetters(['mergedConfig']) ...mapGetters(['mergedConfig'])
}, },

View file

@ -60,7 +60,7 @@
v-if="status.translation" v-if="status.translation"
class="translation" class="translation"
> >
<h4>{{ $t('status.translated_from', { language: status.translation.detected_language }) }}</h4> <h4>{{ $t(`languages.translated_from.${status.translation.detected_language.toLowerCase()}`) }}</h4>
<RichContent <RichContent
:class="{ '-single-line': singleLine }" :class="{ '-single-line': singleLine }"
class="text media-body" class="text media-body"
@ -85,7 +85,7 @@
:key="language.key" :key="language.key"
:value="language.value" :value="language.value"
> >
{{ language.label }} {{ $t(`languages.${language.value.toLowerCase()}`) }}
</option> </option>
</Select> </Select>
{{ ' ' }} {{ ' ' }}

View file

@ -11,12 +11,13 @@ const StillImage = {
], ],
data () { data () {
return { return {
stopGifs: this.$store.getters.mergedConfig.stopGifs stopGifs: this.$store.getters.mergedConfig.stopGifs,
isAnimated: false
} }
}, },
computed: { computed: {
animated () { animated () {
return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif')) return this.stopGifs && this.isAnimated
}, },
style () { style () {
const appendPx = (str) => /\d$/.test(str) ? str + 'px' : str const appendPx = (str) => /\d$/.test(str) ? str + 'px' : str
@ -31,17 +32,89 @@ const StillImage = {
const image = this.$refs.src const image = this.$refs.src
if (!image) return if (!image) return
this.imageLoadHandler && this.imageLoadHandler(image) this.imageLoadHandler && this.imageLoadHandler(image)
this.detectAnimation(image)
this.drawThumbnail()
},
onError () {
this.imageLoadError && this.imageLoadError()
},
detectAnimation (image) {
if (this.mimetype === 'image/gif' || this.src.endsWith('.gif')) {
this.isAnimated = true
return
}
// harmless CORS errors without-- clean console with
if (!this.$store.state.instance.mediaProxyAvailable) return
// Animated JPEGs?
if (!(this.src.endsWith('.webp') || this.src.endsWith('.png'))) return
// Browser Cache should ensure image doesn't get loaded twice if cache exists
fetch(image.src, {
referrerPolicy: 'same-origin'
})
.then(data => {
// We don't need to read the whole file so only call it once
data.body.getReader().read()
.then(reader => {
if (this.src.endsWith('.webp') && this.isAnimatedWEBP(reader.value)) {
this.isAnimated = true
return
}
if (this.src.endsWith('.png') && this.isAnimatedPNG(reader.value)) {
this.isAnimated = true
}
})
})
.catch(() => {
// this.imageLoadError && this.imageLoadError()
})
},
isAnimatedWEBP (data) {
/**
* WEBP HEADER CHUNK
* === START HEADER ===
* 82 73 70 70 ("RIFF")
* xx xx xx xx (SIZE)
* 87 69 66 80 ("WEBP")
* === END OF HEADER ===
* 86 80 56 88 ("VP8X") Extended VP8X
* xx xx xx xx (VP8X)
* [++] RSVILEX(A)R (1 byte)
* A Animated bit
*/
// Relevant bytes
const segment = data.slice(4 * 3, (4 * 5) + 1)
// Check for VP8X string
if (segment.join('').includes(['86805688'])) {
// Check for Animation bit
return !!((segment[8] >> 1) & 1)
}
// No VP8X = Not Animated (X is for Extended)
return false
},
isAnimatedPNG (data) {
// Find acTL before IDAT in PNG; if found it is animated
const segment = []
for (let i = 0; i < data.length; i++) {
segment.push(String.fromCharCode(data[i]))
}
const str = segment.join('')
const idatPos = str.indexOf('IDAT')
return (str.substring(0, idatPos > 0 ? idatPos : 0).indexOf('acTL') > 0)
},
drawThumbnail () {
const canvas = this.$refs.canvas const canvas = this.$refs.canvas
if (!canvas) return if (!this.$refs.canvas) return
const image = this.$refs.src
const width = image.naturalWidth const width = image.naturalWidth
const height = image.naturalHeight const height = image.naturalHeight
canvas.width = width canvas.width = width
canvas.height = height canvas.height = height
canvas.getContext('2d').drawImage(image, 0, 0, width, height) canvas.getContext('2d').drawImage(image, 0, 0, width, height)
},
onError () {
this.imageLoadError && this.imageLoadError()
} }
},
updated () {
// On computed animated change
this.drawThumbnail()
} }
} }

View file

@ -135,7 +135,6 @@
a { a {
display: block; display: block;
padding: 0.6em 0.65em; padding: 0.6em 0.65em;
padding-bottom: 0;
&:hover { &:hover {
background-color: $fallback--lightBg; background-color: $fallback--lightBg;

View file

@ -23,7 +23,8 @@ const TimelineMenuContent = {
...mapState({ ...mapState({
currentUser: state => state.users.currentUser, currentUser: state => state.users.currentUser,
privateMode: state => state.instance.private, privateMode: state => state.instance.private,
federating: state => state.instance.federating federating: state => state.instance.federating,
showBubbleTimeline: state => (state.instance.localBubbleInstances.length > 0)
}) })
} }
} }

View file

@ -16,7 +16,7 @@
>{{ $t("nav.home_timeline") }}</span> >{{ $t("nav.home_timeline") }}</span>
</router-link> </router-link>
</li> </li>
<li v-if="currentUser"> <li v-if="currentUser && showBubbleTimeline">
<router-link <router-link
class="menu-item" class="menu-item"
:to="{ name: 'bubble-timeline' }" :to="{ name: 'bubble-timeline' }"

View file

@ -5,7 +5,7 @@
"keyword": { "keyword": {
"ftl_removal": "Von der Zeitleiste \"Das gesamte bekannte Netzwerk\" entfernen", "ftl_removal": "Von der Zeitleiste \"Das gesamte bekannte Netzwerk\" entfernen",
"is_replaced_by": "→", "is_replaced_by": "→",
"keyword_policies": "Keyword Richtlinien", "keyword_policies": "Richtlinien für Schlüsselwörter",
"reject": "Ablehnen", "reject": "Ablehnen",
"replace": "Ersetzen" "replace": "Ersetzen"
}, },
@ -16,12 +16,15 @@
"accept_desc": "Diese Instanz akzeptiert nur Nachrichten von den folgenden Instanzen:", "accept_desc": "Diese Instanz akzeptiert nur Nachrichten von den folgenden Instanzen:",
"ftl_removal": "Von der Zeitleiste \"Das bekannte Netzwerk\" entfernen", "ftl_removal": "Von der Zeitleiste \"Das bekannte Netzwerk\" entfernen",
"ftl_removal_desc": "Dieser Instanz entfernt folgende Instanzen von der \"Das bekannte Netzwerk\" Zeitleiste:", "ftl_removal_desc": "Dieser Instanz entfernt folgende Instanzen von der \"Das bekannte Netzwerk\" Zeitleiste:",
"instance": "Instanz",
"media_nsfw": "Erzwingen Medien als heikel zu makieren", "media_nsfw": "Erzwingen Medien als heikel zu makieren",
"media_nsfw_desc": "Diese Instanz makiert die Medien in Beiträgen der folgenden Instanzen als heikel:", "media_nsfw_desc": "Diese Instanz makiert die Medien in Beiträgen der folgenden Instanzen als heikel:",
"media_removal": "Medienentfernung", "media_removal": "Medienentfernung",
"media_removal_desc": "Diese Instanz entfernt Medien von den Beiträgen der folgenden Instanzen:", "media_removal_desc": "Diese Instanz entfernt Medien von den Beiträgen der folgenden Instanzen:",
"not_applicable": "entfällt",
"quarantine": "Quarantäne", "quarantine": "Quarantäne",
"quarantine_desc": "Diese Instanz sendet nur öffentliche Beiträge zu den folgenden Instanzen:", "quarantine_desc": "Diese Instanz sendet keine Beiträge zu den folgenden Instanzen:",
"reason": "Grund",
"reject": "Ablehnen", "reject": "Ablehnen",
"reject_desc": "Diese Instanz akzeptiert keine Nachrichten der folgenden Instanzen:", "reject_desc": "Diese Instanz akzeptiert keine Nachrichten der folgenden Instanzen:",
"simple_policies": "Instanzspezifische Richtlinien" "simple_policies": "Instanzspezifische Richtlinien"
@ -29,6 +32,27 @@
}, },
"staff": "Mitarbeiter" "staff": "Mitarbeiter"
}, },
"announcements": {
"all_day_prompt": "Dies ist ein Ganztagsereignis",
"cancel_edit_action": "Abbrechen",
"close_error": "Schließen",
"delete_action": "Löschen",
"edit_action": "Bearbeiten",
"end_time_display": "Endet um {time}",
"end_time_prompt": "Ende: ",
"inactive_message": "Diese Ankündigung ist inaktiv",
"mark_as_read_action": "Als gelesen markieren",
"page_header": "Ankündigungen",
"post_action": "Veröffentlichen",
"post_error": "Fehler: {error}",
"post_form_header": "Ankündigung veröffentlichen",
"post_placeholder": "Inhalt der Ankündigung",
"published_time_display": "Veröffentlicht um {time}",
"start_time_display": "Startet um {time}",
"start_time_prompt": "Start: ",
"submit_edit_action": "Absenden",
"title": "Ankündigung"
},
"chats": { "chats": {
"chats": "Chats", "chats": "Chats",
"delete": "Löschen", "delete": "Löschen",
@ -109,6 +133,13 @@
"admin": "Admin", "admin": "Admin",
"moderator": "Moderator" "moderator": "Moderator"
}, },
"scope_in_timeline": {
"direct": "Direkt",
"local": "Lokal - nur deine eigene Instanz kann diesen Beitrag sehen",
"private": "Nur an Folgende",
"public": "Öffentlich",
"unlisted": "Nicht gelistet"
},
"show_less": "Zeige weniger", "show_less": "Zeige weniger",
"show_more": "Zeige mehr", "show_more": "Zeige mehr",
"submit": "Absenden", "submit": "Absenden",
@ -131,6 +162,84 @@
"load_older": "Lade ältere Interaktionen", "load_older": "Lade ältere Interaktionen",
"moves": "Benutzer migriert zu" "moves": "Benutzer migriert zu"
}, },
"languages": {
"ar": "Arabisch",
"az": "Aserbaidschanisch",
"bg": "Bulgarisch",
"cs": "Tschechisch",
"da": "Dänisch",
"de": "Deutsch",
"el": "Griechisch",
"en": "Englisch",
"eo": "Esperanto",
"es": "Spanisch",
"fa": "Persisch",
"fi": "Finnisch",
"fr": "Französisch",
"ga": "Irisch",
"he": "Hebräisch",
"hi": "Hindi",
"hu": "Ungarisch",
"id": "Indonesisch",
"it": "Italienisch",
"ja": "Japanisch",
"ko": "Koreanisch",
"lt": "Litauisch",
"lv": "Lettisch",
"nl": "Niederländisch",
"pl": "Polnisch",
"pt": "Portugiesisch",
"ru": "Russisch",
"sk": "Slowakisch",
"sv": "Schwedisch",
"tr": "Türkisch",
"translated_from": {
"ar": "Übersetzt aus dem Arabischen",
"az": "Übersetzt aus dem Aserbaidschanischen",
"bg": "Übersetzt aus dem Bulgarischen",
"cs": "Übersetzt aus dem Tschechischen",
"da": "Übersetzt aus dem Dänischen",
"de": "Übersetzt aus dem Deutschen",
"el": "Übersetzt aus dem Griechischen",
"en": "Übersetzt aus dem Englischen",
"eo": "Übersetzt von @:languages.eo",
"es": "Übersetzt aus dem Spanischen",
"fa": "Übersetzt aus dem Persischen",
"fi": "Übersetzt aus dem Finnischen",
"fr": "Übersetzt aus dem Französischen",
"ga": "Übersetzt aus dem Irischen",
"he": "Übersetzt aus dem Hebräischen",
"hi": "Übersetzt von @:languages.hi",
"hu": "Übersetzt aus dem Ungarischen",
"id": "Übersetzt aus dem Indonesischen",
"it": "Übersetzt aus dem Italienischen",
"ja": "Übersetzt aus dem Japanischen",
"ko": "Übersetzt aus dem Koreanischen",
"lt": "Übersetzt aus dem Litauischen",
"lv": "Übersetzt aus dem Lettischen",
"nl": "Übersetzt aus dem Niederländischen",
"pl": "Übersetzt aus dem Polnischen",
"pt": "Übersetzt aus dem Portugiesischen",
"ru": "Übersetzt aus dem Russischen",
"sk": "Übersetzt aus dem Slowakischen",
"sv": "Übersetzt aus dem Schwedischen",
"tr": "Übersetzt aus dem Türkischen",
"uk": "Übersetzt aus dem Ukrainischen",
"zh": "Übersetzt aus dem Chinesischen"
},
"uk": "Ukrainisch",
"zh": "Chinesisch"
},
"lists": {
"create": "Erstellen",
"delete": "Liste löschen",
"following_only": "Auf Folgende begrenzen",
"lists": "Listen",
"new": "Neue Liste",
"save": "Änderungen speichern",
"search": "Benutzer suchen",
"title": "Listen-Titel"
},
"login": { "login": {
"authentication_code": "Authentifizierungscode", "authentication_code": "Authentifizierungscode",
"description": "Mit OAuth anmelden", "description": "Mit OAuth anmelden",
@ -144,38 +253,45 @@
"login": "Anmelden", "login": "Anmelden",
"logout": "Abmelden", "logout": "Abmelden",
"password": "Passwort", "password": "Passwort",
"placeholder": "z.B. lain", "placeholder": "meinbenutzername",
"recovery_code": "Wiederherstellungscode", "recovery_code": "Wiederherstellungscode",
"register": "Registrieren", "register": "Registrieren",
"username": "Benutzername" "username": "Benutzername"
}, },
"media_modal": { "media_modal": {
"counter": "{current} / {total}",
"hide": "Medienansicht schließen",
"next": "Weiter", "next": "Weiter",
"previous": "Zurück" "previous": "Zurück"
}, },
"nav": { "nav": {
"about": "Über", "about": "Über",
"administration": "Administration", "administration": "Administration",
"announcements": "Ankündigungen",
"back": "Zurück", "back": "Zurück",
"bookmarks": "Lesezeichen", "bookmarks": "Lesezeichen",
"chats": "Chats", "chats": "Chats",
"dms": "Direktnachrichten", "dms": "Direktnachrichten",
"friend_requests": "Followanfragen", "friend_requests": "Followanfragen",
"home_timeline": "Heim Zeitlinie", "home_timeline": "Heimzeitleiste",
"home_timeline_description": "Beiträge von Leuten, denen du folgst",
"interactions": "Interaktionen", "interactions": "Interaktionen",
"lists": "Listen",
"mentions": "Erwähnungen", "mentions": "Erwähnungen",
"preferences": "Voreinstellungen", "preferences": "Voreinstellungen",
"public_timeline_description": "Öffentliche Beiträge von dieser Instanz",
"public_tl": "Öffentliche Zeitleiste", "public_tl": "Öffentliche Zeitleiste",
"search": "Suche", "search": "Suche",
"timeline": "Zeitleiste", "timeline": "Zeitleiste",
"timelines": "Zeitlinie", "timelines": "Zeitlinie",
"twkn": "Bekannte Netzwerk", "twkn": "Bekanntes Netzwerk",
"twkn_timeline_description": "Beiträge aus dem gesamten bekannten Netzwerk",
"user_search": "Benutzersuche", "user_search": "Benutzersuche",
"who_to_follow": "Wem folgen" "who_to_follow": "Wem folgen"
}, },
"notifications": { "notifications": {
"broken_favorite": "Unbekannte Nachricht, suche danach…", "broken_favorite": "Unbekannte Nachricht, suche danach…",
"error": "Error beim laden von Neuigkeiten", "error": "Fehler beim Laden neuer Benachrichtigungen: {0}",
"favorited_you": "favorisierte deine Nachricht", "favorited_you": "favorisierte deine Nachricht",
"follow_request": "möchte dir folgen", "follow_request": "möchte dir folgen",
"followed_you": "folgt dir", "followed_you": "folgt dir",
@ -183,6 +299,7 @@
"migrated_to": "migrierte zu", "migrated_to": "migrierte zu",
"no_more_notifications": "Keine Benachrichtigungen mehr", "no_more_notifications": "Keine Benachrichtigungen mehr",
"notifications": "Benachrichtigungen", "notifications": "Benachrichtigungen",
"poll_ended": "Umfrage wurde beendet",
"reacted_with": "reagierte mit {0}", "reacted_with": "reagierte mit {0}",
"read": "Gelesen!", "read": "Gelesen!",
"repeated_you": "wiederholte deine Nachricht" "repeated_you": "wiederholte deine Nachricht"
@ -223,27 +340,34 @@
"text/bbcode": "BBCode", "text/bbcode": "BBCode",
"text/html": "HTML", "text/html": "HTML",
"text/markdown": "Markdown", "text/markdown": "Markdown",
"text/plain": "Nur Text" "text/plain": "Nur Text",
"text/x.misskeymarkdown": "MFM"
}, },
"content_warning": "Betreff (optional)", "content_warning": "Inhaltswarnung (optional)",
"default": "Sitze gerade im Hofbräuhaus.", "default": "Sitze gerade im Hofbräuhaus",
"direct_warning_to_all": "Dieser Beitrag wird für alle erwähnten Benutzer sichtbar sein.", "direct_warning_to_all": "Dieser Beitrag wird für alle erwähnten Benutzer sichtbar sein.",
"direct_warning_to_first_only": "Dieser Beitrag wird für alle Benutzer, die am Anfang der Nachricht erwähnt wurden, sichtbar sein.", "direct_warning_to_first_only": "Dieser Beitrag wird für alle Benutzer, die am Anfang der Nachricht erwähnt wurden, sichtbar sein.",
"empty_status_error": "Eine leere Nachricht ohne Anhänge kann nicht gesendet werden", "edit_remote_warning": "Änderungen könnten auf manchen Instanzen nicht sichtbar sein!",
"edit_status": "Beitrag ändern",
"edit_unsupported_warning": "Umfragen und Erwähnungen werden durch die Bearbeitung nicht geändert.",
"empty_status_error": "Eine Nachricht ohne Text und ohne Anhänge kann nicht gesendet werden",
"media_description": "Medienbeschreibung", "media_description": "Medienbeschreibung",
"media_description_error": "Medien konnten nicht neu geladen werden, versuche es erneut", "media_description_error": "Medien konnten nicht neu geladen werden, versuche es erneut",
"new_status": "Neuen Status veröffentlichen", "media_not_sensitive_warning": "Es wurde eine Inhaltswarnung eingestellt, aber die Anhänge sind nicht als heikel gekennzeichnet!",
"new_status": "Neuer Post",
"post": "Post", "post": "Post",
"posting": "Veröffentlichen", "posting": "Veröffentlichen",
"preview": "Vorschau", "preview": "Vorschau",
"preview_empty": "Leer", "preview_empty": "Leer",
"scope": { "scope": {
"direct": "Direkt - Beitrag nur an erwähnte Profile", "direct": "Direkt - Beitrag nur an erwähnte Profile",
"local": "Lokal - diesen Beitrag nicht föderieren",
"private": "Nur Follower - Beitrag nur für Follower sichtbar", "private": "Nur Follower - Beitrag nur für Follower sichtbar",
"public": "Öffentlich - Beitrag an öffentliche Zeitleisten", "public": "Öffentlich - Beitrag an öffentliche Zeitleisten",
"unlisted": "Nicht gelistet - Nicht in öffentlichen Zeitleisten anzeigen" "unlisted": "Nicht gelistet - Nicht in öffentlichen Zeitleisten anzeigen"
}, },
"scope_notice": { "scope_notice": {
"local": "Dieser Bericht ist auf anderen Instanzen nicht sichbar",
"private": "Dieser Beitrag wird nur für deine Follower sichtbar sein", "private": "Dieser Beitrag wird nur für deine Follower sichtbar sein",
"public": "Dieser Beitrag wird für alle sichtbar sein", "public": "Dieser Beitrag wird für alle sichtbar sein",
"unlisted": "Dieser Beitrag wird weder in der öffentlichen Zeitleiste noch im gesamten bekannten Netzwerk sichtbar sein" "unlisted": "Dieser Beitrag wird weder in der öffentlichen Zeitleiste noch im gesamten bekannten Netzwerk sichtbar sein"
@ -251,11 +375,12 @@
}, },
"registration": { "registration": {
"bio": "Bio", "bio": "Bio",
"bio_placeholder": "z.B.\nHallo, ich bin Lain.\nIch bin ein super süßes blushy-crushy Anime Girl aus dem vorstädtischen Japan. Du kennst mich vielleicht von Wired.", "bio_placeholder": "z. B.\nHallo! Willkommen auf meinem Profil.\nIch mag Anime und Spiele. Hoffentlich können wir Freunde sein!",
"captcha": "CAPTCHA", "captcha": "CAPTCHA",
"email": "Email", "email": "Email",
"email_language": "In welcher Sprache möchtest du E-Mails vom Server erhalten?",
"fullname": "Angezeigter Name", "fullname": "Angezeigter Name",
"fullname_placeholder": "z.B. Lain Iwakura", "fullname_placeholder": "z. B. Atsuko Kagari",
"new_captcha": "Zum Erstellen eines neuen Captcha auf das Bild klicken", "new_captcha": "Zum Erstellen eines neuen Captcha auf das Bild klicken",
"password_confirm": "Passwort bestätigen", "password_confirm": "Passwort bestätigen",
"reason": "Grund zur Anmeldung", "reason": "Grund zur Anmeldung",
@ -263,7 +388,7 @@
"register": "Registrierung", "register": "Registrierung",
"registration": "Registrierung", "registration": "Registrierung",
"token": "Einladungsschlüssel", "token": "Einladungsschlüssel",
"username_placeholder": "z.B. lain", "username_placeholder": "z. B. akko",
"validations": { "validations": {
"email_required": "darf nicht leer sein", "email_required": "darf nicht leer sein",
"fullname_required": "darf nicht leer sein", "fullname_required": "darf nicht leer sein",
@ -290,7 +415,19 @@
}, },
"settings": { "settings": {
"accent": "Akzent", "accent": "Akzent",
"account_alias": "Account-Pseudonyme",
"account_alias_table_head": "Pseudonym",
"account_backup": "Sicherungskopie des Accounts",
"account_backup_description": "Dies ermöglicht es, ein Archiv aller Informationen und Beiträge des Accounts herunterzuladen, aber dieses Archiv kann nicht in einen Pleroma-Account importiert werden.",
"account_backup_table_head": "Sicherungskopie",
"account_privacy": "Privatsphäre",
"add_alias_error": "Fehler beim Hinzufügen eines Pseudonyms: {error}",
"add_backup": "Neue Sicherungskopie erstellen",
"add_backup_error": "Fehler beim Erstellen der Sicherungskopie: {error}",
"added_alias": "Pseudonym hinzugefügt.",
"added_backup": "Sicherungskopie hinzugefügt.",
"allow_following_move": "Erlaube auto-follow, wenn von dir verfolgte Accounts umziehen", "allow_following_move": "Erlaube auto-follow, wenn von dir verfolgte Accounts umziehen",
"always_show_post_button": "Immer einen schwebenden Knopf zum Erstellen neuer Beiträge anzeigen",
"app_name": "Anwendungsname", "app_name": "Anwendungsname",
"attachmentRadius": "Anhänge", "attachmentRadius": "Anhänge",
"attachments": "Anhänge", "attachments": "Anhänge",
@ -300,6 +437,7 @@
"avatarRadius": "Avatare", "avatarRadius": "Avatare",
"avatar_size_instruction": "Die empfohlene minimale Größe für Avatare ist 150x150 Pixel.", "avatar_size_instruction": "Die empfohlene minimale Größe für Avatare ist 150x150 Pixel.",
"background": "Hintergrund", "background": "Hintergrund",
"backup_not_ready": "Diese Sicherungskopie ist noch nicht fertig.",
"bio": "Bio", "bio": "Bio",
"block_export": "Block Export", "block_export": "Block Export",
"block_export_button": "Exportiere deine Blocks in eine csv Datei", "block_export_button": "Exportiere deine Blocks in eine csv Datei",
@ -321,10 +459,27 @@
"changed_password": "Passwort erfolgreich geändert!", "changed_password": "Passwort erfolgreich geändert!",
"chatMessageRadius": "Chat Nachricht", "chatMessageRadius": "Chat Nachricht",
"checkboxRadius": "Auswahlfelder", "checkboxRadius": "Auswahlfelder",
"collapse_subject": "Beiträge mit Betreff einklappen", "collapse_subject": "Beiträge mit Inhaltswarnungen einklappen",
"columns": "Spalten",
"composing": "Verfassen", "composing": "Verfassen",
"confirm_dialogs": "Bestätigung erforderlich für:",
"confirm_dialogs_approve_follow": "Annehmen einer Followanfrage",
"confirm_dialogs_block": "Jemanden blockieren",
"confirm_dialogs_delete": "Löschen eines Beitrages",
"confirm_dialogs_deny_follow": "Ablehnen einer Followanfrage",
"confirm_dialogs_mute": "Jemanden stummschalten",
"confirm_dialogs_repeat": "Wiederholen eines Beitrages",
"confirm_dialogs_unfollow": "Folgen beenden",
"confirm_new_password": "Neues Passwort bestätigen", "confirm_new_password": "Neues Passwort bestätigen",
"confirmation_dialogs": "Bestätigungs-Einstellungen",
"conversation_display": "Anzeige wie ein Gespräch",
"conversation_display_linear": "lineare Anzeige",
"conversation_display_tree": "hierarchische Anzeige",
"conversation_other_replies_button": "Zeige den \"andere Antworten\"-Knopf",
"conversation_other_replies_button_below": "Unter Beiträgen",
"conversation_other_replies_button_inside": "Innerhalb von Beiträgen",
"current_avatar": "Dein derzeitiger Avatar", "current_avatar": "Dein derzeitiger Avatar",
"current_mascot": "Das ausgewählte Maskottchen",
"current_password": "Aktuelles Passwort", "current_password": "Aktuelles Passwort",
"data_import_export_tab": "Datenimport/-export", "data_import_export_tab": "Datenimport/-export",
"default_vis": "Standard-Sichtbarkeitsumfang", "default_vis": "Standard-Sichtbarkeitsumfang",
@ -332,11 +487,15 @@
"delete_account_description": "Lösche deine Daten und deaktiviere deinen Account unwiderruflich.", "delete_account_description": "Lösche deine Daten und deaktiviere deinen Account unwiderruflich.",
"delete_account_error": "Es ist ein Fehler beim Löschen deines Accounts aufgetreten. Tritt dies weiterhin auf, wende dich an den Administrator der Instanz.", "delete_account_error": "Es ist ein Fehler beim Löschen deines Accounts aufgetreten. Tritt dies weiterhin auf, wende dich an den Administrator der Instanz.",
"delete_account_instructions": "Tippe dein Passwort unten in das Feld ein, um die Löschung deines Accounts zu bestätigen.", "delete_account_instructions": "Tippe dein Passwort unten in das Feld ein, um die Löschung deines Accounts zu bestätigen.",
"disable_sticky_headers": "Spaltenüberschriften nicht am Bildschirmrand anheften",
"discoverable": "Erlaube, dass dieser Account in Suchergebnissen auftaucht", "discoverable": "Erlaube, dass dieser Account in Suchergebnissen auftaucht",
"domain_mutes": "Domains", "domain_mutes": "Domains",
"download_backup": "Herunterladen",
"email_language": "Sprache für E-Mails des Servers",
"emoji_reactions_on_timeline": "Zeige Emoji-Reaktionen auf der Zeitleiste", "emoji_reactions_on_timeline": "Zeige Emoji-Reaktionen auf der Zeitleiste",
"enable_web_push_notifications": "Web-Pushbenachrichtigungen aktivieren", "enable_web_push_notifications": "Web-Pushbenachrichtigungen aktivieren",
"enter_current_password_to_confirm": "Gib dein aktuelles Passwort ein, um deine Identität zu bestätigen", "enter_current_password_to_confirm": "Gib dein aktuelles Passwort ein, um deine Identität zu bestätigen",
"expert_mode": "Erweiterte Einstellungen anzeigen",
"export_theme": "Farbschema speichern", "export_theme": "Farbschema speichern",
"file_export_import": { "file_export_import": {
"backup_restore": "Einstellungen backuppen", "backup_restore": "Einstellungen backuppen",
@ -344,8 +503,8 @@
"backup_settings_theme": "Einstellungen und Theme in eine Datei speichern", "backup_settings_theme": "Einstellungen und Theme in eine Datei speichern",
"errors": { "errors": {
"file_slightly_new": "Geringfügige Abweichung in der Dateiversion, einige Einstellungen konnten möglicherweise nicht geladen werden", "file_slightly_new": "Geringfügige Abweichung in der Dateiversion, einige Einstellungen konnten möglicherweise nicht geladen werden",
"file_too_new": "Inkompatible Major Version: {fileMajor}, dieses PleromaFE Version (settings ver {feMajor}) ist zu alt", "file_too_new": "Inkompatible Major-Version: {fileMajor}, diese PleromaFE-Version (Einstellungs-Version {feMajor}) ist zu alt",
"file_too_old": "Inkompatible Major Version: {fileMajor}, die Dateiversion ist zu alt und wird nicht mehr unterstützt (min. set. ver. {feMajor})", "file_too_old": "Inkompatible Major-Version: {fileMajor}, die Dateiversion ist zu alt und wird nicht mehr unterstützt (mind. Version {feMajor})",
"invalid_file": "Die ausgewählte Datei kann nicht zur Wiederherstellung verwendet werden. Keine Änderungen wurden umgesetzt." "invalid_file": "Die ausgewählte Datei kann nicht zur Wiederherstellung verwendet werden. Keine Änderungen wurden umgesetzt."
}, },
"restore_settings": "Einstellungen von einer Datei wiederherstellen" "restore_settings": "Einstellungen von einer Datei wiederherstellen"
@ -364,18 +523,26 @@
"hide_all_muted_posts": "Verstecke stummgeschaltete Posts", "hide_all_muted_posts": "Verstecke stummgeschaltete Posts",
"hide_attachments_in_convo": "Anhänge in Unterhaltungen ausblenden", "hide_attachments_in_convo": "Anhänge in Unterhaltungen ausblenden",
"hide_attachments_in_tl": "Anhänge in der Zeitleiste ausblenden", "hide_attachments_in_tl": "Anhänge in der Zeitleiste ausblenden",
"hide_bot_indication": "Bot-Hinweis in Beiträgen ausblenden",
"hide_favorites_description": "Favoriten-Liste verbergen (andere erhalten trotzdem Benachrichtigungen)",
"hide_filtered_statuses": "Gefilterte Beiträge verbergen", "hide_filtered_statuses": "Gefilterte Beiträge verbergen",
"hide_followers_count_description": "Verberge die Anzahl deiner Folgenden", "hide_followers_count_description": "Verberge die Anzahl deiner Folgenden",
"hide_followers_description": "Zeige nicht, wer mir folgt", "hide_followers_description": "Zeige nicht, wer mir folgt",
"hide_follows_count_description": "Verberge die Anzahl deiner Gefolgten", "hide_follows_count_description": "Verberge die Anzahl deiner Gefolgten",
"hide_follows_description": "Zeige nicht, wem ich folge", "hide_follows_description": "Zeige nicht, wem ich folge",
"hide_isp": "Instanz-spezifisches Panel ausblenden", "hide_isp": "Instanz-spezifisches Panel ausblenden",
"hide_list_aliases_error_action": "Schließen",
"hide_media_previews": "Verstecke Vorschau von Medien", "hide_media_previews": "Verstecke Vorschau von Medien",
"hide_muted_posts": "Verberge Beiträge stummgeschalteter Nutzer", "hide_muted_posts": "Verberge Beiträge stummgeschalteter Nutzer",
"hide_muted_threads": "Stummgeschaltete Unterhaltungen ausblenden",
"hide_post_stats": "Beitragsstatistiken verbergen (z.B. die Anzahl der Favoriten)", "hide_post_stats": "Beitragsstatistiken verbergen (z.B. die Anzahl der Favoriten)",
"hide_shoutbox": "Shoutbox der Instanz verbergen", "hide_shoutbox": "Shoutbox der Instanz verbergen",
"hide_site_favicon": "Favicon der Instanz im Top-Panel nicht anzeigen",
"hide_site_name": "Instanznamen im Top-Panel nicht anzeigen",
"hide_threads_with_blocked_users": "Unterhaltungen, die blockierte Benutzer erwähnen, stummschalten",
"hide_user_stats": "Benutzerstatistiken verbergen (z.B. die Anzahl der Follower)", "hide_user_stats": "Benutzerstatistiken verbergen (z.B. die Anzahl der Follower)",
"hide_wallpaper": "Verstecke Instanzhintergrundbild", "hide_wallpaper": "Verstecke Instanzhintergrundbild",
"hide_wordfiltered_statuses": "Beiträge, die durch den Wortfilter erkannt wurden, ausblenden",
"import_blocks_from_a_csv_file": "Importiere Blocks von einer CSV Datei", "import_blocks_from_a_csv_file": "Importiere Blocks von einer CSV Datei",
"import_followers_from_a_csv_file": "Importiere Follower aus einer CSV-Datei", "import_followers_from_a_csv_file": "Importiere Follower aus einer CSV-Datei",
"import_mutes_from_a_csv_file": "Importiere stummgeschaltete User von einer cvs Datei", "import_mutes_from_a_csv_file": "Importiere stummgeschaltete User von einer cvs Datei",
@ -388,10 +555,23 @@
"invalid_theme_imported": "Die ausgewählte Datei ist kein unterstütztes Pleroma-Theme. Keine Änderungen wurden vorgenommen.", "invalid_theme_imported": "Die ausgewählte Datei ist kein unterstütztes Pleroma-Theme. Keine Änderungen wurden vorgenommen.",
"limited_availability": "In deinem Browser nicht verfügbar", "limited_availability": "In deinem Browser nicht verfügbar",
"links": "Links", "links": "Links",
"list_aliases_error": "Fehler beim Abrufen von Pseudonymen: {error}",
"list_backups_error": "Fehler beim Abrufen von Sicherungskopien: {error}",
"lock_account_description": "Sperre deinen Account, um neue Follower zu genehmigen oder abzulehnen", "lock_account_description": "Sperre deinen Account, um neue Follower zu genehmigen oder abzulehnen",
"loop_video": "Videos wiederholen", "loop_video": "Videos wiederholen",
"loop_video_silent_only": "Nur Videos ohne Ton wiederholen (z.B. Mastodons \"gifs\")", "loop_video_silent_only": "Nur Videos ohne Ton wiederholen (z.B. Mastodons \"gifs\")",
"mascot": "Mastodon-FE-Maskottchen",
"max_depth_in_thread": "Maximale Tiefe, bis zu der Unterhaltungen standardmäßig angezeigt werden",
"max_thumbnails": "Maximale Anzahl von Vorschaubildern pro Beitrag", "max_thumbnails": "Maximale Anzahl von Vorschaubildern pro Beitrag",
"mention_link_bolden_you": "eigene Erwähnungen hervorheben",
"mention_link_display": "Erwähungs-Links anzeigen",
"mention_link_display_full": "immer als vollständige Namen (z. B. {'@'}foo{'@'}example.org)",
"mention_link_display_full_for_remote": "vollständige Namen nur für Nutzer anderer Instanzen (z. B. {'@'}foo{'@'}example.org)",
"mention_link_display_short": "immer kurze Namen (z. B. {'@'}foo)",
"mention_link_fade_domain": "Domain schwächer anzeigen (z. B. das {'@'}example.org in {'@'}foo{'@'}example.org)",
"mention_link_show_avatar": "Benutzer-Avatar neben Link anzeigen",
"mention_link_show_tooltip": "Vollständigen Benutzernamen als Tooltip für Benutzer anderer Instanzen anzeigen",
"mention_links": "Erwähnungs-Links",
"mfa": { "mfa": {
"authentication_methods": "Authentifizierungsmethoden", "authentication_methods": "Authentifizierungsmethoden",
"confirm_and_enable": "Bestätige und aktiviere OTP", "confirm_and_enable": "Bestätige und aktiviere OTP",
@ -415,6 +595,12 @@
}, },
"minimal_scopes_mode": "Minimiere Reichweitenoptionen", "minimal_scopes_mode": "Minimiere Reichweitenoptionen",
"more_settings": "Weitere Einstellungen", "more_settings": "Weitere Einstellungen",
"move_account": "Account umziehen",
"move_account_error": "Fehler beim Umzug: {error}",
"move_account_notes": "Wenn der Account woanders hin umgezogen werden soll, muss dieser Account erst als ein Pseudonym des anderen Accounts eingestellt werden.",
"move_account_target": "Ziel-Account (z. B. {example})",
"moved_account": "Account umgezogen.",
"mute_bot_posts": "Bot-Beiträge stummschalten",
"mute_export": "Stumm geschaltete User exportieren", "mute_export": "Stumm geschaltete User exportieren",
"mute_export_button": "Stumm geschaltete User in eine cvs Datei exportieren", "mute_export_button": "Stumm geschaltete User in eine cvs Datei exportieren",
"mute_import": "Stumm geschaltete User importieren", "mute_import": "Stumm geschaltete User importieren",
@ -424,6 +610,7 @@
"mutes_tab": "Stummschaltungen", "mutes_tab": "Stummschaltungen",
"name": "Name", "name": "Name",
"name_bio": "Name & Bio", "name_bio": "Name & Bio",
"new_alias_target": "Neues Pseudonym hinzufügen (z. B. {example})",
"new_email": "Neue Email", "new_email": "Neue Email",
"new_password": "Neues Passwort", "new_password": "Neues Passwort",
"no_blocks": "Keine Blocks", "no_blocks": "Keine Blocks",
@ -433,6 +620,7 @@
"notification_mutes": "Um nicht mehr die Benachrichtigungen von einem bestimmten User zu bekommen, verwende eine Stummschaltung.", "notification_mutes": "Um nicht mehr die Benachrichtigungen von einem bestimmten User zu bekommen, verwende eine Stummschaltung.",
"notification_setting_block_from_strangers": "Benachrichtigungen von Nutzern blockieren, denen Du nicht folgst", "notification_setting_block_from_strangers": "Benachrichtigungen von Nutzern blockieren, denen Du nicht folgst",
"notification_setting_filters": "Filter", "notification_setting_filters": "Filter",
"notification_setting_hide_if_cw": "Inhalt von Push-Nachrichten verbergen, wenn eine Inhaltswarnung besteht",
"notification_setting_hide_notification_contents": "Absender und Inhalte von Push-Nachrichten verbergen", "notification_setting_hide_notification_contents": "Absender und Inhalte von Push-Nachrichten verbergen",
"notification_setting_privacy": "Privatsphäre", "notification_setting_privacy": "Privatsphäre",
"notification_visibility": "Benachrichtigungstypen, die angezeigt werden sollen", "notification_visibility": "Benachrichtigungstypen, die angezeigt werden sollen",
@ -441,6 +629,7 @@
"notification_visibility_likes": "Favoriten", "notification_visibility_likes": "Favoriten",
"notification_visibility_mentions": "Erwähnungen", "notification_visibility_mentions": "Erwähnungen",
"notification_visibility_moves": "Nutzer zieht um", "notification_visibility_moves": "Nutzer zieht um",
"notification_visibility_polls": "Abschluss von Umfragen, in denen du abgestimmt hast",
"notification_visibility_repeats": "Wiederholungen", "notification_visibility_repeats": "Wiederholungen",
"notifications": "Benachrichtigungen", "notifications": "Benachrichtigungen",
"nsfw_clickthrough": "Aktiviere ausblendbares Overlay für Anhänge, die als NSFW markiert sind", "nsfw_clickthrough": "Aktiviere ausblendbares Overlay für Anhänge, die als NSFW markiert sind",
@ -449,7 +638,8 @@
"panelRadius": "Panel", "panelRadius": "Panel",
"pause_on_unfocused": "Streaming pausieren, wenn das Tab nicht fokussiert ist", "pause_on_unfocused": "Streaming pausieren, wenn das Tab nicht fokussiert ist",
"play_videos_in_modal": "Videos in größerem Medienfenster abspielen", "play_videos_in_modal": "Videos in größerem Medienfenster abspielen",
"post_status_content_type": "Beitragsart", "post_status_content_type": "Standard-Beitragsart",
"posts": "Beiträge",
"preload_images": "Bilder vorausladen", "preload_images": "Bilder vorausladen",
"presets": "Voreinstellungen", "presets": "Voreinstellungen",
"profile_background": "Profilhintergrund", "profile_background": "Profilhintergrund",
@ -463,6 +653,10 @@
"profile_tab": "Profil", "profile_tab": "Profil",
"radii_help": "Kantenrundung (in Pixel) der Oberfläche anpassen", "radii_help": "Kantenrundung (in Pixel) der Oberfläche anpassen",
"refresh_token": "Token aktualisieren", "refresh_token": "Token aktualisieren",
"remove_alias": "Dieses Pseudonym entfernen",
"remove_backup": "Entfernen",
"render_mfm": "Misskey-Markdown darstellen",
"render_mfm_on_hover": "MFM-Animationen pausieren, solange sich der Mauszeiger nicht über dem Beitrag befindet",
"replies_in_timeline": "Antworten in der Zeitleiste", "replies_in_timeline": "Antworten in der Zeitleiste",
"reply_visibility_all": "Alle Antworten zeigen", "reply_visibility_all": "Alle Antworten zeigen",
"reply_visibility_following": "Zeige nur Antworten an mich oder an Benutzer, denen ich folge", "reply_visibility_following": "Zeige nur Antworten an mich oder an Benutzer, denen ich folge",
@ -486,13 +680,21 @@
"security": "Sicherheit", "security": "Sicherheit",
"security_tab": "Sicherheit", "security_tab": "Sicherheit",
"sensitive_by_default": "Alle Beiträge standardmäßig als heikel markieren", "sensitive_by_default": "Alle Beiträge standardmäßig als heikel markieren",
"sensitive_if_subject": "Bilder automatisch als heikel markieren, wenn der Beitrag eine Inhaltswarnung hat",
"set_new_avatar": "Setze einen neuen Avatar", "set_new_avatar": "Setze einen neuen Avatar",
"set_new_mascot": "Neues Maskottchen einstellen",
"set_new_profile_background": "Setze einen neuen Hintergrund für dein Profil", "set_new_profile_background": "Setze einen neuen Hintergrund für dein Profil",
"set_new_profile_banner": "Setze einen neuen Banner für dein Profil", "set_new_profile_banner": "Setze einen neuen Banner für dein Profil",
"setting_changed": "Einstellungen weichen von den Standardeinstellungen ab", "setting_changed": "Einstellungen weichen von den Standardeinstellungen ab",
"setting_server_side": "Diese Einstellung hängt an deinem Profil und gilt für alle Sitzungen und Clients",
"settings": "Einstellungen", "settings": "Einstellungen",
"show_admin_badge": "Zeige Admin-Abzeichen auf meinem Profil", "show_admin_badge": "Zeige Admin-Abzeichen auf meinem Profil",
"show_moderator_badge": "Zeige Moderator-Abzeichen auf meinem Profil", "show_moderator_badge": "Zeige Moderator-Abzeichen auf meinem Profil",
"show_nav_shortcuts": "Zusätzliche Schnellnavigation im Top-Panel anzeigen",
"show_panel_nav_shortcuts": "Zeitleisten-Schnellnavigation im Panel oben anzeigen",
"show_scrollbars": "Scrollbalken der Seitenspalte anzeigen",
"show_wider_shortcuts": "Mehr Platz zwischen Schnellnagivationen im Top-Panel anzeigen",
"show_yous": "(Du)'s anzeigen",
"stop_gifs": "Animationen nur beim Darüberfahren abspielen", "stop_gifs": "Animationen nur beim Darüberfahren abspielen",
"streaming": "Aktiviere automatisches Laden (Streaming) von neuen Beiträgen", "streaming": "Aktiviere automatisches Laden (Streaming) von neuen Beiträgen",
"style": { "style": {
@ -574,7 +776,7 @@
"fine_print": "Lies unser {0}, um nichts Nützliches zu lernen!", "fine_print": "Lies unser {0}, um nichts Nützliches zu lernen!",
"header": "Vorschau", "header": "Vorschau",
"header_faint": "Das ist in Ordnung", "header_faint": "Das ist in Ordnung",
"input": "Sitze gerade im Hofbräuhaus.", "input": "Sitze gerade im Hofbräuhaus",
"link": "ein netter kleiner Link", "link": "ein netter kleiner Link",
"mono": "Inhalt", "mono": "Inhalt",
"text": "Ein Haufen mehr von {0} und {1}" "text": "Ein Haufen mehr von {0} und {1}"
@ -641,9 +843,9 @@
"use_source": "Neue Version" "use_source": "Neue Version"
} }
}, },
"subject_input_always_show": "Betreff-Feld immer anzeigen", "subject_input_always_show": "Feld für Inhaltswarnung immer anzeigen",
"subject_line_behavior": "Betreff beim Antworten kopieren", "subject_line_behavior": "Inhaltswarnung beim Antworten kopieren",
"subject_line_email": "Wie Email: \"re: Betreff\"", "subject_line_email": "Wie E-Mail: \"re: Inhaltswarnung\"",
"subject_line_mastodon": "Wie Mastodon: unverändert kopieren", "subject_line_mastodon": "Wie Mastodon: unverändert kopieren",
"subject_line_noop": "Nicht kopieren", "subject_line_noop": "Nicht kopieren",
"text": "Text", "text": "Text",
@ -651,15 +853,25 @@
"theme_help": "Benutze HTML-Farbcodes (#rrggbb) um dein Farbschema anzupassen.", "theme_help": "Benutze HTML-Farbcodes (#rrggbb) um dein Farbschema anzupassen.",
"theme_help_v2_1": "Du kannst auch die Farben und die Deckkraft bestimmter Komponenten überschreiben, indem du das Kontrollkästchen umschaltest. Verwende die Schaltfläche \"Alle löschen\", um alle Überschreibungen zurückzusetzen.", "theme_help_v2_1": "Du kannst auch die Farben und die Deckkraft bestimmter Komponenten überschreiben, indem du das Kontrollkästchen umschaltest. Verwende die Schaltfläche \"Alle löschen\", um alle Überschreibungen zurückzusetzen.",
"theme_help_v2_2": "Unter einigen Einträgen befinden sich Symbole für Hintergrund-/Textkontrastindikatoren, für detaillierte Informationen fahre mit der Maus darüber. Bitte beachte, dass bei der Verwendung von Transparenz Kontrastindikatoren den schlechtest möglichen Fall darstellen.", "theme_help_v2_2": "Unter einigen Einträgen befinden sich Symbole für Hintergrund-/Textkontrastindikatoren, für detaillierte Informationen fahre mit der Maus darüber. Bitte beachte, dass bei der Verwendung von Transparenz Kontrastindikatoren den schlechtest möglichen Fall darstellen.",
"third_column_mode": "Wenn genug Platz ist, dritte Spalte anzeigen mit",
"third_column_mode_none": "Dritte Spalte nicht anzeigen",
"third_column_mode_notifications": "Benachrichtigungs-Spalte",
"third_column_mode_postform": "Eingabe für Beiträge und Navigation",
"token": "Zeichen", "token": "Zeichen",
"tooltipRadius": "Tooltips/Warnungen", "tooltipRadius": "Tooltips/Warnungen",
"translation_language": "Sprache für automatische Übersetzungen",
"tree_advanced": "Weitere Knöpfe zum Öffnen und Schließen von Antworten anzeigen",
"tree_fade_ancestors": "Vorgänger des aktuellen Beitrags schwach darstellen",
"type_domains_to_mute": "Tippe die Domains ein, die du stummschalten willst", "type_domains_to_mute": "Tippe die Domains ein, die du stummschalten willst",
"upload_a_photo": "Lade ein Foto hoch", "upload_a_photo": "Lade ein Foto hoch",
"useStreamingApi": "Empfange Posts und Benachrichtigungen in Echtzeit", "useStreamingApi": "Empfange Posts und Benachrichtigungen in Echtzeit",
"useStreamingApiWarning": "(Nicht empfohlen, experimentell, bekannt dafür, Posts zu überspringen)", "useStreamingApiWarning": "(Nicht empfohlen, experimentell, bekannt dafür, Posts zu überspringen)",
"use_at_icon": "{'@'}-Symbol als Icon und nicht als Text anzeigen",
"use_contain_fit": "Vorschaubilder nicht zuschneiden", "use_contain_fit": "Vorschaubilder nicht zuschneiden",
"use_one_click_nsfw": "Heikle Anhänge mit nur einem Klick öffnen", "use_one_click_nsfw": "Heikle Anhänge mit nur einem Klick öffnen",
"user_mutes": "User", "user_mutes": "User",
"user_profile_default_tab": "Standard-Tab des Benutzerprofils",
"user_profiles": "Benutzerprofil",
"user_settings": "Benutzereinstellungen", "user_settings": "Benutzereinstellungen",
"valid_until": "Gültig bis", "valid_until": "Gültig bis",
"values": { "values": {
@ -671,35 +883,75 @@
"frontend_version": "Frontend Version", "frontend_version": "Frontend Version",
"title": "Version" "title": "Version"
}, },
"virtual_scrolling": "Rendering der Timeline optimieren", "virtual_scrolling": "Anzeige der Zeitleiste optimieren",
"word_filter": "Wort Filter" "word_filter": "Wortfilter",
"wordfilter": "Wortfilter"
}, },
"status": { "status": {
"ancestor_follow": "Zeige {numReplies} andere Antwort unter diesem Beitrag | Zeige {numReplies} andere Antworten unter diesem Beitrag",
"ancestor_follow_with_icon": "{icon} {text}",
"attachment_stop_flash": "Flash-Player stoppen",
"bookmark": "Lesezeichen setzen", "bookmark": "Lesezeichen setzen",
"collapse_attachments": "Anhänge einklappen",
"copy_link": "Beitragslink kopieren", "copy_link": "Beitragslink kopieren",
"delete": "Lösche Beitrag", "delete": "Lösche Beitrag",
"delete_confirm": "Möchtest du diese Beitrag wirklich löschen?", "delete_confirm": "Möchtest du diese Beitrag wirklich löschen?",
"delete_confirm_accept_button": "Ja, löschen",
"delete_confirm_cancel_button": "Nein, behalten",
"delete_confirm_title": "Löschen bestätigen",
"edit": "Bearbeiten",
"edit_history": "Bearbeitungsverlauf",
"edit_history_modal_title": "{historyCount} Mal bearbeitet | {historyCount} Mal bearbeitet",
"edited_at": "Bearbeitet um {time}",
"expand": "Ausklappen", "expand": "Ausklappen",
"external_source": "Externe Quelle", "external_source": "Externe Quelle",
"favorites": "Favoriten", "favorites": "Favoriten",
"hide_attachment": "Anhänge verbergen",
"hide_content": "Inhalt verbergen", "hide_content": "Inhalt verbergen",
"hide_full_subject": "Vollständiges Thema verbergen", "hide_full_subject": "Vollständige Inhaltswarnung verbergen",
"many_attachments": "Beitrag hat {number} Anhang | Beitrag hat {number} Anhänge",
"mentions": "Erwähnungen",
"move_down": "Anhang nach rechts verschieben",
"move_up": "Anhang nach links verschieben",
"mute_conversation": "Konversation stummstellen", "mute_conversation": "Konversation stummstellen",
"nsfw": "NSFW", "nsfw": "NSFW",
"open_gallery": "Galerie öffnen",
"override_translation_source_language": "Ursprungsspache überschreiben",
"pin": "An Profil anheften", "pin": "An Profil anheften",
"pinned": "Angeheftet", "pinned": "Angeheftet",
"plus_more": "+{number} mehr",
"remove_attachment": "Anhang entfernen",
"repeat_confirm": "Beitrag wirklich wiederholen?",
"repeat_confirm_accept_button": "Ja, wiederholen",
"repeat_confirm_cancel_button": "Nein, nicht wiederholen",
"repeat_confirm_title": "Wiederholen bestätigen",
"repeats": "Geteilte Beiträge", "repeats": "Geteilte Beiträge",
"replies_list": "Antworten:", "replies_list": "Antworten:",
"replies_list_with_others": "Zeige noch {numReplies} Antwort | Zeige noch {numReplies} Antworten",
"reply_to": "Antworten auf", "reply_to": "Antworten auf",
"show_all_attachments": "Alle Anhänge anzeigen",
"show_all_conversation": "Ganzes Gespräch anzeigen (noch {numStatus} Beitrag) | Ganzes Gespräch anzeigen (noch {numStatus} Beiträge)",
"show_all_conversation_with_icon": "{icon} {text}",
"show_attachment_description": "Vorschau-Beschreibung (Anhang öffnen für vollständige Beschreibung)",
"show_attachment_in_modal": "Anhang in einem Fenster anzeigen",
"show_content": "Inhalt anzeigen", "show_content": "Inhalt anzeigen",
"show_full_subject": "Vollständiges Thema anzeigen", "show_full_subject": "Vollständige Inhaltswarnung anzeigen",
"show_only_conversation_under_this": "Nur Antworten auf diesen Bericht anzeigen",
"status_deleted": "Dieser Beitrag wurde gelöscht", "status_deleted": "Dieser Beitrag wurde gelöscht",
"status_unavailable": "Beitrag nicht verfügbar", "status_unavailable": "Beitrag nicht verfügbar",
"thread_muted": "Thread stummgeschaltet", "thread_follow": "Zeige noch {numStatus} Antwort | Zeige noch {numStatus} Antworten",
"thread_follow_with_icon": "{icon} {text}",
"thread_hide": "Diese Unterhaltung stummschalten",
"thread_muted": "Unterhaltung stummgeschaltet",
"thread_muted_and_words": ", enthält folgende Wörter:", "thread_muted_and_words": ", enthält folgende Wörter:",
"thread_show": "Diese Unterhaltung anzeigen",
"thread_show_full": "Zeige {numStatus} Antwort | Zeige {numStatus} Antworten",
"thread_show_full_with_icon": "{icon} {text}",
"translate": "Übersetzen",
"unbookmark": "Lesezeichen entfernen", "unbookmark": "Lesezeichen entfernen",
"unmute_conversation": "Konversation nicht mehr stummstellen", "unmute_conversation": "Konversation nicht mehr stummstellen",
"unpin": "Nicht mehr an Profil anheften" "unpin": "Nicht mehr an Profil anheften",
"you": "(Du)"
}, },
"time": { "time": {
"in_future": "in {0}", "in_future": "in {0}",
@ -729,7 +981,7 @@
"error": "Fehler beim Lesen der Timeline: {0}", "error": "Fehler beim Lesen der Timeline: {0}",
"load_older": "Lade ältere Beiträge", "load_older": "Lade ältere Beiträge",
"no_more_statuses": "Keine weiteren Beiträge", "no_more_statuses": "Keine weiteren Beiträge",
"no_retweet_hint": "Der Beitrag ist als nur-für-Follower oder als Direktnachricht markiert und kann nicht wiederholt werden", "no_retweet_hint": "Der Beitrag ist als nur-für-Follower oder Direktnachricht markiert und kann nicht wiederholt oder zitiert werden",
"no_statuses": "Keine Beiträge", "no_statuses": "Keine Beiträge",
"reload": "Neu laden", "reload": "Neu laden",
"repeated": "wiederholte", "repeated": "wiederholte",
@ -744,6 +996,7 @@
"bookmark": "Lesezeichen", "bookmark": "Lesezeichen",
"favorite": "Favorisieren", "favorite": "Favorisieren",
"media_upload": "Medien hochladen", "media_upload": "Medien hochladen",
"quote": "Zitieren",
"reject_follow_request": "Folgeanfrage ablehnen", "reject_follow_request": "Folgeanfrage ablehnen",
"repeat": "Wiederholen", "repeat": "Wiederholen",
"reply": "Antworten", "reply": "Antworten",
@ -770,6 +1023,7 @@
"deactivate_account": "Konto deaktivieren", "deactivate_account": "Konto deaktivieren",
"delete_account": "Konto löschen", "delete_account": "Konto löschen",
"delete_user": "Nutzer löschen", "delete_user": "Nutzer löschen",
"delete_user_data_and_deactivate_confirmation": "Dies löscht unwiderruflich alle Daten dieses Accounts und deaktiviert ihn. Bist du ganz sicher?",
"disable_any_subscription": "Alle Folgeanfragen für diesen Nutzer grundsätzlich ablehnen", "disable_any_subscription": "Alle Folgeanfragen für diesen Nutzer grundsätzlich ablehnen",
"disable_remote_subscription": "Nutzer anderer Instanzen vom Folgen dieses Nutzers ausschließen", "disable_remote_subscription": "Nutzer anderer Instanzen vom Folgen dieses Nutzers ausschließen",
"force_nsfw": "Alle Beiträge als pervers markieren", "force_nsfw": "Alle Beiträge als pervers markieren",
@ -784,13 +1038,29 @@
"strip_media": "Medien von Beiträgen entfernen" "strip_media": "Medien von Beiträgen entfernen"
}, },
"approve": "Genehmigen", "approve": "Genehmigen",
"approve_confirm": "Willst du diesen Benutzer dir wirklich folgen lassen?",
"approve_confirm_accept_button": "Ja, akzeptieren",
"approve_confirm_cancel_button": "Nein, ablehnen",
"approve_confirm_title": "Folgeanfrage bestätigen",
"block": "Blockieren", "block": "Blockieren",
"block_confirm": "Willst du {user} wirklich blockieren?",
"block_confirm_accept_button": "Ja, blockieren",
"block_confirm_cancel_button": "Nein, nicht blockieren",
"block_confirm_title": "Benutzer blockieren",
"block_progress": "Blocken…", "block_progress": "Blocken…",
"blocked": "Blockiert!", "blocked": "Blockiert!",
"bot": "Bot", "bot": "Bot",
"deactivated": "Deaktiviert",
"deny": "Ablehnen", "deny": "Ablehnen",
"deny_confirm": "Willst du die Folgeanfrage dieses Benutzers wirklich ablehnen?",
"deny_confirm_accept_button": "Ja, ablehnen",
"deny_confirm_cancel_button": "Nein, abbrechen",
"deny_confirm_title": "Folgeanfrage ablehnen",
"domain_muted": "Domain nicht mehr blockieren",
"edit_profile": "Profil bearbeiten",
"favorites": "Favoriten", "favorites": "Favoriten",
"follow": "Folgen", "follow": "Folgen",
"follow_cancel": "Anfrage ablehnen",
"follow_progress": "Anfragen…", "follow_progress": "Anfragen…",
"follow_sent": "Anfrage gesendet!", "follow_sent": "Anfrage gesendet!",
"follow_unfollow": "Folgen beenden", "follow_unfollow": "Folgen beenden",
@ -811,16 +1081,27 @@
"mention": "Erwähnungen", "mention": "Erwähnungen",
"message": "Nachricht", "message": "Nachricht",
"mute": "Stummschalten", "mute": "Stummschalten",
"mute_confirm": "Willst du {user} wirklich stummschalten?",
"mute_confirm_accept_button": "Ja, stummschalten",
"mute_confirm_cancel_button": "Nein, nicht stummschalten",
"mute_confirm_title": "Benutzer stummschalten",
"mute_domain": "Domain blockieren",
"mute_progress": "Stummschalten erfolgt…", "mute_progress": "Stummschalten erfolgt…",
"muted": "Stummgeschaltet", "muted": "Stummgeschaltet",
"note": "Private Notiz",
"per_day": "pro Tag", "per_day": "pro Tag",
"remote_follow": "Folgen", "remote_follow": "Folgen",
"replies": "Mit Antworten",
"report": "Melden", "report": "Melden",
"show_repeats": "Geteilte Beiträge anzeigen", "show_repeats": "Geteilte Beiträge anzeigen",
"statuses": "Beiträge", "statuses": "Beiträge",
"subscribe": "Folgen", "subscribe": "Folgen",
"unblock": "Entblocken", "unblock": "Entblocken",
"unblock_progress": "Entblocken…", "unblock_progress": "Entblocken…",
"unfollow_confirm": "Willst du {user} wirklich nicht mehr folgen?",
"unfollow_confirm_accept_button": "Ja, nicht mehr folgen",
"unfollow_confirm_cancel_button": "Nein, weiter folgen",
"unfollow_confirm_title": "Benutzer nicht mehr folgen",
"unmute": "Stummschalten aufheben", "unmute": "Stummschalten aufheben",
"unmute_progress": "Aufhebung erfolgt…", "unmute_progress": "Aufhebung erfolgt…",
"unsubscribe": "Entfolgen" "unsubscribe": "Entfolgen"
@ -843,4 +1124,4 @@
"more": "Mehr", "more": "Mehr",
"who_to_follow": "Wem soll ich folgen" "who_to_follow": "Wem soll ich folgen"
} }
} }

View file

@ -164,6 +164,74 @@
"load_older": "Load older interactions", "load_older": "Load older interactions",
"moves": "User migrates" "moves": "User migrates"
}, },
"languages": {
"bg": "Bulgarian",
"en": "English",
"ar": "Arabic",
"az": "Azerbaijani",
"zh": "Chinese",
"cs": "Czech",
"da": "Danish",
"nl": "Dutch",
"eo": "Esperanto",
"fi": "Finnish",
"fr": "French",
"de": "German",
"el": "Greek",
"he": "Hebrew",
"hi": "Hindi",
"hu": "Hungarian",
"id": "Indonesian",
"ga": "Irish",
"it": "Italian",
"ja": "Japanese",
"ko": "Korean",
"fa": "Persian",
"pl": "Polish",
"pt": "Portuguese",
"ru": "Russian",
"sk": "Slovak",
"es": "Spanish",
"sv": "Swedish",
"tr": "Turkish",
"uk": "Ukrainian",
"lt": "Lithuanian",
"lv": "Latvian",
"translated_from": {
"bg": "Translated from @:languages.bg",
"en": "Translated from @:languages.en",
"ar": "Translated from @:languages.ar",
"az": "Translated from @:languages.az",
"zh": "Translated from @:languages.zh",
"cs": "Translated from @:languages.cs",
"da": "Translated from @:languages.da",
"nl": "Translated from @:languages.nl",
"eo": "Translated from @:languages.eo",
"fi": "Translated from @:languages.fi",
"fr": "Translated from @:languages.fr",
"de": "Translated from @:languages.de",
"el": "Translated from @:languages.el",
"he": "Translated from @:languages.he",
"hi": "Translated from @:languages.hi",
"hu": "Translated from @:languages.hu",
"id": "Translated from @:languages.id",
"ga": "Translated from @:languages.ga",
"it": "Translated from @:languages.it",
"ja": "Translated from @:languages.ja",
"ko": "Translated from @:languages.ko",
"fa": "Translated from @:languages.fa",
"pl": "Translated from @:languages.pl",
"pt": "Translated from @:languages.pt",
"ru": "Translated from @:languages.ru",
"sk": "Translated from @:languages.sk",
"es": "Translated from @:languages.es",
"sv": "Translated from @:languages.sv",
"tr": "Translated from @:languages.tr",
"uk": "Translated from @:languages.uk",
"lt": "Translated from @:languages.lt",
"lv": "Translated from @:languages.lv"
}
},
"lists": { "lists": {
"create": "Create", "create": "Create",
"delete": "Delete list", "delete": "Delete list",
@ -625,6 +693,19 @@
"setting_changed": "Setting is different from default", "setting_changed": "Setting is different from default",
"setting_server_side": "This setting is tied to your profile and affects all sessions and clients", "setting_server_side": "This setting is tied to your profile and affects all sessions and clients",
"settings": "Settings", "settings": "Settings",
"settings_profile": "Settings Profiles",
"settings_profile_currently": "Currently using {name} (version: {version})",
"settings_profiles_show": "Show all settings profiles",
"settings_profiles_unshow": "Hide all settings profiles",
"settings_profile_in_use": "In use",
"settings_profile_creation": "Create new profile",
"settings_profile_creation_submit": "Create",
"settings_profile_creation_new_name_label": "Name",
"settings_profile_use": "Use",
"settings_profile_delete": "Delete",
"settings_profile_delete_confirm": "Do you really want to delete this profile?",
"settings_profile_force_sync": "Synchronize",
"settings_profiles_refresh": "Reload settings profiles",
"show_admin_badge": "Show \"Admin\" badge in my profile", "show_admin_badge": "Show \"Admin\" badge in my profile",
"show_moderator_badge": "Show \"Moderator\" badge in my profile", "show_moderator_badge": "Show \"Moderator\" badge in my profile",
"show_nav_shortcuts": "Show extra navigation shortcuts in top panel", "show_nav_shortcuts": "Show extra navigation shortcuts in top panel",
@ -824,6 +905,12 @@
"word_filter": "Word filter", "word_filter": "Word filter",
"wordfilter": "Wordfilter" "wordfilter": "Wordfilter"
}, },
"settings_profile": {
"synchronizing": "Synchronizing setting profile \"{profile}\"...",
"synchronized": "Synchronized settings!",
"synchronization_error": "Could not synchronize settings: {err}",
"creating": "Creating new setting profile \"{profile}\"..."
},
"status": { "status": {
"ancestor_follow": "See {numReplies} other reply under this post | See {numReplies} other replies under this post", "ancestor_follow": "See {numReplies} other reply under this post | See {numReplies} other replies under this post",
"ancestor_follow_with_icon": "{icon} {text}", "ancestor_follow_with_icon": "{icon} {text}",
@ -857,6 +944,11 @@
"pin": "Pin on profile", "pin": "Pin on profile",
"pinned": "Pinned", "pinned": "Pinned",
"plus_more": "+{number} more", "plus_more": "+{number} more",
"redraft": "Delete & redraft",
"redraft_confirm": "Do you really want to delete and redraft this post? Interactions to the original post will not be preserved.",
"redraft_confirm_accept_button": "Yes, delete and redraft",
"redraft_confirm_cancel_button": "No, keep the original",
"redraft_confirm_title": "Confirm delete & redraft",
"remove_attachment": "Remove attachment", "remove_attachment": "Remove attachment",
"repeat_confirm": "Do you really want to repeat this post?", "repeat_confirm": "Do you really want to repeat this post?",
"repeat_confirm_accept_button": "Yes, repeat it", "repeat_confirm_accept_button": "Yes, repeat it",
@ -1032,6 +1124,7 @@
"note": "Private note", "note": "Private note",
"per_day": "per day", "per_day": "per day",
"remote_follow": "Remote follow", "remote_follow": "Remote follow",
"remove_follower": "Remove follower",
"replies": "With Replies", "replies": "With Replies",
"report": "Report", "report": "Report",
"show_repeats": "Show repeats", "show_repeats": "Show repeats",

View file

@ -164,6 +164,74 @@
"load_older": "Chargez d'anciennes interactions", "load_older": "Chargez d'anciennes interactions",
"moves": "Migrations de comptes" "moves": "Migrations de comptes"
}, },
"languages": {
"ar": "arabe",
"az": "azéri",
"bg": "bulgare",
"cs": "tchèque",
"da": "danois",
"de": "allemand",
"el": "grec",
"en": "anglais",
"eo": "espéranto",
"es": "espagnol",
"fa": "persan",
"fi": "finnois",
"fr": "français",
"ga": "irlandais",
"he": "hébreu",
"hi": "hindi",
"hu": "hongrois",
"id": "indonésien",
"it": "italien",
"ja": "japonais",
"ko": "coréen",
"lt": "lituanien",
"lv": "letton",
"nl": "néerlandais",
"pl": "polonais",
"pt": "portugais",
"ru": "russe",
"sk": "slovaque",
"sv": "suédois",
"tr": "turc",
"translated_from": {
"ar": "Traduit de l'@:languages.ar",
"az": "Traduit de l'@:languages.az",
"bg": "Traduit du @:languages.bg",
"cs": "Traduit du @:languages.cs",
"da": "Traduit du @:languages.da",
"de": "Traduit de l'@:languages.de",
"el": "Traduit du @:languages.el",
"en": "Traduit de l'@:languages.en",
"eo": "Traduit de l'@:languages.eo",
"es": "Traduit de l'@:languages.es",
"fa": "Traduit du @:languages.fa",
"fi": "Traduit du @:languages.fi",
"fr": "Traduit du @:languages.fr",
"ga": "Traduit de l'@:languages.ga",
"he": "Traduit de l'@:languages.he",
"hi": "Traduit de l'@:languages.hi",
"hu": "Traduit du @:languages.hu",
"id": "Traduit de l'@:languages.id",
"it": "Traduit de l'@:languages.it",
"ja": "Traduit du @:languages.ja",
"ko": "Traduit du @:languages.ko",
"lt": "Traduit du @:languages.lt",
"lv": "Traduit du @:languages.lv",
"nl": "Traduit du @:languages.nl",
"pl": "Traduit du @:languages.pl",
"pt": "Traduit du @:languages.pt",
"ru": "Traduit du @:languages.ru",
"sk": "Traduit du @:languages.sk",
"sv": "Traduit du @:languages.sv",
"tr": "Traduit du @:languages.tr",
"uk": "Traduit de l'@:languages.uk",
"zh": "Traduit du @:languages.zh"
},
"uk": "ukrainien",
"zh": "chinois"
},
"lists": { "lists": {
"create": "Créer", "create": "Créer",
"delete": "Supprimer la liste", "delete": "Supprimer la liste",
@ -223,7 +291,7 @@
"twkn": "Réseau connu", "twkn": "Réseau connu",
"twkn_timeline_description": "Les status du réseau entier", "twkn_timeline_description": "Les status du réseau entier",
"user_search": "Recherche de comptes", "user_search": "Recherche de comptes",
"who_to_follow": "Suggestion de suivit" "who_to_follow": "Suggestion de suivi"
}, },
"notifications": { "notifications": {
"broken_favorite": "Message inconnu, recherche en cours…", "broken_favorite": "Message inconnu, recherche en cours…",
@ -285,6 +353,7 @@
"direct_warning_to_first_only": "Ce message sera visible uniquement pour personnes mentionnées au début du message.", "direct_warning_to_first_only": "Ce message sera visible uniquement pour personnes mentionnées au début du message.",
"edit_remote_warning": "Les modifications apportées au status pourraient ne pas être visible sur certaines instances !", "edit_remote_warning": "Les modifications apportées au status pourraient ne pas être visible sur certaines instances !",
"edit_status": "Modifier le statut", "edit_status": "Modifier le statut",
"edit_unsupported_warning": "Les sondages et les mentions ne peuvent être modifier.",
"empty_status_error": "Impossible de publier un statut vide sans pièces-jointes", "empty_status_error": "Impossible de publier un statut vide sans pièces-jointes",
"media_description": "Description de la pièce-jointe", "media_description": "Description de la pièce-jointe",
"media_description_error": "Échec de téléversement du media, essayez encore", "media_description_error": "Échec de téléversement du media, essayez encore",
@ -315,7 +384,7 @@
"email": "Courriel", "email": "Courriel",
"email_language": "Dans quelle langue souhaitez-vous recevoir des courriels ?", "email_language": "Dans quelle langue souhaitez-vous recevoir des courriels ?",
"fullname": "Pseudonyme", "fullname": "Pseudonyme",
"fullname_placeholder": "ex. Lain Iwakura", "fullname_placeholder": "ex : Misato Katsuragi",
"new_captcha": "Cliquez sur l'image pour avoir un nouveau captcha", "new_captcha": "Cliquez sur l'image pour avoir un nouveau captcha",
"password_confirm": "Confirmation du mot de passe", "password_confirm": "Confirmation du mot de passe",
"reason": "Motivation d'inscription", "reason": "Motivation d'inscription",
@ -323,7 +392,7 @@
"register": "Enregistrer", "register": "Enregistrer",
"registration": "Inscription", "registration": "Inscription",
"token": "Jeton d'invitation", "token": "Jeton d'invitation",
"username_placeholder": "ex. lain", "username_placeholder": "ex : misato",
"validations": { "validations": {
"email_required": "ne peut pas être laissé vide", "email_required": "ne peut pas être laissé vide",
"fullname_required": "ne peut pas être laissé vide", "fullname_required": "ne peut pas être laissé vide",
@ -361,7 +430,7 @@
"add_backup_error": "Erreur pendant la création d'une nouvelle archive: {error}", "add_backup_error": "Erreur pendant la création d'une nouvelle archive: {error}",
"added_alias": "Alias créé", "added_alias": "Alias créé",
"added_backup": "Archive créée", "added_backup": "Archive créée",
"allow_following_move": "Activer le suivit automatique à la migration des comptes", "allow_following_move": "Activer le suivi automatique à la migration des comptes",
"always_show_post_button": "Toujours afficher le bouton de Nouveau statut", "always_show_post_button": "Toujours afficher le bouton de Nouveau statut",
"app_name": "Nom de l'application", "app_name": "Nom de l'application",
"attachmentRadius": "Pièces jointes", "attachmentRadius": "Pièces jointes",
@ -394,9 +463,19 @@
"changed_password": "Mot de passe modifié avec succès !", "changed_password": "Mot de passe modifié avec succès !",
"chatMessageRadius": "Message de chat", "chatMessageRadius": "Message de chat",
"checkboxRadius": "Cases à cocher", "checkboxRadius": "Cases à cocher",
"collapse_subject": "Réduire les messages avec des sujets", "collapse_subject": "Réduire les messages avec des avertissements",
"columns": "Colonnes",
"composing": "Composition", "composing": "Composition",
"confirm_dialogs": "Demander confirmation :",
"confirm_dialogs_approve_follow": "Accepter une demande de suivi",
"confirm_dialogs_block": "Bloquer un compte",
"confirm_dialogs_delete": "Supprimer un statut",
"confirm_dialogs_deny_follow": "Rejeter une demande de suivi",
"confirm_dialogs_mute": "Masquer un compte",
"confirm_dialogs_repeat": "Partager un statut",
"confirm_dialogs_unfollow": "Désabonner",
"confirm_new_password": "Confirmation du nouveau mot de passe", "confirm_new_password": "Confirmation du nouveau mot de passe",
"confirmation_dialogs": "Options de confirmation",
"conversation_display": "Affichage des fils", "conversation_display": "Affichage des fils",
"conversation_display_linear": "Vue linéaire", "conversation_display_linear": "Vue linéaire",
"conversation_display_tree": "Vue arborescente", "conversation_display_tree": "Vue arborescente",
@ -606,7 +685,7 @@
"security": "Sécurité", "security": "Sécurité",
"security_tab": "Sécurité", "security_tab": "Sécurité",
"sensitive_by_default": "Marquer les messages comme sensible par défaut", "sensitive_by_default": "Marquer les messages comme sensible par défaut",
"sensitive_if_subject": "Automatiquement marquer les images comme sensible quand le statut a un sujet", "sensitive_if_subject": "Automatiquement marquer les images comme sensible quand le statut a un avertissement",
"set_new_avatar": "Changer d'avatar", "set_new_avatar": "Changer d'avatar",
"set_new_mascot": "Changer de mascotte", "set_new_mascot": "Changer de mascotte",
"set_new_profile_background": "Changer d'image de fond", "set_new_profile_background": "Changer d'image de fond",
@ -769,9 +848,9 @@
"use_source": "Nouvelle version" "use_source": "Nouvelle version"
} }
}, },
"subject_input_always_show": "Toujours afficher le champ Sujet", "subject_input_always_show": "Toujours afficher le champ Avertissement",
"subject_line_behavior": "Copier le sujet en répondant", "subject_line_behavior": "Copier l'avertissement en répondant",
"subject_line_email": "Similaire au courriel: « re: sujet »", "subject_line_email": "Similaire au courriel: « re: avertissement »",
"subject_line_mastodon": "Comme mastodon: copier tel quel", "subject_line_mastodon": "Comme mastodon: copier tel quel",
"subject_line_noop": "Ne pas copier", "subject_line_noop": "Ne pas copier",
"text": "Texte", "text": "Texte",
@ -785,7 +864,8 @@
"third_column_mode_postform": "Création de statut et navigation", "third_column_mode_postform": "Création de statut et navigation",
"token": "Jeton", "token": "Jeton",
"tooltipRadius": "Info-bulles/alertes", "tooltipRadius": "Info-bulles/alertes",
"tree_advanced": "Navigation plus flexible en vue arborescente", "translation_language": "Langue cible de la traduction automatique",
"tree_advanced": "Afficher les boutons pour développer et fermer les fils de discussion",
"tree_fade_ancestors": "Afficher les statuts précédents en gris clair", "tree_fade_ancestors": "Afficher les statuts précédents en gris clair",
"type_domains_to_mute": "Chercher les domaines à masquer", "type_domains_to_mute": "Chercher les domaines à masquer",
"upload_a_photo": "Envoyer une photo", "upload_a_photo": "Envoyer une photo",
@ -795,6 +875,7 @@
"use_contain_fit": "Ne pas rogner les miniatures des pièces-jointes", "use_contain_fit": "Ne pas rogner les miniatures des pièces-jointes",
"use_one_click_nsfw": "Ouvrir les pièces-jointes sensibles avec un seul clic", "use_one_click_nsfw": "Ouvrir les pièces-jointes sensibles avec un seul clic",
"user_mutes": "Comptes", "user_mutes": "Comptes",
"user_profile_default_tab": "Onglet affiché par défaut dans les profils",
"user_profiles": "Profils utilisateurs", "user_profiles": "Profils utilisateurs",
"user_settings": "Paramètres utilisateur", "user_settings": "Paramètres utilisateur",
"valid_until": "Valable jusque", "valid_until": "Valable jusque",
@ -820,12 +901,19 @@
"copy_link": "Copier le lien au status", "copy_link": "Copier le lien au status",
"delete": "Supprimer statuts", "delete": "Supprimer statuts",
"delete_confirm": "Voulez-vous vraiment supprimer ce statuts ?", "delete_confirm": "Voulez-vous vraiment supprimer ce statuts ?",
"delete_confirm_accept_button": "Supprimer",
"delete_confirm_cancel_button": "Garder",
"delete_confirm_title": "Confirmer la suppression du statut",
"edit": "Modifier",
"edit_history": "Histoire de modifications",
"edit_history_modal_title": "modifié {historyCount} fois",
"edited_at": "modifié {time}",
"expand": "Développer", "expand": "Développer",
"external_source": "Source externe", "external_source": "Source externe",
"favorites": "Favoris", "favorites": "Favoris",
"hide_attachment": "Masquer la pièce jointe", "hide_attachment": "Masquer la pièce jointe",
"hide_content": "Cacher le contenu", "hide_content": "Cacher le contenu",
"hide_full_subject": "Cacher le sujet", "hide_full_subject": "Cacher l'avertissement",
"many_attachments": "Le statut a {number} pièce jointe | Le statut a {number} pièces jointes", "many_attachments": "Le statut a {number} pièce jointe | Le statut a {number} pièces jointes",
"mentions": "Mentions", "mentions": "Mentions",
"move_down": "Déplacer à droit", "move_down": "Déplacer à droit",
@ -833,13 +921,18 @@
"mute_conversation": "Masquer la conversation", "mute_conversation": "Masquer la conversation",
"nsfw": "Contenu sensible", "nsfw": "Contenu sensible",
"open_gallery": "Afficher la galerie", "open_gallery": "Afficher la galerie",
"override_translation_source_language": "Changer la langue détectée",
"pin": "Agrafer sur le profil", "pin": "Agrafer sur le profil",
"pinned": "Agraffé", "pinned": "Agraffé",
"plus_more": "+{number} autre | +{number} autres", "plus_more": "+{number} autre | +{number} autres",
"remove_attachment": "Supprimer la pièce jointe", "remove_attachment": "Supprimer la pièce jointe",
"repeat_confirm": "Partager ce statut ?",
"repeat_confirm_accept_button": "Partager",
"repeat_confirm_cancel_button": "Annuler",
"repeat_confirm_title": "Confirmer le partage",
"repeats": "Partages", "repeats": "Partages",
"replies_list": "Réponses:", "replies_list": "Réponses:",
"replies_list_with_others": "Réponses (+{numReplies} autre): | Réponses (+{numReplies} autres) :", "replies_list_with_others": "Afficher +{numReplies} réponse | Afficher +{numReplies} réponses",
"reply_to": "Réponse à", "reply_to": "Réponse à",
"show_all_attachments": "Afficher toutes les pièces jointes", "show_all_attachments": "Afficher toutes les pièces jointes",
"show_all_conversation": "Afficher le fils entier ({numStatus} autre statut) | Afficher le fil entier ({numStatus} autres statuts)", "show_all_conversation": "Afficher le fils entier ({numStatus} autre statut) | Afficher le fil entier ({numStatus} autres statuts)",
@ -847,18 +940,20 @@
"show_attachment_description": "Aperçu (ouvrir la pièce joint pour voir la description complète)", "show_attachment_description": "Aperçu (ouvrir la pièce joint pour voir la description complète)",
"show_attachment_in_modal": "Ouvrir dans la visionneuse", "show_attachment_in_modal": "Ouvrir dans la visionneuse",
"show_content": "Montrer le contenu", "show_content": "Montrer le contenu",
"show_full_subject": "Montrer le sujet en entier", "show_full_subject": "Montrer l'avertissement en entier",
"show_only_conversation_under_this": "N'afficher que les réponses a ce statut", "show_only_conversation_under_this": "N'afficher que les réponses a ce statut",
"status_deleted": "Ce post a été effacé", "status_deleted": "Ce post a été effacé",
"status_unavailable": "Status indisponible", "status_unavailable": "Status indisponible",
"thread_follow": "Afficher la partie restante du fil ({numStatus} statut au total) | Afficher la partie restante du fil ({numStatus} statuts au total)", "thread_follow": "Afficher {numStatus} réponse en plus | Afficher {numStatus} réponses en plus",
"thread_follow_with_icon": "{icon} {text}", "thread_follow_with_icon": "{icon} {text}",
"thread_hide": "Masquer ce fil", "thread_hide": "Masquer ce fil",
"thread_muted": "Fil de discussion masqué", "thread_muted": "Fil de discussion masqué",
"thread_muted_and_words": ", contient les mots :", "thread_muted_and_words": ", contient les mots :",
"thread_show": "Afficher ce fil", "thread_show": "Afficher ce fil",
"thread_show_full": "Afficher tout les statuts dans ce fil ({numStatus} au total, profondeur maximale {depth})", "thread_show_full": "Afficher {numStatus} réponse | Afficher les {numStatus} réponses",
"thread_show_full_with_icon": "{icon} {text}", "thread_show_full_with_icon": "{icon} {text}",
"translate": "Traduction",
"translated_from": "Traduit d'une autre langue ({language})",
"unbookmark": "Supprimer des favoris", "unbookmark": "Supprimer des favoris",
"unmute_conversation": "Démasquer la conversation", "unmute_conversation": "Démasquer la conversation",
"unpin": "Dégrafer du profil", "unpin": "Dégrafer du profil",
@ -901,14 +996,17 @@
"socket_reconnected": "Connexion temps-réel établie", "socket_reconnected": "Connexion temps-réel établie",
"up_to_date": "À jour" "up_to_date": "À jour"
}, },
"toast": {
"no_translation_target_set": "Aucune langue cible choisi pour la traduction automatique. Veuillez en choisir une dans les préférences."
},
"tool_tip": { "tool_tip": {
"accept_follow_request": "Accepter la demande de suivit", "accept_follow_request": "Accepter la demande de suivi",
"add_reaction": "Ajouter une réaction", "add_reaction": "Ajouter une réaction",
"bookmark": "Favori", "bookmark": "Favori",
"favorite": "Favoriser", "favorite": "Favoriser",
"media_upload": "Envoyer un media", "media_upload": "Envoyer un media",
"quote": "Citer", "quote": "Citer",
"reject_follow_request": "Rejeter la demande de suivit", "reject_follow_request": "Rejeter la demande de suivi",
"repeat": "Répéter", "repeat": "Répéter",
"reply": "Répondre", "reply": "Répondre",
"user_settings": "Paramètres utilisateur" "user_settings": "Paramètres utilisateur"

View file

@ -164,6 +164,74 @@
"load_older": "古いインタラクションを見る", "load_older": "古いインタラクションを見る",
"moves": "ユーザーの引っ越し" "moves": "ユーザーの引っ越し"
}, },
"languages": {
"ar": "アラビア語",
"az": "アゼルバイジャン語",
"bg": "ブルガリア語",
"cs": "チェコ語",
"da": "デンマーク語",
"de": "ドイツ語",
"el": "ギリシャ語",
"en": "英語",
"eo": "エス語",
"es": "スペイン語",
"fa": "ペルシャ語",
"fi": "フィンランド語",
"fr": "フランス語",
"ga": "アイルランド語",
"he": "ヘブライ語",
"hi": "ヒンディー語",
"hu": "ハンガリー語",
"id": "インドネシア語",
"it": "イタリア語",
"ja": "日本語",
"ko": "韓国語",
"lt": "リトアニア語",
"lv": "ラトビア語",
"nl": "オランダ語",
"pl": "ポーランド語",
"pt": "ポルトガル語",
"ru": "ロシア語",
"sk": "スロバキア語",
"sv": "スウェーデン語",
"tr": "トルコ語",
"translated_from": {
"ar": "アラビア語から翻訳しました",
"az": "アゼルバイジャン語から翻訳しました",
"bg": "ブルガリア語から翻訳しました",
"cs": "チェコ語から翻訳しました",
"da": "デンマーク語から翻訳しました",
"de": "ドイツ語から翻訳しました",
"el": "ギリシャ語から翻訳しました",
"en": "英語から翻訳しました",
"eo": "エス語から翻訳しました",
"es": "スペイン語から翻訳しました",
"fa": "ペルシア語から翻訳しました",
"fi": "フィンランド語から翻訳しました",
"fr": "フランス語から翻訳しました",
"ga": "アイルランド語から翻訳しました",
"he": "ヘブライ語から翻訳しました",
"hi": "ヒンディー語から翻訳しました",
"hu": "ハンガリー語から翻訳しました",
"id": "インドネシア語から翻訳しました",
"it": "イタリア語から翻訳しました",
"ja": "日本語から翻訳しました",
"ko": "韓国語から翻訳しました",
"lt": "リトアニア語から翻訳しました",
"lv": "ラトビア語から翻訳しました",
"nl": "オランダ語から翻訳しました",
"pl": "ポーランド語から翻訳しました",
"pt": "ポルトガル語から翻訳しました",
"ru": "ロシア語から翻訳しました",
"sk": "スロバキア語から翻訳しました",
"sv": "スウェーデン語から翻訳しました",
"tr": "トルコ語から翻訳しました",
"uk": "ウクライナ語から翻訳しました",
"zh": "中国語から翻訳しました"
},
"uk": "ウクライナ語",
"zh": "中国語"
},
"lists": { "lists": {
"create": "作成", "create": "作成",
"delete": "削除", "delete": "削除",
@ -289,7 +357,7 @@
"empty_status_error": "投稿内容を入力してください", "empty_status_error": "投稿内容を入力してください",
"media_description": "メディアの説明", "media_description": "メディアの説明",
"media_description_error": "メディアのアップロードに失敗しました。もう一度お試しください", "media_description_error": "メディアのアップロードに失敗しました。もう一度お試しください",
"media_not_sensitive_warning": "注意: 説明が付けていますがNSFW警告が付けていません", "media_not_sensitive_warning": "注意: 説明が付いていますがNSFWが付いていません",
"new_status": "投稿する", "new_status": "投稿する",
"post": "投稿", "post": "投稿",
"posting": "投稿", "posting": "投稿",
@ -625,6 +693,19 @@
"setting_changed": "規定の設定と異なっています", "setting_changed": "規定の設定と異なっています",
"setting_server_side": "この設定は、全クライエントに適用します", "setting_server_side": "この設定は、全クライエントに適用します",
"settings": "設定", "settings": "設定",
"settings_profile": "設定プロファイル",
"settings_profile_creation": "プロファイル作成",
"settings_profile_creation_new_name_label": "プロファイル名",
"settings_profile_creation_submit": "作成",
"settings_profile_currently": "現在利用されています:{name} (バージョン {version})",
"settings_profile_delete": "削除",
"settings_profile_delete_confirm": "プロファイルを削除しますか?",
"settings_profile_force_sync": "同期する",
"settings_profile_in_use": "利用されています",
"settings_profile_use": "利用",
"settings_profiles_refresh": "再ロード",
"settings_profiles_show": "全プロファイルを表示",
"settings_profiles_unshow": "隠す",
"show_admin_badge": "\"管理者\"のバッジを見せる", "show_admin_badge": "\"管理者\"のバッジを見せる",
"show_moderator_badge": "\"モデレーター\"のバッジを見せる", "show_moderator_badge": "\"モデレーター\"のバッジを見せる",
"show_nav_shortcuts": "ページ上にショートカットを追加", "show_nav_shortcuts": "ページ上にショートカットを追加",
@ -824,6 +905,12 @@
"word_filter": "単語フィルタ", "word_filter": "単語フィルタ",
"wordfilter": "単語フィルター" "wordfilter": "単語フィルター"
}, },
"settings_profile": {
"creating": "新しい設定プロファイル {profile}を作成しています",
"synchronization_error": "同期できませんでした: {err}",
"synchronized": "同期しました!",
"synchronizing": "設定プロファイル 「{profile}」を同期しています"
},
"status": { "status": {
"ancestor_follow": "{numReplies}件の返信を見る", "ancestor_follow": "{numReplies}件の返信を見る",
"ancestor_follow_with_icon": "{icon} {text}", "ancestor_follow_with_icon": "{icon} {text}",
@ -857,6 +944,11 @@
"pin": "プロフィールにピン留め", "pin": "プロフィールにピン留め",
"pinned": "ピン留め", "pinned": "ピン留め",
"plus_more": "ほか{number}件", "plus_more": "ほか{number}件",
"redraft": "削除して編集",
"redraft_confirm": "削除して編集しますか?",
"redraft_confirm_accept_button": "削除して編集",
"redraft_confirm_cancel_button": "キャンセル",
"redraft_confirm_title": "確認してください",
"remove_attachment": "削除", "remove_attachment": "削除",
"repeat_confirm": "リピートしますか?", "repeat_confirm": "リピートしますか?",
"repeat_confirm_accept_button": "リピート", "repeat_confirm_accept_button": "リピート",

View file

@ -164,6 +164,74 @@
"load_older": "Oudere interacties laden", "load_older": "Oudere interacties laden",
"moves": "Gebruikermigraties" "moves": "Gebruikermigraties"
}, },
"languages": {
"ar": "Arabisch",
"az": "Azerbeidzjaans",
"bg": "Bulgaars",
"cs": "Tsjechisch",
"da": "Deens",
"de": "Duits",
"el": "Grieks",
"en": "Engels",
"eo": "Esperanto",
"es": "Spaans",
"fa": "Persisch",
"fi": "Fins",
"fr": "Frans",
"ga": "Iers",
"he": "Hebreeuws",
"hi": "Hindi",
"hu": "Hongaars",
"id": "Indonesisch",
"it": "Italiaans",
"ja": "Japans",
"ko": "Koreaans",
"lt": "Litouws",
"lv": "Lets",
"nl": "Nederlands",
"pl": "Pools",
"pt": "Portugees",
"ru": "Russisch",
"sk": "Slowaaks",
"sv": "Zweeds",
"tr": "Turks",
"translated_from": {
"ar": "Vertaald uit het @:languages.ar",
"az": "Vertaald uit het @:languages.az",
"bg": "Vertaald uit het @:languages.bg",
"cs": "Vertaald uit het @:languages.cs",
"da": "Vertaald uit het @:languages.da",
"de": "Vertaald uit het @:languages.de",
"el": "Vertaald uit het @:languages.el",
"en": "Vertaald uit het @:languages.en",
"eo": "Vertaald uit het @:languages.eo",
"es": "Vertaald uit het @:languages.es",
"fa": "Vertaald uit het @:languages.fa",
"fi": "Vertaald uit het @:languages.fi",
"fr": "Vertaald uit het @:languages.fr",
"ga": "Vertaald uit het @:languages.ga",
"he": "Vertaald uit het @:languages.he",
"hi": "Vertaald uit het @:languages.hi",
"hu": "Vertaald uit het @:languages.hu",
"id": "Vertaald uit het @:languages.id",
"it": "Vertaald uit het @:languages.it",
"ja": "Vertaald uit het @:languages.ja",
"ko": "Vertaald uit het @:languages.ko",
"lt": "Vertaald uit het @:languages.lt",
"lv": "Vertaald uit het @:languages.lv",
"nl": "Vertaald uit het @:languages.nl",
"pl": "Vertaald uit het @:languages.pl",
"pt": "Vertaald uit het @:languages.pt",
"ru": "Vertaald uit het @:languages.ru",
"sk": "Vertaald uit het @:languages.sk",
"sv": "Vertaald uit het @:languages.sv",
"tr": "Vertaald uit het @:languages.tr",
"uk": "Vertaald uit het @:languages.uk",
"zh": "Vertaald uit het @:languages.zh"
},
"uk": "Oekraeens",
"zh": "Chinees"
},
"lists": { "lists": {
"create": "Aanmaken", "create": "Aanmaken",
"delete": "Lijst verwijderen", "delete": "Lijst verwijderen",
@ -279,10 +347,13 @@
"text/plain": "Platte tekst", "text/plain": "Platte tekst",
"text/x.misskeymarkdown": "MFM" "text/x.misskeymarkdown": "MFM"
}, },
"content_warning": "Onderwerp (optioneel)", "content_warning": "Content Waarschuwing (optioneel)",
"default": "Zojuist gearriveerd op de Zweinstein Hogeschool", "default": "Zojuist gearriveerd op de Zweinstein Hogeschool",
"direct_warning_to_all": "Dit bericht zal zichtbaar zijn voor alle vermelde gebruikers.", "direct_warning_to_all": "Dit bericht zal zichtbaar zijn voor alle vermelde gebruikers.",
"direct_warning_to_first_only": "Dit bericht zal alleen zichtbaar zijn voor de vermelde gebruikers aan het begin van het bericht.", "direct_warning_to_first_only": "Dit bericht zal alleen zichtbaar zijn voor de vermelde gebruikers aan het begin van het bericht.",
"edit_remote_warning": "De gemaakte wijzigingen aan het bericht zijn mogelijk niet zichtbaar op sommige instanties!",
"edit_status": "Bericht Aanpassen",
"edit_unsupported_warning": "Peilingen en vermeldingen zullen niet veranderen tijdens het wijzigen.",
"empty_status_error": "Kan geen leeg bericht zonder bijlagen plaatsen", "empty_status_error": "Kan geen leeg bericht zonder bijlagen plaatsen",
"media_description": "Mediaomschrijving", "media_description": "Mediaomschrijving",
"media_description_error": "Kon media niet ophalen, probeer het opnieuw", "media_description_error": "Kon media niet ophalen, probeer het opnieuw",
@ -392,12 +463,14 @@
"changed_password": "Wachtwoord succesvol gewijzigd!", "changed_password": "Wachtwoord succesvol gewijzigd!",
"chatMessageRadius": "Chatbericht", "chatMessageRadius": "Chatbericht",
"checkboxRadius": "Checkboxen", "checkboxRadius": "Checkboxen",
"collapse_subject": "Berichten met een onderwerp inklappen", "collapse_subject": "Berichten met een content waarschuwing inklappen",
"columns": "Kolommen", "columns": "Kolommen",
"composing": "Opstellen", "composing": "Opstellen",
"confirm_dialogs": "Bevestiging vereisen voor:", "confirm_dialogs": "Bevestiging vereisen voor:",
"confirm_dialogs_approve_follow": "Een volgverzoek accepteren",
"confirm_dialogs_block": "Iemand blokkeren", "confirm_dialogs_block": "Iemand blokkeren",
"confirm_dialogs_delete": "Een bericht verwijderen", "confirm_dialogs_delete": "Een bericht verwijderen",
"confirm_dialogs_deny_follow": "Een volgverzoek afwijzen",
"confirm_dialogs_mute": "Iemand negeren", "confirm_dialogs_mute": "Iemand negeren",
"confirm_dialogs_repeat": "Herhalen van een bericht", "confirm_dialogs_repeat": "Herhalen van een bericht",
"confirm_dialogs_unfollow": "Iemand ontvolgen", "confirm_dialogs_unfollow": "Iemand ontvolgen",
@ -612,7 +685,7 @@
"security": "Beveiliging", "security": "Beveiliging",
"security_tab": "Beveiliging", "security_tab": "Beveiliging",
"sensitive_by_default": "Berichten standaard als gevoelig markeren", "sensitive_by_default": "Berichten standaard als gevoelig markeren",
"sensitive_if_subject": "Automatisch afbeeldingen als gevoelig markeren indien een onderwerp opgegeven is", "sensitive_if_subject": "Automatisch afbeeldingen als gevoelig markeren indien een content waarschuwing opgegeven is",
"set_new_avatar": "Nieuwe avatar instellen", "set_new_avatar": "Nieuwe avatar instellen",
"set_new_mascot": "Nieuwe mascotte instellen", "set_new_mascot": "Nieuwe mascotte instellen",
"set_new_profile_background": "Nieuwe profiel achtergrond instellen", "set_new_profile_background": "Nieuwe profiel achtergrond instellen",
@ -708,7 +781,7 @@
"fine_print": "Lees onze {0} om niets nuttig te leren!", "fine_print": "Lees onze {0} om niets nuttig te leren!",
"header": "Voorvertoning", "header": "Voorvertoning",
"header_faint": "Alles komt goed", "header_faint": "Alles komt goed",
"input": "Tijd voor anime!", "input": "Zojuist aangekomen bij Luna Nova Academie",
"link": "een leuke kleine link", "link": "een leuke kleine link",
"mono": "inhoud", "mono": "inhoud",
"text": "Nog een boel andere {0} en {1}" "text": "Nog een boel andere {0} en {1}"
@ -775,9 +848,9 @@
"use_source": "Nieuwe versie" "use_source": "Nieuwe versie"
} }
}, },
"subject_input_always_show": "Altijd onderwerpveld tonen", "subject_input_always_show": "Altijd het contentwaarschuwings-veld tonen",
"subject_line_behavior": "Onderwerp kopiëren bij beantwoorden", "subject_line_behavior": "Content waarschuwing kopiëren bij beantwoorden",
"subject_line_email": "Zoals e-mail: \"re: onderwerp\"", "subject_line_email": "Zoals e-mail: \"re: waarschuwing\"",
"subject_line_mastodon": "Zoals mastodon: kopiëren zoals het is", "subject_line_mastodon": "Zoals mastodon: kopiëren zoals het is",
"subject_line_noop": "Niet kopiëren", "subject_line_noop": "Niet kopiëren",
"text": "Tekst", "text": "Tekst",
@ -791,7 +864,8 @@
"third_column_mode_postform": "Berichtformulier en navigatie", "third_column_mode_postform": "Berichtformulier en navigatie",
"token": "Token", "token": "Token",
"tooltipRadius": "Tooltips/alarmen", "tooltipRadius": "Tooltips/alarmen",
"tree_advanced": "Flexibelere navigatie toestaan in boom weergave", "translation_language": "Taal voor Automatisch Vertalen",
"tree_advanced": "Extra knoppen tonen om antwoorden te openen en sluiten",
"tree_fade_ancestors": "Ouders van huidige bericht met gedempte tekst tonen", "tree_fade_ancestors": "Ouders van huidige bericht met gedempte tekst tonen",
"type_domains_to_mute": "Zoek domeinen om te negeren", "type_domains_to_mute": "Zoek domeinen om te negeren",
"upload_a_photo": "Foto uploaden", "upload_a_photo": "Foto uploaden",
@ -801,6 +875,7 @@
"use_contain_fit": "Bijlage in miniaturen niet bijsnijden", "use_contain_fit": "Bijlage in miniaturen niet bijsnijden",
"use_one_click_nsfw": "Gevoelige bijlagen met slechts één klik openen", "use_one_click_nsfw": "Gevoelige bijlagen met slechts één klik openen",
"user_mutes": "Gebruikers", "user_mutes": "Gebruikers",
"user_profile_default_tab": "Standaard Tabblad op Gebruikersprofiel",
"user_profiles": "Gebruikersprofielen", "user_profiles": "Gebruikersprofielen",
"user_settings": "Gebruikersinstellingen", "user_settings": "Gebruikersinstellingen",
"valid_until": "Geldig tot", "valid_until": "Geldig tot",
@ -826,12 +901,19 @@
"copy_link": "Link naar bericht kopiëren", "copy_link": "Link naar bericht kopiëren",
"delete": "Bericht verwijderen", "delete": "Bericht verwijderen",
"delete_confirm": "Wil je echt dit bericht verwijderen?", "delete_confirm": "Wil je echt dit bericht verwijderen?",
"delete_confirm_accept_button": "Ja, verwijderen",
"delete_confirm_cancel_button": "Nee, houden zoals het is",
"delete_confirm_title": "Verwijderen bevestigen",
"edit": "Wijzigen",
"edit_history": "Historie Wijzigen",
"edit_history_modal_title": "{historyCount} keer gewijzigd | {historyCount} keren gewijzigd",
"edited_at": "Gewijzigd op {time}",
"expand": "Uitvouwen", "expand": "Uitvouwen",
"external_source": "Externe bron", "external_source": "Externe bron",
"favorites": "Favorieten", "favorites": "Favorieten",
"hide_attachment": "Bijlage verbergen", "hide_attachment": "Bijlage verbergen",
"hide_content": "Inhoud verbergen", "hide_content": "Inhoud verbergen",
"hide_full_subject": "Volledig onderwerp verbergen", "hide_full_subject": "Volledige content waarschuwing verbergen",
"many_attachments": "Bericht heeft {number} bijlage | Bericht heeft {number} bijlagen", "many_attachments": "Bericht heeft {number} bijlage | Bericht heeft {number} bijlagen",
"mentions": "Vermeldingen", "mentions": "Vermeldingen",
"move_down": "Bijlage naar rechts schuiven", "move_down": "Bijlage naar rechts schuiven",
@ -839,32 +921,39 @@
"mute_conversation": "Gesprek negeren", "mute_conversation": "Gesprek negeren",
"nsfw": "Gevoelig", "nsfw": "Gevoelig",
"open_gallery": "Gallerij openen", "open_gallery": "Gallerij openen",
"override_translation_source_language": "Bron-taal omzeilen",
"pin": "Aan profiel vastmaken", "pin": "Aan profiel vastmaken",
"pinned": "Vastgezet", "pinned": "Vastgezet",
"plus_more": "+{number} meer", "plus_more": "+{number} meer",
"remove_attachment": "Bijlage verwijderen", "remove_attachment": "Bijlage verwijderen",
"repeat_confirm": "Weet je zeker dat je dit bericht wilt herhalen?",
"repeat_confirm_accept_button": "Ja, herhalen",
"repeat_confirm_cancel_button": "Nee, niet herhalen",
"repeat_confirm_title": "Herhalen bevestigen",
"repeats": "Herhalingen", "repeats": "Herhalingen",
"replies_list": "Antwoorden:", "replies_list": "Antwoorden:",
"replies_list_with_others": "Antwoorden (+{numReplies} andere): | Antwoorden (+{numReplies} anderen):", "replies_list_with_others": "Bekijk {numReplies} meer antwoord | Bekijk {numReplies} meer antwoorden",
"reply_to": "Antwoorden aan", "reply_to": "Antwoorden aan",
"show_all_attachments": "Alle bijlagen tonen", "show_all_attachments": "Alle bijlagen tonen",
"show_all_conversation": "Volledig gesprek tonen ({numStatus} ander bericht) | Volledig gesprek tonen ({numStatus} andere berichten)", "show_all_conversation": "Volledig gesprek tonen ({numStatus} ander bericht) | Volledig gesprek tonen ({numStatus} andere berichten)",
"show_all_conversation_with_icon": "{icon} {text}", "show_all_conversation_with_icon": "{icon} {text}",
"show_attachment_description": "Voorbeeld beschrijving (open bijlage om de volledige beschrijving te zien)", "show_attachment_description": "Voorbeeld beschrijving (open bijlage om de volledige beschrijving te zien)",
"show_attachment_in_modal": "In media venster tonen", "show_attachment_in_modal": "Bijlage in apart venster tonen",
"show_content": "Inhoud tonen", "show_content": "Inhoud tonen",
"show_full_subject": "Volledig onderwerp tonen", "show_full_subject": "Volledige content waarschuwing tonen",
"show_only_conversation_under_this": "Alleen antwoorden op dit bericht tonen", "show_only_conversation_under_this": "Alleen antwoorden op dit bericht tonen",
"status_deleted": "Dit bericht is verwijderd", "status_deleted": "Dit bericht is verwijderd",
"status_unavailable": "Bericht niet beschikbaar", "status_unavailable": "Bericht niet beschikbaar",
"thread_follow": "Rest van gesprek tonen ({numStatus} bericht in totaal) | Rest van gesprek tonen ({numStatus} berichten in totaal)", "thread_follow": "Toon {numStatus} meer antwoord | Toon {numStatus} meer antwoorden",
"thread_follow_with_icon": "{icon} {text}", "thread_follow_with_icon": "{icon} {text}",
"thread_hide": "Gesprek verbergen", "thread_hide": "Gesprek verbergen",
"thread_muted": "Gesprek genegeerd", "thread_muted": "Gesprek genegeerd",
"thread_muted_and_words": ", heeft woorden:", "thread_muted_and_words": ", heeft woorden:",
"thread_show": "Gesprek tonen", "thread_show": "Gesprek tonen",
"thread_show_full": "Alle berichten in dit gesprek tonen ({numStatus} bericht in totaal, max. diepte {depth}) | Alle berichten in dit gesprek tonen ({numStatus} berichten in totaal, max. diepte {depth})", "thread_show_full": "Toon {numStatus} antwoord | Toon {numStatus} antwoorden",
"thread_show_full_with_icon": "{icon} {text}", "thread_show_full_with_icon": "{icon} {text}",
"translate": "Vertalen",
"translated_from": "Vertaald uit het {language}",
"unbookmark": "Bladwijzer verwijderen", "unbookmark": "Bladwijzer verwijderen",
"unmute_conversation": "Gesprek niet meer negeren", "unmute_conversation": "Gesprek niet meer negeren",
"unpin": "Van profiel losmaken", "unpin": "Van profiel losmaken",
@ -907,6 +996,9 @@
"socket_reconnected": "Realtime verbinding opgezet", "socket_reconnected": "Realtime verbinding opgezet",
"up_to_date": "Up-to-date" "up_to_date": "Up-to-date"
}, },
"toast": {
"no_translation_target_set": "Er is geen taal gekozen om naar te vertalen - dit kan fout gaan. Stel een doelwit taal in in je instellingen."
},
"tool_tip": { "tool_tip": {
"accept_follow_request": "Volgverzoek accepteren", "accept_follow_request": "Volgverzoek accepteren",
"add_reaction": "Reactie toevoegen", "add_reaction": "Reactie toevoegen",
@ -955,12 +1047,24 @@
"strip_media": "Media van berichten verwijderen" "strip_media": "Media van berichten verwijderen"
}, },
"approve": "Goedkeuren", "approve": "Goedkeuren",
"approve_confirm": "Weet je zeker dat je deze gebruiker wilt toestaan om je te volgen?",
"approve_confirm_accept_button": "Ja, toestaan",
"approve_confirm_cancel_button": "Nee, weigeren",
"approve_confirm_title": "Volgverzoek toestaan",
"block": "Blokkeren", "block": "Blokkeren",
"block_confirm": "Weet je zeker dat je {user} wilt blokkeren?",
"block_confirm_accept_button": "Ja, blokkeren",
"block_confirm_cancel_button": "Nee, niet blokkeren",
"block_confirm_title": "Gebruiker blokkeren",
"block_progress": "Blokkeren…", "block_progress": "Blokkeren…",
"blocked": "Geblokkeerd!", "blocked": "Geblokkeerd!",
"bot": "Bot", "bot": "Bot",
"deactivated": "Gedeactiveerd", "deactivated": "Gedeactiveerd",
"deny": "Weigeren", "deny": "Weigeren",
"deny_confirm": "Weet je zeker dat je deze gebruiker wilt weigeren om je te volgen?",
"deny_confirm_accept_button": "Ja, weigeren",
"deny_confirm_cancel_button": "Nee, niet weigeren",
"deny_confirm_title": "Volgverzoek weigeren",
"domain_muted": "Domein deblokkeren", "domain_muted": "Domein deblokkeren",
"edit_profile": "Profiel wijzigen", "edit_profile": "Profiel wijzigen",
"favorites": "Favorieten", "favorites": "Favorieten",
@ -986,18 +1090,27 @@
"mention": "Vermelden", "mention": "Vermelden",
"message": "Bericht", "message": "Bericht",
"mute": "Negeren", "mute": "Negeren",
"mute_confirm": "Weet je zeker dat je {user} wil negeren?",
"mute_confirm_accept_button": "Ja, negeren",
"mute_confirm_cancel_button": "Nee, niet negeren",
"mute_confirm_title": "Gebruiker negeren",
"mute_domain": "Domein blokkeren", "mute_domain": "Domein blokkeren",
"mute_progress": "Negeren…", "mute_progress": "Negeren…",
"muted": "Genegeerd", "muted": "Genegeerd",
"note": "Privé notitie", "note": "Privé notitie",
"per_day": "per dag", "per_day": "per dag",
"remote_follow": "Van afstand volgen", "remote_follow": "Van afstand volgen",
"replies": "Met Antwoorden",
"report": "Rapporteren", "report": "Rapporteren",
"show_repeats": "Herhalingen tonen", "show_repeats": "Herhalingen tonen",
"statuses": "Berichten", "statuses": "Berichten",
"subscribe": "Abonneren", "subscribe": "Abonneren",
"unblock": "Blokkeren opheffen", "unblock": "Blokkeren opheffen",
"unblock_progress": "Blokkeren opheffen…", "unblock_progress": "Blokkeren opheffen…",
"unfollow_confirm": "Weet je zeker dat je {user} wil ontvolgen?",
"unfollow_confirm_accept_button": "Ja, ontvolgen",
"unfollow_confirm_cancel_button": "Nee, niet ontvolgen",
"unfollow_confirm_title": "Gebruiker ontvolgen",
"unmute": "Negeren opheffen", "unmute": "Negeren opheffen",
"unmute_progress": "Negeren opheffen…", "unmute_progress": "Negeren opheffen…",
"unsubscribe": "Abonnement opzeggen" "unsubscribe": "Abonnement opzeggen"

View file

@ -3,6 +3,16 @@ import { WSConnectionStatus } from '../services/api/api.service.js'
const retryTimeout = (multiplier) => 1000 * multiplier const retryTimeout = (multiplier) => 1000 * multiplier
const isVisible = (store, message, visibility) => {
if (visibility === 'all') {
return true
} else if (visibility === 'following') {
return store.getters.relationship(message.in_reply_to_user_id).following
} else if (visibility === 'self') {
return message.in_reply_to_user_id === store.rootState.users.currentUser.id
}
return false
}
const api = { const api = {
state: { state: {
retryMultiplier: 1, retryMultiplier: 1,
@ -85,20 +95,21 @@ const api = {
state.mastoUserSocket.addEventListener( state.mastoUserSocket.addEventListener(
'message', 'message',
({ detail: message }) => { ({ detail: message }) => {
const replyVisibility = rootState.config.replyVisibility
if (!message) return // pings if (!message) return // pings
if (message.event === 'notification') { if (message.event === 'notification') {
dispatch('addNewNotifications', { dispatch('addNewNotifications', {
notifications: [message.notification], notifications: [message.notification],
older: false older: false
}) })
} else if (message.event === 'update') { } else if (message.event === 'update' && isVisible(store, message.status, replyVisibility)) {
dispatch('addNewStatuses', { dispatch('addNewStatuses', {
statuses: [message.status], statuses: [message.status],
userId: false, userId: false,
showImmediately: timelineData.visibleStatuses.length === 0, showImmediately: timelineData.visibleStatuses.length === 0,
timeline: 'friends' timeline: 'friends'
}) })
} else if (message.event === 'status.update') { } else if (message.event === 'status.update' && isVisible(store, message.status, replyVisibility)) {
dispatch('addNewStatuses', { dispatch('addNewStatuses', {
statuses: [message.status], statuses: [message.status],
userId: false, userId: false,
@ -200,7 +211,17 @@ const api = {
...rest ...rest
}) })
}, },
startFetchingConfig (store) {
if (store.state.fetchers.config) return
const fetcher = store.state.backendInteractor.startFetchingConfig({ store })
store.commit('addFetcher', { fetcherName: 'config', fetcher })
},
stopFetchingConfig (store) {
const fetcher = store.state.fetchers.config
if (!fetcher) return
store.commit('removeFetcher', { fetcherName: 'config', fetcher })
},
// Notifications // Notifications
startFetchingNotifications (store) { startFetchingNotifications (store) {
if (store.state.fetchers.notifications) return if (store.state.fetchers.notifications) return
@ -262,10 +283,15 @@ const api = {
getSupportedTranslationlanguages (store) { getSupportedTranslationlanguages (store) {
store.state.backendInteractor.getSupportedTranslationlanguages({ store }) store.state.backendInteractor.getSupportedTranslationlanguages({ store })
.then((data) => { .then((data) => {
store.dispatch('setOption', { name: 'supportedTranslationLanguages', value: data }) store.dispatch('setInstanceOption', { name: 'supportedTranslationLanguages', value: data })
})
},
listSettingsProfiles (store) {
store.state.backendInteractor.listSettingsProfiles({ store })
.then((data) => {
store.commit('setInstanceOption', { name: 'settingsProfiles', value: data })
}) })
}, },
// Pleroma websocket // Pleroma websocket
setWsToken (store, token) { setWsToken (store, token) {
store.commit('setWsToken', token) store.commit('setWsToken', token)

View file

@ -21,6 +21,8 @@ export const multiChoiceProperties = [
] ]
export const defaultState = { export const defaultState = {
profile: 'default',
profileVersion: 0,
expertLevel: 0, // used to track which settings to show and hide expertLevel: 0, // used to track which settings to show and hide
colors: {}, colors: {},
theme: undefined, theme: undefined,
@ -72,7 +74,7 @@ export const defaultState = {
highlight: {}, highlight: {},
interfaceLanguage: browserLocale, interfaceLanguage: browserLocale,
hideScopeNotice: false, hideScopeNotice: false,
useStreamingApi: true, useStreamingApi: false,
sidebarRight: undefined, // instance default sidebarRight: undefined, // instance default
scopeCopy: undefined, // instance default scopeCopy: undefined, // instance default
subjectLineBehavior: undefined, // instance default subjectLineBehavior: undefined, // instance default
@ -160,6 +162,42 @@ const config = {
} }
}, },
actions: { actions: {
syncSettings: (store) => {
store.commit('setOption', { name: 'profileVersion', value: store.state.profileVersion + 1 })
const notice = {
level: 'info',
messageKey: 'settings_profile.synchronizing',
messageArgs: { profile: store.state.profile },
timeout: 5000
}
store.dispatch('pushGlobalNotice', notice)
store.rootState.api.backendInteractor.saveSettingsProfile({
settings: store.state, profileName: store.state.profile, version: store.state.profileVersion
}).then(() => {
store.dispatch('removeGlobalNotice', notice)
store.dispatch('pushGlobalNotice', {
level: 'success',
messageKey: 'settings_profile.synchronized',
messageArgs: { profile: store.state.profile },
timeout: 2000
})
store.dispatch('listSettingsProfiles')
}).catch((err) => {
store.dispatch('removeGlobalNotice', notice)
store.dispatch('pushGlobalNotice', {
level: 'error',
messageKey: 'settings_profile.synchronization_error',
messageArgs: { error: err.message },
timeout: 5000
})
console.error(err)
})
},
deleteSettingsProfile (store, name) {
store.rootState.api.backendInteractor.deleteSettingsProfile({ profileName: name }).then(() => {
store.dispatch('listSettingsProfiles')
})
},
loadSettings ({ dispatch }, data) { loadSettings ({ dispatch }, data) {
const knownKeys = new Set(Object.keys(defaultState)) const knownKeys = new Set(Object.keys(defaultState))
const presentKeys = new Set(Object.keys(data)) const presentKeys = new Set(Object.keys(data))
@ -177,8 +215,11 @@ const config = {
setHighlight ({ commit, dispatch }, { user, color, type }) { setHighlight ({ commit, dispatch }, { user, color, type }) {
commit('setHighlight', { user, color, type }) commit('setHighlight', { user, color, type })
}, },
setOption ({ commit, dispatch }, { name, value }) { setOption ({ commit, dispatch }, { name, value, manual }) {
commit('setOption', { name, value }) commit('setOption', { name, value })
if (manual === true) {
dispatch('syncSettings')
}
switch (name) { switch (name) {
case 'theme': case 'theme':
setPreset(value) setPreset(value)
@ -196,6 +237,36 @@ const config = {
dispatch('setLayoutWidth', undefined) dispatch('setLayoutWidth', undefined)
break break
} }
},
getSettingsProfile (store, forceUpdate = false) {
const profile = store.state.profile
store.rootState.api.backendInteractor.getSettingsProfile({ store, profileName: profile })
.then(({ settings, version }) => {
console.log('found settings version', version)
if (forceUpdate || (version > store.state.profileVersion)) {
store.commit('setOption', { name: 'profileVersion', value: version })
Object.entries(settings).forEach(([name, value]) => {
if (store.state[name] !== value) {
store.dispatch('setOption', { name, value })
}
})
} else {
console.log('settings are up to date')
}
})
.catch((err) => {
console.error(`could not fetch profile ${profile}`, err)
if (err.statusCode === 404) {
// create profile
store.dispatch('pushGlobalNotice', {
level: 'warning',
messageKey: 'settings_profile.creating',
messageArgs: { profile },
timeout: 5000
})
store.dispatch('syncSettings')
}
})
} }
} }
} }

View file

@ -3,6 +3,8 @@ import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import apiService from '../services/api/api.service.js' import apiService from '../services/api/api.service.js'
import { instanceDefaultProperties } from './config.js' import { instanceDefaultProperties } from './config.js'
const REMOTE_INTERACTION_URL = '/main/ostatus'
const defaultState = { const defaultState = {
// Stuff from apiConfig // Stuff from apiConfig
name: 'Pleroma FE', name: 'Pleroma FE',
@ -128,6 +130,18 @@ const instance = {
}, },
instanceDomain (state) { instanceDomain (state) {
return new URL(state.server).hostname return new URL(state.server).hostname
},
remoteInteractionLink (state) {
const server = state.server.endsWith('/') ? state.server.slice(0, -1) : state.server
const link = server + REMOTE_INTERACTION_URL
return ({ statusId, nickname }) => {
if (statusId) {
return `${link}?status_id=${statusId}`
} else {
return `${link}?nickname=${nickname}`
}
}
} }
}, },
actions: { actions: {

View file

@ -54,6 +54,11 @@ const unblockUser = (store, id) => {
.then((relationship) => store.commit('updateUserRelationship', [relationship])) .then((relationship) => store.commit('updateUserRelationship', [relationship]))
} }
const removeUserFromFollowers = (store, id) => {
return store.rootState.api.backendInteractor.removeUserFromFollowers({ id })
.then((relationship) => store.commit('updateUserRelationship', [relationship]))
}
const muteUser = (store, id) => { const muteUser = (store, id) => {
const predictedRelationship = store.state.relationships[id] || { id } const predictedRelationship = store.state.relationships[id] || { id }
predictedRelationship.muting = true predictedRelationship.muting = true
@ -317,6 +322,9 @@ const users = {
unblockUser (store, id) { unblockUser (store, id) {
return unblockUser(store, id) return unblockUser(store, id)
}, },
removeUserFromFollowers (store, id) {
return removeUserFromFollowers(store, id)
},
blockUsers (store, ids = []) { blockUsers (store, ids = []) {
return Promise.all(ids.map(id => blockUser(store, id))) return Promise.all(ids.map(id => blockUser(store, id)))
}, },
@ -521,6 +529,7 @@ const users = {
store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken())) store.commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
store.dispatch('stopFetchingNotifications') store.dispatch('stopFetchingNotifications')
store.dispatch('stopFetchingFollowRequests') store.dispatch('stopFetchingFollowRequests')
store.dispatch('stopFetchingConfig')
store.commit('clearNotifications') store.commit('clearNotifications')
store.commit('resetStatuses') store.commit('resetStatuses')
store.dispatch('setLastTimeline', 'public-timeline') store.dispatch('setLastTimeline', 'public-timeline')
@ -581,6 +590,10 @@ const users = {
store.dispatch('setLayoutWidth', windowWidth()) store.dispatch('setLayoutWidth', windowWidth())
store.dispatch('setLayoutHeight', windowHeight()) store.dispatch('setLayoutHeight', windowHeight())
store.dispatch('getSupportedTranslationlanguages')
store.dispatch('getSettingsProfile')
store.dispatch('listSettingsProfiles')
store.dispatch('startFetchingConfig')
// Fetch our friends // Fetch our friends
store.rootState.api.backendInteractor.fetchFriends({ id: user.id }) store.rootState.api.backendInteractor.fetchFriends({ id: user.id })

View file

@ -68,6 +68,7 @@ const MASTODON_BLOCK_USER_URL = id => `/api/v1/accounts/${id}/block`
const MASTODON_UNBLOCK_USER_URL = id => `/api/v1/accounts/${id}/unblock` const MASTODON_UNBLOCK_USER_URL = id => `/api/v1/accounts/${id}/unblock`
const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute` const MASTODON_MUTE_USER_URL = id => `/api/v1/accounts/${id}/mute`
const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute` const MASTODON_UNMUTE_USER_URL = id => `/api/v1/accounts/${id}/unmute`
const MASTODON_REMOVE_USER_FROM_FOLLOWERS = id => `/api/v1/accounts/${id}/remove_from_followers`
const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe` const MASTODON_SUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/subscribe`
const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe` const MASTODON_UNSUBSCRIBE_USER = id => `/api/v1/pleroma/accounts/${id}/unsubscribe`
const MASTODON_SET_NOTE_URL = id => `/api/v1/accounts/${id}/note` const MASTODON_SET_NOTE_URL = id => `/api/v1/accounts/${id}/note`
@ -102,6 +103,8 @@ const PLEROMA_ANNOUNCEMENTS_URL = '/api/v1/pleroma/admin/announcements'
const PLEROMA_POST_ANNOUNCEMENT_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_EDIT_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}` const PLEROMA_DELETE_ANNOUNCEMENT_URL = id => `/api/v1/pleroma/admin/announcements/${id}`
const AKKOMA_SETTING_PROFILE_URL = (name) => `/api/v1/akkoma/frontend_settings/pleroma-fe/${name}`
const AKKOMA_SETTING_PROFILE_LIST = `/api/v1/akkoma/frontend_settings/pleroma-fe`
const oldfetch = window.fetch const oldfetch = window.fetch
@ -303,6 +306,13 @@ const unblockUser = ({ id, credentials }) => {
}).then((data) => data.json()) }).then((data) => data.json())
} }
const removeUserFromFollowers = ({ id, credentials }) => {
return fetch(MASTODON_REMOVE_USER_FROM_FOLLOWERS(id), {
headers: authHeaders(credentials),
method: 'POST'
}).then((data) => data.json())
}
const approveUser = ({ id, credentials }) => { const approveUser = ({ id, credentials }) => {
let url = MASTODON_APPROVE_USER_URL(id) let url = MASTODON_APPROVE_USER_URL(id)
return fetch(url, { return fetch(url, {
@ -1451,6 +1461,40 @@ const deleteAnnouncement = ({ id, credentials }) => {
}) })
} }
const getSettingsProfile = ({ profileName, credentials }) => {
return promisedRequest({
url: AKKOMA_SETTING_PROFILE_URL(profileName),
credentials
})
}
const saveSettingsProfile = ({ profileName, credentials, settings, version }) => {
return promisedRequest({
url: AKKOMA_SETTING_PROFILE_URL(profileName),
method: 'PUT',
credentials,
payload: {
settings,
version
}
})
}
const deleteSettingsProfile = ({ profileName, credentials }) => {
return promisedRequest({
url: AKKOMA_SETTING_PROFILE_URL(profileName),
method: 'DELETE',
credentials
})
}
const listSettingsProfiles = ({ credentials }) => {
return promisedRequest({
url: AKKOMA_SETTING_PROFILE_LIST,
credentials
})
}
export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => { export const getMastodonSocketURI = ({ credentials, stream, args = {} }) => {
return Object.entries({ return Object.entries({
...(credentials ...(credentials
@ -1589,6 +1633,7 @@ const apiService = {
unmuteConversation, unmuteConversation,
blockUser, blockUser,
unblockUser, unblockUser,
removeUserFromFollowers,
fetchUser, fetchUser,
fetchUserRelationship, fetchUserRelationship,
favorite, favorite,
@ -1677,7 +1722,11 @@ const apiService = {
deleteAnnouncement, deleteAnnouncement,
adminFetchAnnouncements, adminFetchAnnouncements,
translateStatus, translateStatus,
getSupportedTranslationlanguages getSupportedTranslationlanguages,
getSettingsProfile,
saveSettingsProfile,
listSettingsProfiles,
deleteSettingsProfile
} }
export default apiService export default apiService

View file

@ -4,6 +4,7 @@ import notificationsFetcher from '../notifications_fetcher/notifications_fetcher
import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service' import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service'
import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js' import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js'
import announcementsFetcher from '../../services/announcements_fetcher/announcements_fetcher.service.js' import announcementsFetcher from '../../services/announcements_fetcher/announcements_fetcher.service.js'
import configFetcher from '../config_fetcher/config_fetcher.service.js'
const backendInteractorService = credentials => ({ const backendInteractorService = credentials => ({
startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) { startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) {
@ -18,6 +19,10 @@ const backendInteractorService = credentials => ({
return notificationsFetcher.startFetching({ store, credentials }) return notificationsFetcher.startFetching({ store, credentials })
}, },
startFetchingConfig ({ store }) {
return configFetcher.startFetching({ store, credentials })
},
fetchNotifications (args) { fetchNotifications (args) {
return notificationsFetcher.fetchAndUpdate({ ...args, credentials }) return notificationsFetcher.fetchAndUpdate({ ...args, credentials })
}, },

View file

@ -0,0 +1,14 @@
import { promiseInterval } from '../promise_interval/promise_interval.js'
const startFetching = ({ credentials, store }) => {
console.log('startFetching: Config')
const boundFetchAndUpdate = () => store.dispatch('getSettingsProfile')
boundFetchAndUpdate()
return promiseInterval(boundFetchAndUpdate, 10 * 60000)
}
const configFetcher = {
startFetching
}
export default configFetcher

3200
yarn.lock

File diff suppressed because it is too large Load diff