Merge branch 'main' into feat--view-transition-api

pull/2211/head
Horváth Bálint 2024-03-17 16:07:35 +01:00 zatwierdzone przez GitHub
commit 2187621f43
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
110 zmienionych plików z 4892 dodań i 1998 usunięć

Wyświetl plik

@ -1,15 +0,0 @@
*.css
*.png
*.ico
*.toml
*.patch
*.txt
Dockerfile
public/
public-dev/
public-staging/
https-dev-config/localhost.crt
https-dev-config/localhost.key
Dockerfile
elk-translation-status.json
docs/translation-status.json

Wyświetl plik

@ -1,19 +0,0 @@
{
"extends": "@antfu",
"ignorePatterns": ["!pages/public"],
"overrides": [
{
"files": ["locales/**.json"],
"rules": {
"jsonc/sort-keys": "error"
}
}
],
"rules": {
"vue/no-restricted-syntax":["error", {
"selector": "VElement[name='a']",
"message": "Use NuxtLink instead."
}],
"n/prefer-global/process": "off"
}
}

Wyświetl plik

@ -2,4 +2,4 @@
name: 🚀 New feature proposal
about: Propose a new feature
labels: 's: pending triage'
---
---

Wyświetl plik

@ -21,7 +21,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 20
cache: pnpm
- name: 📦 Install dependencies

45
.vscode/settings.json vendored
Wyświetl plik

@ -5,10 +5,6 @@
"unmute",
"unstorage"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": false,
"files.associations": {
"*.css": "postcss"
},
@ -23,7 +19,44 @@
"i18n-ally.preferredDelimiter": "_",
"i18n-ally.sortKeys": true,
"i18n-ally.sourceLanguage": "en",
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
// Disable the default formatter, use eslint instead
"prettier.enable": false,
"volar.completion.preferredTagNameCase": "pascal",
"volar.completion.preferredAttrNameCase": "kebab"
"editor.formatOnSave": false,
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "never"
},
// Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [
{ "rule": "style/*", "severity": "off" },
{ "rule": "*-indent", "severity": "off" },
{ "rule": "*-spacing", "severity": "off" },
{ "rule": "*-spaces", "severity": "off" },
{ "rule": "*-order", "severity": "off" },
{ "rule": "*-dangle", "severity": "off" },
{ "rule": "*-newline", "severity": "off" },
{ "rule": "*quotes", "severity": "off" },
{ "rule": "*semi", "severity": "off" }
],
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml"
]
}

Wyświetl plik

@ -8,7 +8,7 @@ For guidelines on contributing to the documentation, refer to the [docs README](
### Online
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
[![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https://pr.new/elk-zone/elk)
@ -21,7 +21,6 @@ To develop and test the Elk package:
2. Ensure using the latest Node.js (16.x).
If you have [nvm](https://github.com/nvm-sh/nvm), you can run `nvm i` to install the required version.
3. The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/) v7. To use it you must first enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`. (Note: on Linux in a standard Node 16+ environment, you should follow the instructions to install via Node's `corepack` rather than using the `curl` command)
4. Check out a branch where you can work and commit your changes:

Wyświetl plik

@ -39,8 +39,8 @@ The Elk team maintains a deployment at:
### Self-Host Docker Deployment
In order to host Elk yourself you can use the provided Dockerfile to build a container with elk. Be aware, that Elk only loads properly if the connection is done via SSL/TLS. The Docker container itself does not provide any SSL/TLS handling. You'll have to add this bit yourself.
One could put Elk behind popular reverse proxies with SSL Handling like Traefik, NGINX etc.
In order to host Elk yourself you can use the provided Dockerfile to build a container with elk. Be aware, that Elk only loads properly if the connection is done via SSL/TLS. The Docker container itself does not provide any SSL/TLS handling. You'll have to add this bit yourself.
One could put Elk behind popular reverse proxies with SSL Handling like Traefik, NGINX etc.
1. checkout source ```git clone https://github.com/elk-zone/elk.git```
1. got into new source dir: ```cd elk```
@ -52,7 +52,6 @@ One could put Elk behind popular reverse proxies with SSL Handling like Traefik,
> [!NOTE]
> The provided Dockerfile creates a container which will eventually run Elk as non-root user and create a persistent named Docker volume upon first start (if that volume does not yet exist). This volume is always created with root permission. Failing to change the permissions of ```/elk/data``` inside this volume to UID:GID 911 (as specified for Elk in the Dockerfile) will prevent Elk from storing it's config for user accounts. You either have to fix the permission in the created named volume, or mount a directory with the correct permission to ```/elk/data``` into the container.
### Ecosystem
These are known deployments using Elk as an alternative Web client for Mastodon servers or as a base for other projects in the fediverse:
@ -107,7 +106,7 @@ We're really excited that you're interested in contributing to Elk! Before submi
### Online
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
[![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https://pr.new/elk-zone/elk)
@ -158,8 +157,8 @@ You can consult the [PWA documentation](https://docs.elk.zone/pwa) to learn more
## 👨‍💻 Contributors
<a href="https://github.com/elk-zone/elk/graphs/contributors">
<img src="https://contrib.rocks/image?repo=elk-zone/elk" />
</a>
<img src="https://contrib.rocks/image?repo=elk-zone/elk" />
</a>
## 📄 License

Wyświetl plik

@ -13,6 +13,7 @@ const { t } = useI18n()
const isSelf = useSelfAccount(() => account)
const enable = computed(() => !isSelf.value && currentUser.value)
const relationship = computed(() => props.relationship || useRelationship(account).value)
const isLoading = computed(() => relationship.value === undefined)
const { client } = useMasto()
@ -62,6 +63,10 @@ const buttonStyle = computed(() => {
if (relationship.value ? relationship.value.following : context === 'following')
return `text-base ${relationship.value?.followedBy ? 'border-strong' : 'border-base'}`
// If loading, use a plain style
if (isLoading.value)
return 'text-base border-base'
// If not following, use a button style
return 'text-inverted bg-primary border-primary'
})
@ -77,28 +82,33 @@ const buttonStyle = computed(() => {
:hover="!relationship?.blocking && !relationship?.muting && relationship?.following ? 'border-red text-red' : 'bg-base border-primary text-primary'"
@click="relationship?.blocking ? unblock() : relationship?.muting ? unmute() : toggleFollowAccount(relationship!, account)"
>
<template v-if="relationship?.blocking">
<span elk-group-hover="hidden">{{ $t('account.blocking') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unblock') }}</span>
</template>
<template v-if="relationship?.muting">
<span elk-group-hover="hidden">{{ $t('account.muting') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unmute') }}</span>
</template>
<template v-else-if="relationship ? relationship.following : context === 'following'">
<span elk-group-hover="hidden">{{ relationship?.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unfollow') }}</span>
</template>
<template v-else-if="relationship?.requested">
<span elk-group-hover="hidden">{{ $t('account.follow_requested') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.withdraw_follow_request') }}</span>
</template>
<template v-else-if="relationship ? relationship.followedBy : context === 'followedBy'">
<span elk-group-hover="hidden">{{ $t('account.follows_you') }}</span>
<span hidden elk-group-hover="inline">{{ account.locked ? $t('account.request_follow') : $t('account.follow_back') }}</span>
<template v-if="isLoading">
<span i-svg-spinners-180-ring-with-bg />
</template>
<template v-else>
<span>{{ account.locked ? $t('account.request_follow') : $t('account.follow') }}</span>
<template v-if="relationship?.blocking">
<span elk-group-hover="hidden">{{ $t('account.blocking') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unblock') }}</span>
</template>
<template v-if="relationship?.muting">
<span elk-group-hover="hidden">{{ $t('account.muting') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unmute') }}</span>
</template>
<template v-else-if="relationship ? relationship.following : context === 'following'">
<span elk-group-hover="hidden">{{ relationship?.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unfollow') }}</span>
</template>
<template v-else-if="relationship?.requested">
<span elk-group-hover="hidden">{{ $t('account.follow_requested') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.withdraw_follow_request') }}</span>
</template>
<template v-else-if="relationship ? relationship.followedBy : context === 'followedBy'">
<span elk-group-hover="hidden">{{ $t('account.follows_you') }}</span>
<span hidden elk-group-hover="inline">{{ account.locked ? $t('account.request_follow') : $t('account.follow_back') }}</span>
</template>
<template v-else>
<span>{{ account.locked ? $t('account.request_follow') : $t('account.follow') }}</span>
</template>
</template>
</button>
</template>

Wyświetl plik

@ -2,39 +2,33 @@
import type { mastodon } from 'masto'
import { fetchAccountByHandle } from '~/composables/cache'
type WatcherType = [acc?: mastodon.v1.Account, h?: string, v?: boolean]
type WatcherType = [acc?: mastodon.v1.Account | null, h?: string, v?: boolean]
defineOptions({
inheritAttrs: false,
})
const props = defineProps<{
account?: mastodon.v1.Account
account?: mastodon.v1.Account | null
handle?: string
disabled?: boolean
}>()
const hoverCard = ref()
const targetIsVisible = ref(false)
const accountHover = ref()
const hovered = useElementHover(accountHover)
const account = ref<mastodon.v1.Account | null | undefined>(props.account)
useIntersectionObserver(
hoverCard,
([{ intersectionRatio }]) => {
targetIsVisible.value = intersectionRatio > 0.1
},
)
watch(
() => [props.account, props.handle, targetIsVisible.value] satisfies WatcherType,
() => [props.account, props.handle, hovered.value] satisfies WatcherType,
([newAccount, newHandle, newVisible], oldProps) => {
if (!newVisible || process.test)
return
if (newAccount) {
account.value = newAccount
return
}
if (!newVisible || process.test)
return
if (newHandle) {
const [_oldAccount, oldHandle, _oldVisible] = oldProps ?? [undefined, undefined, false]
if (!oldHandle || newHandle !== oldHandle || !account.value) {
@ -49,15 +43,22 @@ watch(
}
account.value = undefined
}, { immediate: true, flush: 'post' },
},
{ immediate: true, flush: 'post' },
)
const userSettings = useUserSettings()
</script>
<template>
<span ref="hoverCard">
<VMenu v-if="!disabled && account && !getPreferences(userSettings, 'hideAccountHoverCard')" placement="bottom-start" :delay="{ show: 500, hide: 100 }" v-bind="$attrs" :close-on-content-click="false">
<span ref="accountHover">
<VMenu
v-if="!disabled && account && !getPreferences(userSettings, 'hideAccountHoverCard')"
placement="bottom-start"
:delay="{ show: 500, hide: 100 }"
v-bind="$attrs"
:close-on-content-click="false"
>
<slot />
<template #popper>
<AccountHoverCard v-if="account" :account="account" />

Wyświetl plik

@ -25,13 +25,16 @@ function shareAccount() {
}
async function toggleReblogs() {
if (!relationship.value!.showingReblogs && await openConfirmDialog({
title: t('confirm.show_reblogs.title'),
description: t('confirm.show_reblogs.description', [account.acct]),
confirm: t('confirm.show_reblogs.confirm'),
cancel: t('confirm.show_reblogs.cancel'),
}) !== 'confirm')
return
if (!relationship.value!.showingReblogs) {
const dialogChoice = await openConfirmDialog({
title: t('confirm.show_reblogs.title'),
description: t('confirm.show_reblogs.description', [account.acct]),
confirm: t('confirm.show_reblogs.confirm'),
cancel: t('confirm.show_reblogs.cancel'),
})
if (dialogChoice.choice !== 'confirm')
return
}
const showingReblogs = !relationship.value?.showingReblogs
relationship.value = await client.value.v1.accounts.$select(account.id).follow({ reblogs: showingReblogs })

Wyświetl plik

@ -0,0 +1,45 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
defineOptions({
inheritAttrs: false,
})
const { tagName, disabled } = defineProps<{
tagName?: string
disabled?: boolean
}>()
const tag = ref<mastodon.v1.Tag>()
const tagHover = ref()
const hovered = useElementHover(tagHover)
watch(hovered, (newHovered) => {
if (newHovered && tagName) {
fetchTag(tagName).then((t) => {
tag.value = t
})
}
})
const userSettings = useUserSettings()
</script>
<template>
<span ref="tagHover">
<VMenu
v-if="!disabled && !getPreferences(userSettings, 'hideTagHoverCard')"
placement="bottom-start"
:delay="{ show: 500, hide: 100 }"
v-bind="$attrs"
:close-on-content-click="false"
>
<slot />
<template #popper>
<TagCardSkeleton v-if="!tag" />
<TagCard v-else :tag="tag" />
</template>
</VMenu>
<slot v-else />
</span>
</template>

Wyświetl plik

@ -22,7 +22,7 @@ onMounted(() => {
const commandMode = computed(() => input.value.startsWith('>'))
const query = computed(() => commandMode ? '' : input.value.trim())
const query = computed(() => commandMode.value ? '' : input.value.trim())
const { accounts, hashtags, loading } = useSearch(query)
@ -61,7 +61,7 @@ const searchResult = computed<QueryResult>(() => {
}
})
const result = computed<QueryResult>(() => commandMode
const result = computed<QueryResult>(() => commandMode.value
? registry.query(scopes.value.map(s => s.id).join('.'), input.value.slice(1).trim())
: searchResult.value,
)

Wyświetl plik

@ -4,6 +4,8 @@ defineProps<{
hover?: boolean
iconChecked?: string
iconUnchecked?: string
checkedIconColor?: string
prependCheckbox?: boolean
}>()
const modelValue = defineModel<boolean | null>()
</script>
@ -15,9 +17,12 @@ const modelValue = defineModel<boolean | null>()
v-bind="$attrs"
@click.prevent="modelValue = !modelValue"
>
<span v-if="label" flex-1 ms-2 pointer-events-none>{{ label }}</span>
<span v-if="label && !prependCheckbox" flex-1 ms-2 pointer-events-none>{{ label }}</span>
<span
:class="modelValue ? (iconChecked ?? 'i-ri:checkbox-line') : (iconUnchecked ?? 'i-ri:checkbox-blank-line')"
:class="[
modelValue ? (iconChecked ?? 'i-ri:checkbox-line') : (iconUnchecked ?? 'i-ri:checkbox-blank-line'),
modelValue && checkedIconColor,
]"
text-lg
aria-hidden="true"
/>
@ -26,6 +31,7 @@ const modelValue = defineModel<boolean | null>()
type="checkbox"
sr-only
>
<span v-if="label && prependCheckbox" flex-1 ms-2 pointer-events-none>{{ label }}</span>
</label>
</template>

Wyświetl plik

@ -1,5 +1,9 @@
<script setup lang="ts">
const { as = 'div', active } = defineProps<{ as: any; active: boolean }>()
const { as = 'div', active } = defineProps<{
as: any
active: boolean
}>()
const el = ref()
watch(() => active, (active) => {

Wyświetl plik

@ -68,7 +68,7 @@ async function removeList() {
actionError.value = undefined
await nextTick()
if (confirmDelete === 'confirm') {
if (confirmDelete.choice === 'confirm') {
await nextTick()
try {
await client.v1.lists.$select(list.value.id).remove()
@ -92,7 +92,7 @@ async function removeList() {
async function clearError() {
actionError.value = undefined
await nextTick()
if (isEditing)
if (isEditing.value)
input.value?.focus()
else
deleteBtn.value?.focus()

Wyświetl plik

@ -0,0 +1,45 @@
<script setup lang="ts">
const model = defineModel<number>()
const isValid = defineModel<boolean>('isValid')
const days = ref<number | ''>(0)
const hours = ref<number | ''>(1)
const minutes = ref<number | ''>(0)
watchEffect(() => {
if (days.value === '' || hours.value === '' || minutes.value === '') {
isValid.value = false
return
}
const duration
= days.value * 24 * 60 * 60
+ hours.value * 60 * 60
+ minutes.value * 60
if (duration <= 0) {
isValid.value = false
return
}
isValid.value = true
model.value = duration
})
</script>
<template>
<div flex flex-grow-0 gap-2>
<label flex items-center gap-2>
<input v-model="days" type="number" min="0" max="1999" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.days', days === '' ? 0 : days) }}
</label>
<label flex items-center gap-2>
<input v-model="hours" type="number" min="0" max="24" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.hours', hours === '' ? 0 : hours) }}
</label>
<label flex items-center gap-2>
<input v-model="minutes" type="number" min="0" max="59" step="5" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.minute', minutes === '' ? 0 : minutes) }}
</label>
</div>
</template>

Wyświetl plik

@ -1,11 +1,34 @@
<script setup lang="ts">
import type { ConfirmDialogChoice, ConfirmDialogLabel } from '~/types'
import type { ConfirmDialogChoice, ConfirmDialogOptions } from '~/types'
import DurationPicker from '~/components/modal/DurationPicker.vue'
defineProps<ConfirmDialogLabel>()
const props = defineProps<ConfirmDialogOptions>()
const emit = defineEmits<{
(evt: 'choice', choice: ConfirmDialogChoice): void
}>()
const hasDuration = ref(false)
const isValidDuration = ref(true)
const duration = ref(60 * 60) // default to 1 hour
const shouldMuteNotifications = ref(true)
const isMute = computed(() => props.extraOptionType === 'mute')
function handleChoice(choice: ConfirmDialogChoice['choice']) {
const dialogChoice = {
choice,
...isMute.value && {
extraOptions: {
mute: {
duration: hasDuration.value ? duration.value : 0,
notifications: shouldMuteNotifications.value,
},
},
},
}
emit('choice', dialogChoice)
}
</script>
<template>
@ -16,11 +39,17 @@ const emit = defineEmits<{
<div v-if="description">
{{ description }}
</div>
<div v-if="isMute" flex-col flex gap-4>
<CommonCheckbox v-model="hasDuration" :label="$t('confirm.mute_account.specify_duration')" prepend-checkbox checked-icon-color="text-primary" />
<DurationPicker v-if="hasDuration" v-model="duration" v-model:is-valid="isValidDuration" />
<CommonCheckbox v-model="shouldMuteNotifications" :label="$t('confirm.mute_account.notifications')" prepend-checkbox checked-icon-color="text-primary" />
</div>
<div flex justify-end gap-2>
<button btn-text @click="emit('choice', 'cancel')">
<button btn-text @click="handleChoice('cancel')">
{{ cancel || $t('confirm.common.cancel') }}
</button>
<button btn-solid @click="emit('choice', 'confirm')">
<button btn-solid :disabled="!isValidDuration" @click="handleChoice('confirm')">
{{ confirm || $t('confirm.common.confirm') }}
</button>
</div>

Wyświetl plik

@ -1,8 +1,12 @@
<script setup lang="ts">
// only one icon can be lit up at the same time
import { STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE } from '~/constants'
const moreMenuVisible = ref(false)
const { notifications } = useNotifications()
const lastAccessedNotificationRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE, '')
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
</script>
<template>
@ -19,7 +23,7 @@ const { notifications } = useNotifications()
<NuxtLink to="/search" :aria-label="$t('nav.search')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:search-line />
</NuxtLink>
<NuxtLink to="/notifications" :aria-label="$t('nav.notifications')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<NuxtLink :to="`/notifications/${lastAccessedNotificationRoute}`" :aria-label="$t('nav.notifications')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div flex relative>
<div class="i-ri:notification-4-line" text-xl />
<div v-if="notifications" class="top-[-0.3rem] right-[-0.3rem]" absolute font-bold rounded-full h-4 w-4 text-xs bg-primary text-inverted flex items-center justify-center>
@ -32,8 +36,8 @@ const { notifications } = useNotifications()
</NuxtLink>
</template>
<template v-else>
<NuxtLink :to="`/${currentServer}/explore`" :aria-label="$t('nav.explore')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:hashtag />
<NuxtLink :to="`/${currentServer}/explore/${lastAccessedExploreRoute}`" :aria-label="$t('nav.explore')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:compass-3-line />
</NuxtLink>
<NuxtLink group :to="`/${currentServer}/public/local`" :aria-label="$t('nav.local')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:group-2-line />

Wyświetl plik

@ -1,9 +1,13 @@
<script setup lang="ts">
import { STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE } from '~/constants'
const { command } = defineProps<{
command?: boolean
}>()
const { notifications } = useNotifications()
const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')
const lastAccessedNotificationRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE, '')
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
</script>
<template>
@ -12,7 +16,7 @@ const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')
<div class="spacer" shrink xl:hidden />
<NavSideItem :text="$t('nav.home')" to="/home" icon="i-ri:home-5-line" user-only :command="command" />
<NavSideItem :text="$t('nav.notifications')" to="/notifications" icon="i-ri:notification-4-line" user-only :command="command">
<NavSideItem :text="$t('nav.notifications')" :to="`/notifications/${lastAccessedNotificationRoute}`" icon="i-ri:notification-4-line" user-only :command="command">
<template #icon>
<div flex relative>
<div class="i-ri:notification-4-line" text-xl />
@ -30,10 +34,11 @@ const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')
<NavSideItem :text="$t('action.compose')" to="/compose" icon="i-ri:quill-pen-line" user-only :command="command" />
<div class="spacer" shrink hidden sm:block />
<NavSideItem :text="$t('nav.explore')" :to="isHydrated ? `/${currentServer}/explore` : '/explore'" icon="i-ri:hashtag" :command="command" />
<NavSideItem :text="$t('nav.explore')" :to="isHydrated ? `/${currentServer}/explore/${lastAccessedExploreRoute}` : `/explore/${lastAccessedExploreRoute}`" icon="i-ri:compass-3-line" :command="command" />
<NavSideItem :text="$t('nav.local')" :to="isHydrated ? `/${currentServer}/public/local` : '/public/local'" icon="i-ri:group-2-line " :command="command" />
<NavSideItem :text="$t('nav.federated')" :to="isHydrated ? `/${currentServer}/public` : '/public'" icon="i-ri:earth-line" :command="command" />
<NavSideItem :text="$t('nav.lists')" :to="isHydrated ? `/${currentServer}/lists` : '/lists'" icon="i-ri:list-check" user-only :command="command" />
<NavSideItem :text="$t('nav.hashtags')" to="/hashtags" icon="i-ri:hashtag" user-only :command="command" />
<div class="spacer" shrink hidden sm:block />
<NavSideItem :text="$t('nav.settings')" to="/settings" icon="i-ri:settings-3-line" :command="command" />

Wyświetl plik

@ -57,11 +57,21 @@ const noUserVisual = computed(() => isHydrated.value && props.userOnly && !curre
<div
class="item"
flex items-center gap4
w-fit rounded-3
px2 mx3 sm:mxa
xl="ml0 mr5 px5 w-auto"
transition-100
elk-group-hover="bg-active" group-focus-visible:ring="2 current"
:class="isSmallScreen
? `
w-full
px5 sm:mxa
transition-colors duration-200 transform
hover-bg-gray-100 hover-dark:(bg-gray-700 text-white)
` : `
w-fit rounded-3
px2 mx3 sm:mxa
transition-100
elk-group-hover-bg-active
group-focus-visible:ring-2
group-focus-visible:ring-current
`"
>
<slot name="icon">
<div :class="icon" text-xl />

Wyświetl plik

@ -35,8 +35,8 @@ const showWarning = computed(() => {
return false
return isSupported
&& (!isSubscribed.value || !notificationPermission.value || notificationPermission.value === 'prompt')
&& !(hiddenNotification.value[currentUser.value?.account?.acct ?? ''] === true)
&& (!isSubscribed.value || !notificationPermission.value || notificationPermission.value === 'prompt')
&& !(hiddenNotification.value[currentUser.value?.account?.acct ?? ''])
})
async function saveSettings() {

Wyświetl plik

@ -30,8 +30,14 @@ const draftState = useDraft(draftKey, initial)
const { draft } = draftState
const {
isExceedingAttachmentLimit, isUploading, failedAttachments, isOverDropZone,
uploadAttachments, pickAttachments, setDescription, removeAttachment,
isExceedingAttachmentLimit,
isUploading,
failedAttachments,
isOverDropZone,
uploadAttachments,
pickAttachments,
setDescription,
removeAttachment,
dropZoneRef,
} = useUploadMediaAttachment(draft)
@ -68,7 +74,7 @@ function trimPollOptions() {
const trimmedOptions = draft.value.params.poll!.options.slice(0, indexLastNonEmpty + 1)
if (currentInstance.value?.configuration
&& trimmedOptions.length >= currentInstance.value?.configuration?.polls.maxOptions)
&& trimmedOptions.length >= currentInstance.value?.configuration?.polls.maxOptions)
draft.value.params.poll!.options = trimmedOptions
else
draft.value.params.poll!.options = [...trimmedOptions, '']
@ -132,7 +138,7 @@ const characterCount = computed(() => {
length -= fullMatch.length - (before + username).length - 1 // - 1 for the @
if (draft.value.mentions) {
// + 1 is needed as mentions always need a space seperator at the end
// + 1 is needed as mentions always need a space separator at the end
length += draft.value.mentions.map((mention) => {
const [handle] = mention.split('@')
return `@${handle}`

Wyświetl plik

@ -18,12 +18,12 @@ useCommand({
scope: 'Settings',
name: () => props.text
?? (props.to
? typeof props.to === 'string'
? props.to
: props.to.name
: ''
),
?? (props.to
? typeof props.to === 'string'
? props.to
: props.to.name
: ''
),
description: () => props.description,
icon: () => props.icon || '',
visible: () => props.command && props.to,

Wyświetl plik

@ -8,8 +8,7 @@ const dropdown = ref<any>()
const fieldIcons = computed(() =>
Array.from({ length: maxAccountFieldCount.value }, (_, i) =>
getAccountFieldIcon(form.value.fieldsAttributes[i].name),
),
getAccountFieldIcon(form.value.fieldsAttributes[i].name)),
)
const fieldCount = computed(() => {

Wyświetl plik

@ -62,12 +62,13 @@ async function shareLink(status: mastodon.v1.Status) {
}
async function deleteStatus() {
if (await openConfirmDialog({
const confirmDelete = await openConfirmDialog({
title: t('confirm.delete_posts.title'),
description: t('confirm.delete_posts.description'),
confirm: t('confirm.delete_posts.confirm'),
cancel: t('confirm.delete_posts.cancel'),
}) !== 'confirm')
})
if (confirmDelete.choice !== 'confirm')
return
removeCachedStatus(status.value.id)
@ -80,12 +81,13 @@ async function deleteStatus() {
}
async function deleteAndRedraft() {
if (await openConfirmDialog({
const confirmDelete = await openConfirmDialog({
title: t('confirm.delete_posts.title'),
description: t('confirm.delete_posts.description'),
confirm: t('confirm.delete_posts.confirm'),
cancel: t('confirm.delete_posts.cancel'),
}) !== 'confirm')
})
if (confirmDelete.choice !== 'confirm')
return
if (import.meta.dev) {

Wyświetl plik

@ -32,7 +32,7 @@ const hideAllMedia = computed(
const viewTransitionStyle = getViewTransitionStyles('status-content')
const embeddedMediaPreference = usePreferences('experimentalEmbeddedMedia')
const allowEmbeddedMedia = computed(() => status.card?.html && embeddedMediaPreference)
const allowEmbeddedMedia = computed(() => status.card?.html && embeddedMediaPreference.value)
</script>
<template>

Wyświetl plik

@ -1,21 +1,56 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
import { fetchAccountById } from '~/composables/cache'
const {
status,
isSelfReply = false,
} = defineProps<{
type WatcherType = [status?: mastodon.v1.Status, v?: boolean]
const props = defineProps<{
status: mastodon.v1.Status
isSelfReply: boolean
}>()
const isSelf = computed(() => status.inReplyToAccountId === status.account.id)
const account = isSelf.value ? computed(() => status.account) : useAccountById(status.inReplyToAccountId)
const link = ref()
const targetIsVisible = ref(false)
const isSelf = computed(() => props.status.inReplyToAccountId === props.status.account.id)
const account = ref<mastodon.v1.Account | null | undefined>(isSelf.value ? props.status.account : undefined)
useIntersectionObserver(
link,
([{ intersectionRatio }]) => {
targetIsVisible.value = intersectionRatio > 0.1
},
)
watch(
() => [props.status, targetIsVisible.value] satisfies WatcherType,
([newStatus, newVisible]) => {
if (newStatus.account && newStatus.inReplyToAccountId === newStatus.account.id) {
account.value = newStatus.account
return
}
if (!newVisible)
return
const newId = newStatus.inReplyToAccountId
if (newId) {
fetchAccountById(newStatus.inReplyToAccountId).then((acc) => {
if (newId === props.status.inReplyToAccountId)
account.value = acc
})
return
}
account.value = undefined
},
{ immediate: true, flush: 'post' },
)
</script>
<template>
<NuxtLink
v-if="status.inReplyToId"
ref="link"
flex="~ gap2" items-center h-auto text-sm text-secondary
:to="getStatusInReplyToRoute(status)"
:title="$t('status.replying_to', [account ? getDisplayName(account) : $t('status.someone')])"

Wyświetl plik

@ -1,5 +1,10 @@
<script setup lang="ts">
const props = defineProps<{ enabled?: boolean; filter?: boolean; isDM?: boolean; sensitiveNonSpoiler?: boolean }>()
const props = defineProps<{
enabled?: boolean
filter?: boolean
isDM?: boolean
sensitiveNonSpoiler?: boolean
}>()
const expandSpoilers = computed(() => {
const expandCW = currentUser.value ? getExpandSpoilersByDefault(currentUser.value.account) : false

Wyświetl plik

@ -1,9 +1,7 @@
<script lang="ts" setup>
<script setup lang="ts">
import type { mastodon } from 'masto'
const {
tag,
} = defineProps<{
const { tag } = defineProps<{
tag: mastodon.v1.Tag
}>()
@ -32,19 +30,21 @@ function go(evt: MouseEvent | KeyboardEvent) {
<template>
<div
block p4 hover:bg-active flex justify-between cursor-pointer
block p4 hover:bg-active flex justify-between cursor-pointer flex-gap-2
@click="onclick"
@keydown.enter="onclick"
>
<div>
<h4 flex items-center text-size-base leading-normal font-medium line-clamp-1 break-all ws-pre-wrap>
<TagActionButton :tag="tag" />
<bdi>
<span>#</span>
<span hover:underline>{{ tag.name }}</span>
</bdi>
</h4>
<CommonTrending v-if="tag.history" :history="tag.history" text-sm text-secondary line-clamp-1 ws-pre-wrap break-all />
<div flex flex-gap-2>
<TagActionButton :tag="tag" />
<div>
<h4 flex items-center text-size-base leading-normal font-medium line-clamp-1 break-all ws-pre-wrap>
<bdi>
<span>#</span>
<span hover:underline>{{ tag.name }}</span>
</bdi>
</h4>
<CommonTrending v-if="tag.history" :history="tag.history" text-sm text-secondary line-clamp-1 ws-pre-wrap break-all />
</div>
</div>
<div v-if="tag.history" flex items-center>
<CommonTrendingCharts :history="tag.history" />

Wyświetl plik

@ -1,5 +1,5 @@
<template>
<div p4 flex justify-between>
<div p4 flex justify-between gap-4>
<div flex="~ col 1 gap-2">
<div flex class="skeleton-loading-bg" h-5 w-30 rounded />
<div flex class="skeleton-loading-bg" h-4 w-45 rounded />

Wyświetl plik

@ -1,18 +1,27 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
import { STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE } from '~/constants'
const { filter } = defineProps<{
filter?: mastodon.v1.NotificationType
}>()
const route = useRoute()
const lastAccessedNotificationRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE, '')
const options = { limit: 30, types: filter ? [filter] : [] }
// Default limit is 20 notifications, and servers are normally caped to 30
const paginator = useMastoClient().v1.notifications.list(options)
const stream = useStreaming(client => client.user.notification.subscribe())
lastAccessedNotificationRoute.value = route.path.replace(/\/notifications\/?/, '')
const { clearNotifications } = useNotifications()
onActivated(clearNotifications)
onActivated(() => {
clearNotifications()
lastAccessedNotificationRoute.value = route.path.replace(/\/notifications\/?/, '')
})
</script>
<template>

Wyświetl plik

@ -72,7 +72,7 @@ function onEnter(e: KeyboardEvent) {
}
function escapeAutocomplete(evt: KeyboardEvent) {
if (!autocompleteShow)
if (!autocompleteShow.value)
return
autocompleteShow.value = false
evt.stopPropagation()

Wyświetl plik

@ -93,6 +93,23 @@ export async function fetchAccountByHandle(acct: string): Promise<mastodon.v1.Ac
return promise
}
export function fetchTag(tagName: string, force = false): Promise<mastodon.v1.Tag> {
const server = currentServer.value
const userId = currentUser.value?.account.id
const key = `${server}:${userId}:tag:${tagName}`
const cached = cache.get(key)
if (cached && !force)
return Promise.resolve(cached)
const promise = useMastoClient().v1.tags.$select(tagName).fetch()
.then((tag) => {
cacheTag(tag)
return tag
})
cache.set(key, promise)
return promise
}
export function useAccountById(id?: string | null) {
return useAsyncState(() => fetchAccountById(id), null).state
}
@ -113,3 +130,8 @@ export function cacheAccount(account: mastodon.v1.Account, server = currentServe
setCached(`${server}:${userId}:account:${account.id}`, account, override)
setCached(`${server}:${userId}:account:${userAcct}`, account, override)
}
export function cacheTag(tag: mastodon.v1.Tag, server = currentServer.value, override?: boolean) {
const userId = currentUser.value?.account.id
setCached(`${server}:${userId}:tag:${tag.name}`, tag, override)
}

Wyświetl plik

@ -170,7 +170,8 @@ export const useCommandRegistry = defineStore('command', () => {
const indexed = cmds.map((cmd, index) => ({ ...cmd, index }))
const grouped = new Map<CommandScopeNames, CommandQueryResultItem[]>(
scopes.map(scope => [scope, []]))
scopes.map(scope => [scope, []]),
)
for (const cmd of indexed) {
const scope = cmd.scope ?? ''
grouped.get(scope)!.push({

Wyświetl plik

@ -494,7 +494,10 @@ function _markdownProcess(value: string) {
let start = 0
while (true) {
let found: { match: RegExpMatchArray; replacer: (c: (string | Node)[]) => Node } | undefined
let found: {
match: RegExpMatchArray
replacer: (c: (string | Node)[]) => Node
} | undefined
for (const [re, replacer] of _markdownReplacements) {
re.lastIndex = start
@ -524,10 +527,21 @@ function transformMarkdown(node: Node) {
return _markdownProcess(node.value)
}
function addBdiParagraphs(node: Node) {
if (node.name === 'p' && !('dir' in node.attributes) && node.children?.length && node.children.length > 1)
node.attributes.dir = 'auto'
return node
}
function transformParagraphs(node: Node): Node | Node[] {
// Add bdi to paragraphs
addBdiParagraphs(node)
// For top level paragraphs, inject an empty <p> to preserve status paragraphs in our editor (except for the last one)
if (node.parent?.type === DOCUMENT_NODE && node.name === 'p' && node.parent.children.at(-1) !== node)
return [node, h('p')]
return node
}

Wyświetl plik

@ -10,6 +10,7 @@ import Emoji from '~/components/emoji/Emoji.vue'
import ContentCode from '~/components/content/ContentCode.vue'
import ContentMentionGroup from '~/components/content/ContentMentionGroup.vue'
import AccountHoverWrapper from '~/components/account/AccountHoverWrapper.vue'
import TagHoverWrapper from '~/components/account/TagHoverWrapper.vue'
function getTextualAstComponents(astChildren: Node[]): string {
return astChildren
@ -128,11 +129,13 @@ function handleMention(el: Node) {
addBdiNode(el)
return h(AccountHoverWrapper, { handle, class: 'inline-block' }, () => nodeToVNode(el))
}
const matchTag = href.match(TagLinkRE)
if (matchTag) {
const [, , name] = matchTag
const [, , tagName] = matchTag
addBdiNode(el)
el.attributes.href = `/${currentServer.value}/tags/${name}`
el.attributes.href = `/${currentServer.value}/tags/${tagName}`
return h(TagHoverWrapper, { tagName, class: 'inline-block' }, () => nodeToVNode(el))
}
}
}

Wyświetl plik

@ -1,9 +1,9 @@
import type { mastodon } from 'masto'
import type { ConfirmDialogChoice, ConfirmDialogLabel, Draft, ErrorDialogData } from '~/types'
import type { ConfirmDialogChoice, ConfirmDialogOptions, Draft, ErrorDialogData } from '~/types'
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'
export const confirmDialogChoice = ref<ConfirmDialogChoice>()
export const confirmDialogLabel = ref<ConfirmDialogLabel>()
export const confirmDialogLabel = ref<ConfirmDialogOptions>()
export const errorDialogData = ref<ErrorDialogData>()
export const mediaPreviewList = ref<mastodon.v1.MediaAttachment[]>([])
@ -39,7 +39,7 @@ export function openSigninDialog() {
isSigninDialogOpen.value = true
}
export async function openConfirmDialog(label: ConfirmDialogLabel | string): Promise<ConfirmDialogChoice> {
export async function openConfirmDialog(label: ConfirmDialogOptions | string): Promise<ConfirmDialogChoice> {
confirmDialogLabel.value = typeof label === 'string' ? { title: label } : label
confirmDialogChoice.value = undefined
isConfirmDialogOpen.value = true

Wyświetl plik

@ -29,8 +29,10 @@ export function useHumanReadableNumber() {
}
}
export function useFormattedDateTime(value: MaybeRefOrGetter<string | number | Date | undefined | null>,
options: Intl.DateTimeFormatOptions = { dateStyle: 'long', timeStyle: 'medium' }) {
export function useFormattedDateTime(
value: MaybeRefOrGetter<string | number | Date | undefined | null>,
options: Intl.DateTimeFormatOptions = { dateStyle: 'long', timeStyle: 'medium' },
) {
const { locale } = useI18n()
const formatter = computed(() => Intl.DateTimeFormat(locale.value, options))
return computed(() => {

Wyświetl plik

@ -36,9 +36,11 @@ export function useMagicSequence(keys: string[]): ComputedRef<boolean> {
down = false
success.value = true
}
}, {
},
{
deep: true,
})
},
)
return computed(() => success.value)
}

Wyświetl plik

@ -36,26 +36,25 @@ export function usePublish(options: {
const { params, attachments } = draft.value
const firstEmptyInputIndex = params.poll?.options.findIndex(option => option.trim().length === 0)
return isEmpty.value
|| options.isUploading.value
|| isSending.value
|| (attachments.length === 0 && !params.status)
|| failedMessages.value.length > 0
|| (attachments.length > 0 && params.poll !== null && params.poll !== undefined)
|| ((params.poll !== null && params.poll !== undefined)
&& (
(firstEmptyInputIndex !== -1
&& firstEmptyInputIndex !== params.poll.options.length - 1
)
|| params.poll.options.findLastIndex(option => option.trim().length > 0) + 1 < 2
|| (new Set(params.poll.options).size !== params.poll.options.length)
|| (currentInstance.value?.configuration?.polls.maxCharactersPerOption !== undefined
&& params.poll.options.find(option => option.length > currentInstance.value!.configuration!.polls.maxCharactersPerOption) !== undefined
)
)
)
|| options.isUploading.value
|| isSending.value
|| (attachments.length === 0 && !params.status)
|| failedMessages.value.length > 0
|| (attachments.length > 0 && params.poll !== null && params.poll !== undefined)
|| ((params.poll !== null && params.poll !== undefined)
&& (
(firstEmptyInputIndex !== -1
&& firstEmptyInputIndex !== params.poll.options.length - 1
)
|| params.poll.options.findLastIndex(option => option.trim().length > 0) + 1 < 2
|| (new Set(params.poll.options).size !== params.poll.options.length)
|| (currentInstance.value?.configuration?.polls.maxCharactersPerOption !== undefined
&& params.poll.options.find(option => option.length > currentInstance.value!.configuration!.polls.maxCharactersPerOption) !== undefined
)
))
})
watch(() => draft, () => {
watch(draft, () => {
if (failedMessages.value.length > 0)
failedMessages.value.length = 0
}, { deep: true })
@ -164,7 +163,7 @@ export function useUploadMediaAttachment(draft: Ref<Draft>) {
const maxPixels = computed(() => {
return currentInstance.value?.configuration?.mediaAttachments?.imageMatrixLimit
?? 4096 ** 2
?? 4096 ** 2
})
const loadImage = (inputFile: Blob) => new Promise<HTMLImageElement>((resolve, reject) => {

Wyświetl plik

@ -11,9 +11,12 @@ let timeoutHandle: NodeJS.Timeout | undefined
export function useRelationship(account: mastodon.v1.Account): Ref<mastodon.v1.Relationship | undefined> {
if (!currentUser.value)
return ref()
let relationship = requestedRelationships.get(account.id)
if (relationship)
return relationship
// allow batch relationship requests
relationship = ref<mastodon.v1.Relationship | undefined>()
requestedRelationships.set(account.id, relationship)
if (timeoutHandle)
@ -22,14 +25,19 @@ export function useRelationship(account: mastodon.v1.Account): Ref<mastodon.v1.R
timeoutHandle = undefined
fetchRelationships()
}, 100)
return relationship
}
async function fetchRelationships() {
const requested = Array.from(requestedRelationships.entries()).filter(([, r]) => !r.value)
const relationships = await useMastoClient().v1.accounts.relationships.fetch({ id: requested.map(([id]) => id) })
for (let i = 0; i < requested.length; i++)
requested[i][1].value = relationships[i]
for (const relationship of relationships) {
const requestedToUpdate = requested.find(([id]) => id === relationship.id)
if (!requestedToUpdate)
continue
requestedToUpdate[1].value = relationship
}
}
export async function toggleFollowAccount(relationship: mastodon.v1.Relationship, account: mastodon.v1.Account) {
@ -39,12 +47,13 @@ export async function toggleFollowAccount(relationship: mastodon.v1.Relationship
const unfollow = relationship!.following || relationship!.requested
if (unfollow) {
if (await openConfirmDialog({
const confirmUnfollow = await openConfirmDialog({
title: i18n.t('confirm.unfollow.title'),
description: i18n.t('confirm.unfollow.description', [`@${account.acct}`]),
confirm: i18n.t('confirm.unfollow.confirm'),
cancel: i18n.t('confirm.unfollow.cancel'),
}) !== 'confirm')
})
if (confirmUnfollow.choice !== 'confirm')
return
}
@ -66,18 +75,28 @@ export async function toggleMuteAccount(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.muting && await openConfirmDialog({
title: i18n.t('confirm.mute_account.title'),
description: i18n.t('confirm.mute_account.description', [account.acct]),
confirm: i18n.t('confirm.mute_account.confirm'),
cancel: i18n.t('confirm.mute_account.cancel'),
}) !== 'confirm')
return
let duration = 0 // default 0 == indefinite
let notifications = true // default true = mute notifications
if (!relationship!.muting) {
const confirmMute = await openConfirmDialog({
title: i18n.t('confirm.mute_account.title'),
description: i18n.t('confirm.mute_account.description', [account.acct]),
confirm: i18n.t('confirm.mute_account.confirm'),
cancel: i18n.t('confirm.mute_account.cancel'),
extraOptionType: 'mute',
})
if (confirmMute.choice !== 'confirm')
return
duration = confirmMute.extraOptions!.mute.duration
notifications = confirmMute.extraOptions!.mute.notifications
}
relationship!.muting = !relationship!.muting
relationship = relationship!.muting
? await client.value.v1.accounts.$select(account.id).mute({
// TODO support more options
duration,
notifications,
})
: await client.value.v1.accounts.$select(account.id).unmute()
}
@ -86,13 +105,16 @@ export async function toggleBlockAccount(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.blocking && await openConfirmDialog({
title: i18n.t('confirm.block_account.title'),
description: i18n.t('confirm.block_account.description', [account.acct]),
confirm: i18n.t('confirm.block_account.confirm'),
cancel: i18n.t('confirm.block_account.cancel'),
}) !== 'confirm')
return
if (!relationship!.blocking) {
const confirmBlock = await openConfirmDialog({
title: i18n.t('confirm.block_account.title'),
description: i18n.t('confirm.block_account.description', [account.acct]),
confirm: i18n.t('confirm.block_account.confirm'),
cancel: i18n.t('confirm.block_account.cancel'),
})
if (confirmBlock.choice !== 'confirm')
return
}
relationship!.blocking = !relationship!.blocking
relationship = await client.value.v1.accounts.$select(account.id)[relationship!.blocking ? 'block' : 'unblock']()
@ -102,13 +124,16 @@ export async function toggleBlockDomain(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.domainBlocking && await openConfirmDialog({
title: i18n.t('confirm.block_domain.title'),
description: i18n.t('confirm.block_domain.description', [getServerName(account)]),
confirm: i18n.t('confirm.block_domain.confirm'),
cancel: i18n.t('confirm.block_domain.cancel'),
}) !== 'confirm')
return
if (!relationship!.domainBlocking) {
const confirmDomainBlock = await openConfirmDialog({
title: i18n.t('confirm.block_domain.title'),
description: i18n.t('confirm.block_domain.description', [getServerName(account)]),
confirm: i18n.t('confirm.block_domain.confirm'),
cancel: i18n.t('confirm.block_domain.cancel'),
})
if (confirmDomainBlock.choice !== 'confirm')
return
}
relationship!.domainBlocking = !relationship!.domainBlocking
await client.value.v1.domainBlocks[relationship!.domainBlocking ? 'create' : 'remove']({ domain: getServerName(account) })

Wyświetl plik

@ -59,11 +59,11 @@ export function useSearch(query: MaybeRefOrGetter<string>, options: UseSearchOpt
}
watch(() => resolveUnref(query), () => {
loading.value = !!(q && isHydrated.value)
loading.value = !!(q.value && isHydrated.value)
})
debouncedWatch(() => resolveUnref(query), async () => {
if (!q || !isHydrated.value)
if (!q.value || !isHydrated.value)
return
loading.value = true
@ -87,7 +87,7 @@ export function useSearch(query: MaybeRefOrGetter<string>, options: UseSearchOpt
}, { debounce: 300 })
const next = async () => {
if (!q || !isHydrated.value || !paginator)
if (!q.value || !isHydrated.value || !paginator)
return
loading.value = true

Wyświetl plik

@ -20,7 +20,7 @@ function getDefaultVisibility(currentVisibility: mastodon.v1.StatusVisibility) {
// the post more private than the replying to post
const preferredVisibility = currentUser.value?.account.source.privacy || 'public'
return ALL_VISIBILITY.indexOf(currentVisibility)
> ALL_VISIBILITY.indexOf(preferredVisibility)
> ALL_VISIBILITY.indexOf(preferredVisibility)
? currentVisibility
: preferredVisibility
}

Wyświetl plik

@ -95,7 +95,12 @@ export async function translateText(text: string, from: string | null | undefine
return status
}
const translations = new WeakMap<mastodon.v1.Status | mastodon.v1.StatusEdit, { visible: boolean; text: string; success: boolean; error: string }>()
const translations = new WeakMap<mastodon.v1.Status | mastodon.v1.StatusEdit, {
visible: boolean
text: string
success: boolean
error: string
}>()
export function useTranslation(status: mastodon.v1.Status | mastodon.v1.StatusEdit, to: string) {
if (!translations.has(status))

Wyświetl plik

@ -6,10 +6,12 @@ import type {
} from '~/composables/push-notifications/types'
import { PushSubscriptionError } from '~/composables/push-notifications/types'
export async function createPushSubscription(user: RequiredUserLogin,
export async function createPushSubscription(
user: RequiredUserLogin,
notificationData: CreatePushNotification,
policy: mastodon.v1.WebPushSubscriptionPolicy = 'all',
force = false): Promise<mastodon.v1.WebPushSubscription | undefined> {
force = false,
): Promise<mastodon.v1.WebPushSubscription | undefined> {
const { server: serverEndpoint, vapidKey } = user
return await getRegistration()

Wyświetl plik

@ -64,7 +64,7 @@ export function usePushManager() {
policy?: mastodon.v1.WebPushSubscriptionPolicy,
force?: boolean,
): Promise<SubscriptionResult> => {
if (!isSupported)
if (!isSupported.value)
return 'not-supported'
if (!currentUser.value)
@ -87,7 +87,10 @@ export function usePushManager() {
currentUser.value.pushSubscription = await createPushSubscription(
{
pushSubscription, server, token, vapidKey,
pushSubscription,
server,
token,
vapidKey,
},
notificationData ?? {
alerts: {
@ -109,7 +112,7 @@ export function usePushManager() {
}
const unsubscribe = async () => {
if (!isSupported || !isSubscribed || !currentUser.value)
if (!isSupported.value || !isSubscribed.value || !currentUser.value)
return false
await removePushNotifications(currentUser.value)

Wyświetl plik

@ -2,5 +2,6 @@ import { breakpointsTailwind } from '@vueuse/core'
export const breakpoints = useBreakpoints(breakpointsTailwind)
export const isSmallScreen = breakpoints.smallerOrEqual('sm')
export const isMediumOrLargeScreen = breakpoints.between('sm', 'xl')
export const isExtraLargeScreen = breakpoints.smallerOrEqual('xl')

Wyświetl plik

@ -16,6 +16,7 @@ export interface PreferencesSettings {
hideTranslation: boolean
hideUsernameEmojis: boolean
hideAccountHoverCard: boolean
hideTagHoverCard: boolean
hideNews: boolean
grayscaleMode: boolean
enableAutoplay: boolean
@ -71,6 +72,7 @@ export const DEFAULT__PREFERENCES_SETTINGS: PreferencesSettings = {
hideTranslation: false,
hideUsernameEmojis: false,
hideAccountHoverCard: false,
hideTagHoverCard: false,
hideNews: false,
grayscaleMode: false,
enableAutoplay: true,

Wyświetl plik

@ -5,7 +5,10 @@ const highlighter = ref<Highlighter>()
const registeredLang = ref(new Map<string, boolean>())
let shikiImport: Promise<void> | undefined
export function useHighlighter(lang: Lang): { promise?: Promise<void>; highlighter?: Highlighter } {
export function useHighlighter(lang: Lang): {
promise?: Promise<void>
highlighter?: Highlighter
} {
if (!shikiImport) {
shikiImport = import('shiki')
.then(async ({ getHighlighter }) => {

Wyświetl plik

@ -55,11 +55,17 @@ export function useTiptap(options: UseTiptapOptions) {
},
}),
Mention.configure({
renderHTML({ options, node }) {
return ['span', { 'data-type': 'mention', 'data-id': node.attrs.id }, `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`]
},
suggestion: TiptapMentionSuggestion,
}),
Mention
.extend({ name: 'hashtag' })
.configure({
renderHTML({ options, node }) {
return ['span', { 'data-type': 'hashtag', 'data-id': node.attrs.id }, `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`]
},
suggestion: TiptapHashtagSuggestion,
}),
Mention

Wyświetl plik

@ -16,7 +16,11 @@ declare module '@tiptap/core' {
/**
* Insert a custom emoji.
*/
insertCustomEmoji: (options: { src: string; alt?: string; title?: string }) => ReturnType
insertCustomEmoji: (options: {
src: string
alt?: string
title?: string
}) => ReturnType
/**
* Insert a emoji.
*/

Wyświetl plik

@ -1,8 +1,10 @@
import type { ExtendedRegExpMatchArray } from '@tiptap/core'
import type { ExtendedRegExpMatchArray, InputRuleFinder, nodeInputRule } from '@tiptap/core'
import type { NodeType } from '@tiptap/pm/model'
import {
InputRule,
Node,
callOrReturn,
mergeAttributes,
nodeInputRule,
nodePasteRule,
} from '@tiptap/core'
import { emojiRegEx, getEmojiAttributes } from '~/config/emojis'
@ -18,8 +20,10 @@ function wrapHandler<T extends (...args: any[]) => any>(handler: T): T {
})
}
function createEmojiRule<NR extends typeof nodeInputRule | typeof nodePasteRule>(nodeRule: NR,
type: Parameters<NR>[0]['type']): ReturnType<NR>[] {
function createEmojiRule<NR extends typeof nodeInputRule | typeof nodePasteRule>(
nodeRule: NR,
type: Parameters<NR>[0]['type'],
): ReturnType<NR>[] {
const rule = nodeRule({
find: emojiRegEx as RegExp,
type,
@ -80,7 +84,34 @@ export const TiptapPluginEmoji = Node.create({
},
addInputRules() {
return createEmojiRule(nodeInputRule, this.type)
function emojiInputRule(config: {
find: InputRuleFinder
type: NodeType
getAttributes?:
| Record<string, any>
| ((match: ExtendedRegExpMatchArray) => Record<string, any>)
| false
| null
}) {
return new InputRule({
find: config.find,
handler: ({ state, range, match }) => {
const attributes = callOrReturn(config.getAttributes, undefined, match) || {}
const { tr } = state
const start = range.from
const end = range.to
tr.insert(start, config.type.create(attributes)).delete(
tr.mapping.map(start),
tr.mapping.map(end),
)
tr.scrollIntoView()
},
})
}
return createEmojiRule(emojiInputRule, this.type)
},
addPasteRules() {

Wyświetl plik

@ -14,7 +14,6 @@ export default defineI18nConfig(() => {
missingWarn: true,
datetimeFormats,
numberFormats,
// eslint-disable-next-line @typescript-eslint/comma-dangle
pluralRules
pluralRules,
}
})

Wyświetl plik

@ -88,6 +88,26 @@ const locales: LocaleObjectData[] = [
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
},
} satisfies LocaleObjectData),
({
code: 'ckb',
file: 'ckb.json',
name: 'کوردیی ناوەندی',
dir: 'rtl',
pluralRule: (choice: number) => {
const name = new Intl.PluralRules('ckb').select(choice)
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
},
} satisfies LocaleObjectData),
({
code: 'fa-IR',
file: 'fa-IR.json',
name: 'فارسی',
dir: 'rtl',
pluralRule: (choice: number) => {
const name = new Intl.PluralRules('fa-IR').select(choice)
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
},
} satisfies LocaleObjectData),
{
code: 'ca',
file: 'ca.json',

Wyświetl plik

@ -22,7 +22,16 @@ export const STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS = 'elk-hide-explore-tags-tips'
export const STORAGE_KEY_NOTIFICATION = 'elk-notification'
export const STORAGE_KEY_NOTIFICATION_POLICY = 'elk-notification-policy'
export const STORAGE_KEY_PWA_HIDE_INSTALL = 'elk-pwa-hide-install'
export const STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE = 'elk-last-accessed-notification-route'
export const STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE = 'elk-last-accessed-explore-route'
export const HANDLED_MASTO_URLS = /^(https?:\/\/)?([\w\d-]+\.)+\w+\/(@[@\w\d-\.]+)(\/objects)?(\/\d+)?$/
export const NOTIFICATION_FILTER_TYPES: mastodon.v1.NotificationType[] = ['status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update', 'admin.sign_up', 'admin.report']
export const THEME_COLORS = {
themeDark: '#111111',
themeLight: '#fafafa',
backgroundDark: '#fafafa',
backgroundLight: '#111111',
} as const

Wyświetl plik

@ -30,7 +30,7 @@ We use [Docus](https://docus.dev) as the site generator and deploy through Netli
When you are ready to submit work back to the main Elk repo, create a PR.
1. If it has been a bit, synchronize your fork with the upstream repo on GitHub.
1. If it has been a bit, synchronize your fork with the upstream repo on GitHub.
2. Do your work in a branch on your fork
Use `git checkout -b branchNameToUse` to create a working branch separate from `main`.
3. Do your work in your preferred editor

Wyświetl plik

@ -14,10 +14,10 @@ css({
gap: '0.5rem',
fontSize: '1.5rem',
},
img: {
'img': {
flexShrink: 0,
aspectRatio: '1/1',
height: '2.5rem'
}
height: '2.5rem',
},
})
</style>

Wyświetl plik

@ -61,8 +61,8 @@ async function copyToClipboard() {
try {
await navigator.clipboard.writeText([
`# ${localeTitle.value}`,
(localeTab.value === 'missing' ? missingEntries.value : outdatedEntries.value).join('\n')].join('\n'),
)
(localeTab.value === 'missing' ? missingEntries.value : outdatedEntries.value).join('\n'),
].join('\n'))
copied.value = true
setTimeout(() => copied.value = false, 750)
}

Wyświetl plik

@ -35,7 +35,6 @@ You can think of the service as something similar to Twitter, but with some key
For more details about Mastodon, see their [website](https://joinmastodon.org/), [blog](https://blog.joinmastodon.org), [docs](https://docs.joinmastodon.org), and [GitHub Repository](https://github.com/mastodon/mastodon).
## What is a Mastodon Client?
A Mastodon Client is software that serves up the posts and activities from a Mastodon server using the [Mastodon API](https://docs.joinmastodon.org/api/).
@ -80,7 +79,6 @@ Desktop
[TheDesk](https://thedesk.top/en/), [Whalebird](https://whalebird.social/en), or [Sengi](https://nicolasconstant.github.io/sengi/)
::
All of these apps provide some combination of the features a typical Mastodon user expects for their account.
### Browser-based Mastodon Clients

Wyświetl plik

@ -67,7 +67,6 @@ Options include:
Elk reorders timeline posts that are connected to each other to display them in a connected thread in the timelines.
This helps keep the conversation context for a post and its replies.
## Improved notifications
Elk groups boosts and likes to the same post when they occur together in the notification history.
@ -76,7 +75,6 @@ This greatly simplifies your notification history.
<!-- ## GitHub HTML cards -->
<!-- - markdown support
- GitHub HTML cards
- and so on... -->

Wyświetl plik

@ -4,7 +4,7 @@ We're really excited that you're interested in contributing to Elk! Before submi
## Online
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
You can use [StackBlitz Codeflow](https://stackblitz.com/codeflow) to fix bugs or implement features. You'll also see a Codeflow button on PRs to review them without a local setup. Once the elk repo has been cloned in Codeflow, the dev server will start automatically and print the URL to open the App. You should receive a prompt in the bottom-right suggesting to open it in the Editor or in another Tab. To learn more, check out the [Codeflow docs](https://developer.stackblitz.com/codeflow/what-is-codeflow).
[![Open in Codeflow](https://developer.stackblitz.com/img/open_in_codeflow.svg)](https://pr.new/elk-zone/elk)

Wyświetl plik

@ -69,7 +69,7 @@ If you deleted any account from your backend with push notification subscription
- Scroll down in the page and locate "Permissions > Notifications"
- Click on "Configuration" button
- Locate "Elk" website in the list and select it, then click on "Remove website" button
- Safari (WIP)
- Safari (WIP)
### Permission denied: enable notifications in your browser
@ -186,7 +186,7 @@ To debug the PWA service worker in your mobile browser, you will need to:
- Cache: `[x]` Cache storage and `[x]` Application cache
- Click on Clear site data button
- Go to `Application > Service Workers` and check the current service worker is missing or has the status deleted or reduntant.
6) Disable port forwarding: open the "Port forwarding..." modal again on the `chrome://inspect/#devices` page and either uncheck the "Enable port forwarding" option or remove the entry from the list and click "Done".
6) Disable port forwarding: open the "Port forwarding..." modal again on the `chrome://inspect/#devices` page and either uncheck the "Enable port forwarding" option or remove the entry from the list and click "Done".
## PWA web manifest and related applications

Wyświetl plik

@ -35,4 +35,3 @@ When we update this privacy notice, the updated version will be indicated by a n
## Contact
If you have questions or comments about this notice, you may raise an issue at https://github.com/elk-zone/elk.

Wyświetl plik

@ -1,10 +1,10 @@
[build]
publish = "dist"
command = "pnpm generate"
publish = "dist"
command = "pnpm generate"
# Allow previewing docs
[[redirects]]
from = "/docs/*"
to = "/:splat"
status = 200
force = true
from = "/docs/*"
to = "/:splat"
status = 200
force = true

Wyświetl plik

@ -13,6 +13,6 @@
},
"devDependencies": {
"@nuxt-themes/docus": "^1.15.0",
"nuxt": "^3.10.3"
"nuxt": "^3.11.0"
}
}

37
eslint.config.js 100644
Wyświetl plik

@ -0,0 +1,37 @@
// @ts-check
import antfu from '@antfu/eslint-config'
export default await antfu(
{
unocss: false,
vue: {
overrides: {
'vue/no-restricted-syntax': ['error', {
selector: 'VElement[name=\'a\']',
message: 'Use NuxtLink instead.',
}],
},
},
ignores: [
'public/**',
'public-dev/**',
'public-staging/**',
'https-dev-config/**',
'elk-translation-status.json',
'docs/translation-status.json',
],
},
{
rules: {
// TODO: migrate all process reference to `import.meta.env` and remove this rule
'node/prefer-global/process': 'off',
},
},
// Sort local files
{
files: ['locales/**.json'],
rules: {
'jsonc/sort-keys': 'error',
},
},
)

687
locales/ckb.json 100644
Wyświetl plik

@ -0,0 +1,687 @@
{
"a11y": {
"loading_page": "خرمەخرمی لاپەڕە، تکایە چاوەڕوان بن",
"loading_titled_page": "خرمەی لاپەڕەی {0}، تکایە چاوەڕوان بن",
"locale_changed": "زمان گۆڕدرا بۆ {0}",
"locale_changing": "گۆڕینی زمان، تکایە چاوەڕوان بن",
"route_loaded": "لاپەڕەی {0} بارکراوە"
},
"account": {
"avatar_description": "{0}بە ئاڤاتاری",
"blocked_by": "تۆ لەلایەن ئەم بەکارهێنەرەوە بلۆک کراویت.",
"blocked_domains": "دۆمەینەکانی بلۆککراو",
"blocked_users": "بەکارهێنەرانی بلۆککراو",
"blocking": "بلۆک کراوە",
"bot": "بۆت",
"favourites": "دڵخواز",
"follow": "بەدواداچوون",
"follow_back": "دوا بکەوە",
"follow_requested": "داواکراوە",
"followers": "هۆگران",
"followers_count": "هۆگر {0}|هۆگر {0}|{0} هۆگر",
"following": "شوێنکەوتوو",
"following_count": "{0} شوێنکەوتوو",
"follows_you": "شوێنت دەکەوێت",
"go_to_profile": "بڕۆ بۆ پڕۆفایلی",
"joined": "بەشداری کردووە",
"moved_title": "ئاماژەی بەوە کردووە، لە ئێستادا هەژمارە نوێیەکەیان بەم شێوەیەیە:",
"muted_users": "بەکارهێنەرە بێدەنگەکان",
"muting": "بێدەنگ",
"mutuals": "دوولایەنە",
"notifications_on_post_disable": "واز لە ئاگادارکردنەوەم بێنە کاتێک {username} پۆست دەکات",
"notifications_on_post_enable": "کاتێک {username} پۆست دەکات ئاگادارم بکەرەوە",
"pinned": "سەنجاق کراوە",
"posts": "بابەت",
"posts_count": "{0} بابەت|{0} بابەت|{0} بابەت",
"profile_description": "سەردێڕی پڕۆفایلی {0}",
"profile_personal_note": "تێبینی کەسی",
"profile_unavailable": "پڕۆفایلی بەردەست نییە",
"request_follow": "داواکاری بۆ بەدواداچوون",
"unblock": "بلۆک بکەرەوە",
"unfollow": "بەدوایدا مەچۆ",
"unmute": "بێدەنگی لابەرە",
"view_other_followers": "لەوانەیە شوێنکەوتووانی حاڵەتەکانی تر نیشان نەدرێن.",
"view_other_following": "لە حاڵەتەکانی تر ناتوانرێت ئاشکرا بکرێت."
},
"action": {
"apply": "به‌کاربردن",
"bookmark": "نیشانەکردن",
"bookmarked": "نیشانە کراوە",
"boost": "هاوبەشکردن",
"boost_count": "{0}",
"boosted": "هاوبەشکرا",
"clear_publish_failed": "هەڵەکانی بڵاوکردنەوە پاک بکەرەوە",
"clear_save_failed": "پاککردنی هەڵەی پاشکەوتکراوە",
"clear_upload_failed": "هەڵەکانی بارکردنی پەڕگە پاک بکەرەوە",
"close": "داخستن",
"compose": "نووسین",
"confirm": "دڵنیاکردنەوە",
"done": "تەواو",
"edit": "دەستکاری",
"enter_app": "چوونەناو ئەپ",
"favourite": "په‌سند",
"favourite_count": "{0}",
"favourited": "پەسەندکراوە",
"more": "زیاتر",
"next": "دواتر",
"prev": "پێشتر",
"publish": "بڵاوكردنه‌وه‌",
"reply": "وەڵامدانەوە",
"reply_count": "{0}",
"reset": "ڕێکخستنه‌وه‌",
"save": "پاشه‌که‌وت",
"save_changes": "پاشکەوتی گۆرانکاری",
"sign_in": "چوونەژوورەوە",
"sign_in_to": "چوونە ژوورەوە بۆ {0}",
"switch_account": "گۆڕینی هەژمارە",
"vote": "دەنگدان"
},
"app_desc_short": "ڕاژەخوازێکی وێبی ماستۆدۆن",
"app_logo": "Elk لۆگۆی",
"app_name": "Elk",
"attachment": {
"edit_title": "وەسف",
"remove_label": "لابردنی لکێندراو"
},
"command": {
"activate": "چالاککردن",
"complete": "تەواو",
"compose_desc": "نووسینی بابەتێکی نوێ",
"select_lang": "زمان هەڵبژێرە",
"sign_in_desc": "هەژمارەیێکی ئامادە زیاد بکە",
"switch_account": "بیگۆڕە بۆ {0}",
"switch_account_desc": "بیگۆڕە بۆ ئەژمێرێکی تر",
"toggle_dark_mode": "گۆڕینی دۆخی تاریک",
"toggle_zen_mode": "دۆخی zen بگۆڕە"
},
"common": {
"end_of_list": "کۆتایی لیستەکە",
"error": "هەڵە",
"fetching": "هێنانی ...",
"in": "لە",
"no_bookmarks": "هێشتا هیچ بابەتێک نیشانە نەکراوە",
"no_favourites": "هێشتا هیچ بابەتێک پەسەند نەکراوە",
"not_found": "هەڵەی ٤٠٤، نەدۆزرایه‌وه‌",
"offline_desc": "وا دیارە تۆ لە دەرەوەی هێڵ بیت. تکایە پەیوەندی تۆڕەکەت بپشکنە."
},
"compose": {
"draft_title": "ڕەشنووس {0}",
"drafts": "ڕەشنووسەکان ({v})"
},
"confirm": {
"block_account": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "بلۆک",
"title": "ئایا دڵنیای کە دەتەوێت {0} بلۆک بکەیت؟"
},
"block_domain": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "بلۆک",
"title": "ئایا دڵنیای کە دەتەوێت {0} بلۆک بکەیت؟"
},
"common": {
"cancel": "نەخێر",
"confirm": "بەڵێ"
},
"delete_list": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "سڕینەوە",
"title": "ئایا دڵنیای کە دەتەوێت لیستی \"{0}\" بسڕیتەوە؟"
},
"delete_posts": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "سڕینەوە",
"title": "دڵنیای دەتەوێت ئەم بابەتە بسڕیتەوە؟"
},
"mute_account": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "بێدەنگ",
"title": "ئایا دڵنیای کە دەتەوێت {0} بێدەنگ بکەیت؟"
},
"show_reblogs": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "پیشاندان",
"title": "ئایا دڵنیای کە دەتەوێت هاوبەشیەکان لە {0}ەوە پیشان بدەیت؟"
},
"unfollow": {
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"confirm": "شوێن نەکەوتن",
"title": "دڵنیای کە دەتەوێت شوێنی نەکەویتەوە؟"
}
},
"conversation": {
"with": "لەگەڵ"
},
"custom_cards": {
"stackblitz": {
"lines": "هێڵەکان {0}",
"open": "کراوە",
"snippet_from": "پارچەیەک لە {0}"
}
},
"error": {
"account_not_found": "هەژمار {0} نەدۆزرایەوە",
"file_size_cannot_exceed_n_mb": "قەبارەی پەڕگە ناتوانرێت لە {0} مێگابایت تێپەڕێت",
"sign_in_error": "ناتوانیت پەیوەندی بکەیت بە ڕاژەکار.",
"status_not_found": "بابەت نەدۆزرایەوە",
"unsupported_file_format": "پەڕەگە پشتگیری نەکراو"
},
"help": {
"build_preview": {
"desc1": "لە ئێستادا ئێوە وشانی پێشوەختەی Elk لە کۆمەڵگەوە دەبینن - {0}.",
"desc2": "لەوانەیە گۆڕانکاری بێ پێداچوونەوە یان تەنانەت زیانبەخشی تێدابێت.",
"desc3": "بە هەژمارە ڕاستەقینەکەتەوە مەچۆژوور",
"title": "پێشبینینی بڵاوکردنەوە"
},
"desc_highlight": "چاوەڕوانی هەندێک هەڵە و تایبەتمەندی ونبوو لێرە و لەوێ بن.",
"desc_para1": "سوپاس بۆ ئارەزووی ئێوە بۆ تاقیکردنەوەی Elk، ڕاژەخوازی ماستۆدۆنەکەمان لە پێشکەوتندایە!",
"desc_para2": "ئێمە زۆر کار لەسەر گەشەپێدانەکە دەکەین و بە تێپەڕبوونی کات باشتری دەکەین.",
"desc_para3": "بۆ بەرزکردنەوەی گەشەپێدان، دەتوانیت لە ڕێگەی پاڵپشتیەکانی گیتهاب پشتیوانی تاقمەکەمان بکەیت. هیوادارین چێژ لە Elk وەربگرن!",
"desc_para4": "Elk سەرچاوە کراوەیە. ئەگەر دەتەوێت یارمەتی بدەیت لە تاقیکەرەوە، فیدباک بنێرە، یان بەشداری بکە،",
"desc_para5": "لە گیتهاب نزیکمان بکەرەوە",
"desc_para6": "و بەشداری بکەن.",
"footer_team": "گەشەپێدارانی Elk",
"title": "ئێلک(Elk) لە پێشبینیدایە!"
},
"language": {
"search": "گەڕان"
},
"list": {
"add_account": "هەژمارە زیاد بکە بۆ لیستەکە",
"cancel_edit": "هەڵوەشاندنەوەی دەستکاریکردن",
"clear_error": "هەڵە پاک بکەرەوە",
"create": "دروستکردن",
"delete": "ئەم لیستە بسڕەوە",
"delete_error": "لە کاتی سڕینەوەی لیستەکەدا هەڵەیەک ڕوویدا",
"edit": "دەستکاری ئەم لیستە بکە",
"edit_error": "لە کاتی نوێکردنەوەی لیستەکەدا هەڵەیەک ڕوویدا",
"error": "لە کاتی دروستکردنی لیستەکەدا هەڵەیەک ڕوویدا",
"error_prefix": "هەڵە:",
"list_title_placeholder": "ناونیشانی لیستەکە",
"modify_account": "دەستکاری لیستەکان بکە بە هەژمارە",
"remove_account": "هەژمارە لە لیستەکە دەربهێنە",
"save": "پاشکەوتی گۆڕانکاری"
},
"magic_keys": {
"dialog_header": "قەدبڕی تەختەکلیل",
"groups": {
"actions": {
"boost": "هابەشیکردن",
"command_mode": "دۆخی فەرمان",
"compose": "نووسین",
"favourite": "دڵخواز",
"title": "کردارەکان"
},
"media": {
"title": "ڕاگه‌یاندن"
},
"navigation": {
"go_to_home": "سەرەتا",
"go_to_notifications": "ئاگاداری",
"next_status": "دۆخی داهاتوو",
"previous_status": "دۆخی پێشوو",
"shortcut_help": "یارمەتی کورتەڕێ",
"title": "ڕێدۆز"
}
},
"sequence_then": "ئیتر"
},
"menu": {
"add_personal_note": "زیادکردنی تێبینی کەسی بۆ {0}",
"block_account": "بلۆک {0}",
"block_domain": " بلۆککردنی دۆمەینی {0}",
"copy_link_to_post": "بەستەری ئەم بابەتە ڕوونووس بکە",
"copy_original_link_to_post": "بەستەری ئەسڵی ڕوونووس بکە بۆ ئەم بابەتە",
"delete": "سڕینەوە",
"delete_and_redraft": "سڕینەوە یا دەستکاری",
"direct_message_account": "پەیامی ڕاستەوخۆ {0}",
"edit": "دەستکاری",
"hide_reblogs": "شاردنەوەی هاوبەشیەکان لە {0}",
"mention_account": "ئاماژە بە {0}",
"mute_account": "بێدەنگکردنی {0}",
"mute_conversation": "ئەم بابەتە بێدەنگ بکەن",
"open_in_original_site": "کردنەوە لە ماڵپەڕی سەرەکی",
"pin_on_profile": "سنجاقکردن لەسەر پرۆفایل",
"remove_personal_note": "لابردنی تێبینی کەسی لە {0}",
"report_account": "{0} گوزارشی",
"share_post": "ئەم بابەتە هاوبەش بکە",
"show_favourited_and_boosted_by": "نیشانی بدە کێ حەزی لێیەتی و هابەشیکردووە",
"show_reblogs": "هاوبەشیەکان نیشان بدە لە {0}",
"show_untranslated": "پیشاندانی ڕێکنەخراو",
"toggle_theme": {
"dark": "گۆڕینی شێوازی تاریک",
"light": "گۆڕینی شێوازی ڕۆژ"
},
"translate_post": "بابەت وەربگێڕە",
"unblock_account": "{0} بلۆکەکە لاببە",
"unblock_domain": "ئازادکردنی {0} دۆمەین",
"unfollow_account": "وازهێنان لە شوێنکەوتووان {0}",
"unmute_account": "بێدەنگی {0} لابەرە",
"unmute_conversation": "بێدەنگی لەم بابەتە لابەرە",
"unpin_on_profile": "سنجاقکردن لابەرە لە پرۆفایل"
},
"modals": {
"aria_label_close": "داخستن"
},
"nav": {
"back": "بگەڕێوە",
"blocked_domains": "دۆمەینە بلۆککراوەکان",
"blocked_users": "بەکارهێنەرە بلۆککراوەکان",
"bookmarks": "نیشانکراوەکان",
"built_at": "{0} دروستکراو",
"compose": "نووسین",
"conversations": "گفتوگۆکان",
"explore": "گەڕان",
"favourites": "دڵخوازەکان",
"federated": "یەکگرتن",
"home": "سەرەتا",
"list": "لیست",
"lists": "لیستەکان",
"local": "خۆماڵی",
"muted_users": "بەکارهێنەرە بێدەنگەکان",
"notifications": "ئاگادارییەکان",
"privacy": "تایبەتێتی",
"profile": "پرۆفایل",
"search": "گەڕان",
"select_feature_flags": "گۆڕینی تایبەتمەندی ئاڵاکان",
"select_font_size": "ئەندازەی پێنووس",
"select_language": "پیشاندانی زمان",
"settings": "ڕێکخستنه‌کان",
"show_intro": "پیشاندانی پێشەکی",
"toggle_theme": "گۆڕینی ڕووکار",
"zen_mode": "شێوەی Zen"
},
"notification": {
"favourited_post": "بابەتەکەتی پەسەند کرد",
"followed_you": "دوای تۆ کەوت",
"followed_you_count": "{0} بەکارهێنەر دوای تۆ کەوتن{0} کەبەکارهێنەر بەدوات کەوتن|{0} بەکارهێنەر دوای تۆ کەوتن",
"missing_type": "MISSING notification.type:",
"reblogged_post": "هاوبەشیکردنی بابەتی تۆ",
"reported": "{0} گوزارشی {1}",
"request_to_follow": "داوای کردووە کە شوێنتان بکەوێت ",
"signed_up": "بوو به ئه ندام",
"update_status": "بابەتەکەیان نوێکردەوە"
},
"placeholder": {
"content_warning": "لێرەدا هۆشدارییەکەت بنووسە",
"default_1": "چی لە مێشکتدایە؟",
"reply_to_account": "وەڵامی {0}",
"replying": "وەڵامدانەوە"
},
"polls": {
"allow_multiple": "ڕێگە بە چەندین هەڵبژاردن بدە",
"cancel": "هه‌ڵوه‌شاندنه‌وه",
"create": "دروستکردنی ڕاپرسی",
"disallow_multiple": "ڕێگەنەدان بە هەڵبژاردنی فرە",
"expiration": "بەسەرچوونی ماوەی ڕاپرسی",
"hide_votes": "Hide vote totals until the end",
"option_placeholder": "هەڵبژاردنی ڕاپرسی {current}/{max}",
"remove_option": "هەڵبژاردن لاببە",
"settings": "بژاردەکانی ڕاپرسی",
"show_votes": "هەمیشە کۆی دەنگەکان پیشان بدە"
},
"pwa": {
"dismiss": " ڕێپێنەدان",
"install": "دامەزراندن",
"install_title": "دامەزراندنی Elk",
"screenshots": {
"dark": "وێنەی ڕوومێزی Elk کە لە دۆخی تاریکدا کاردەکات",
"light": "وێنەی ڕوومێزی Elk کە لە دۆخی ڕووناکیدا کاردەکات"
},
"title": "نوێکردنەوەی نوێی Elk بەردەستە!",
"update": "نوێکردنەوە",
"update_available_short": "نوێکردنەوەی Elk",
"webmanifest": {
"canary": {
"description": "ڕاژەخوازێکی ماستۆدۆن (کاناری)",
"name": "Elk (کاناری)",
"short_name": "Elk (کاناری)"
},
"dev": {
"description": "ڕاژەخوازێکی وێبی ماستۆدۆن (پەرەپێدەر)",
"name": "Elk (پەرەپێدەر)",
"short_name": "Elk (پەرەپێدەر)"
},
"preview": {
"description": "ڕاژەخوازێکی وێبی ماستۆدۆن (پێش‌بینین)",
"name": "Elk (پێش‌بینین)",
"short_name": "Elk (پێش‌بینین)"
},
"release": {
"description": "ڕاژەخوازێکی وێبی ماستۆدۆن",
"name": "Elk",
"short_name": "Elk"
}
}
},
"report": {
"additional_comments": "سەرنجی زیادە",
"another_server": "ئەو بەکارهێنەرەی کە تۆ ڕاپۆرتی دەکەیت لە ڕاژەیێکی ترەوەیە",
"anything_else": "ئایا شتێکی تر هەیە کە پێت وایە پێویستە بزانین؟",
"block_desc": "چیتر هیچ بابەتێک لەم بەکارهێنەرەوە نابینیت. ئەوان ناتوانن پۆستەکانت ببینن و شوێنتکەون بکەن. ئەوان دەتوانن بزانن کە بلۆک کراون.",
"dontlike": "حەزم لێ نیە",
"dontlike_desc": "شتێک نییە کە تۆ بتەوێت بیبینیت",
"forward": "بەڵێ، ئەم گوزارشە بنێرە بۆ {0}",
"forward_question": "ئایا دەتەوێت ڕوونووسێکی بێناو لەم گوزارشە بنێری بۆ ئەو ڕاژەکارەش",
"further_actions": {
"limit": {
"description": "ئەمەی خوارەوە هەڵبژاردنەکانتە بۆ کۆنترۆڵکردنی ئەوەی دەیبینیت:",
"title": "ناتەوێت ئەمە ببینیت؟"
},
"report": {
"description": "لە کاتێکدا ئێمە پێداچوونەوە بۆ ئەمە دەکەین، ئەمە ئەو کردارانەن کە دەتوانیت ئەنجامی بدەیت:",
"title": "سوپاس بۆ گوزارشەکەت ئێمە سەیری ئەمە دەکەین."
}
},
"limiting": "سنووردارکردنی {0}",
"mute_desc": "چیتر هیچ بابەتێکی ئەم بەکارهێنەرە نابینیت. ئەوان هێشتا دەتوانن شوێنت بکەون و بابەتەکانت ببینن. ئه وان نازانن که ئه وان هه ر ده بن.",
"other": "شتێکی ترە",
"other_desc": "کێشەکە ناگونجێت بۆ پۆلەکانی تر",
"reporting": "{0} گوزارش",
"select_many": "هەموو ئەو شتانە دیاریبکە کە جێبەجێ دەکرێن:",
"select_one": "باشترین هاورێ هەڵبژێرە",
"select_posts": "ئایا هیچ بابەتێک هەیە کە پشتگیری ئەم گوزارشە بکات؟",
"select_posts_other": "ئایا هیچ بابەتێکی دیکە هەیە کە پشتگیری ئەم گوزارشە بکات؟",
"spam": "ئەوە سپام",
"spam_desc": "بەستەرە زیانبەخشەکان، پەیوەندی ساختە، یان وەڵامی دووبارەبوونەوە",
"submit": "گوزارش بنێرە",
"unfollow_desc": "چیتر بابەتەکانی ئەم بەکارهێنەرە لە پەڕەی ماڵەکەتدا نابینیت. هێشتا دەتوانیت بابەتەکانیان لە شوێنێکی تر ببینیت.",
"violation": "یەکێک یان زیاتر لە یاساکانی ڕاژەکار پێشێل دەکات",
"whats_wrong_account": "پێمان بڵێ کێشەی ئەم هەژمارە چییە",
"whats_wrong_post": "پێمان بڵێ کێشەی ئەم بابەتە چییە"
},
"search": {
"search_desc": "گەڕان بۆ بەکارهێنەران و هاشتاگەکان",
"search_empty": "نەیتوانی هیچ شتێک بدۆزێتەوە بۆ ئەم مەرجە گەڕانە"
},
"settings": {
"about": {
"built_at": "بنیات نان",
"label": "دەربارە",
"meet_the_team": "تاقمەکە بناسە",
"sponsor_action": "پشتیوانمان بە",
"sponsor_action_desc": "بۆ پشتگیری کردنی تیمی گەشەپێدانی Elk",
"sponsors": "پشتیوانەکان",
"sponsors_body_1": "Elk بە هۆی پشتیوانە بەخشەندە و یارمەتییەکانی، پێزانینی هەیە بۆ :",
"sponsors_body_2": "وە هەموو ئەو کۆمپانیا و کەسانەی کە پشتیوانی دەستەکەی Elk و ئەندامەکان دەکەن.",
"sponsors_body_3": "ئەگەر چێژ لە ئەپەکە وەردەگریت، بیر لەوە بکەرەوە کە پشتیوانیمان بکەیت:",
"version": "وشان"
},
"account_settings": {
"description": "دەستکاری ڕێکخستنەکانی هەژمارەکەت بکە لە ڕوخساری ماستۆدۆن",
"label": "ڕێکخستنەکانی هەژمارە"
},
"interface": {
"color_mode": "شێوەی ڕەنگ",
"dark_mode": "تاریک",
"default": " (بنەڕەت)",
"font_size": "ئەندازەی پێنووس",
"label": "ڕووکار",
"light_mode": "ڕۆشن",
"system_mode": "سیستەم",
"theme_color": "ڕەنگی ڕووکار"
},
"language": {
"display_language": "زمانی پیشاندان",
"label": "زمان",
"post_language": "زمانی بڵاوکردنەوە",
"status": "دۆخی وەرگێڕان: {0}/{1} ({2}٪)",
"translations": {
"add": "زیادکردن",
"choose_language": "زمانێک هەڵبژێرە",
"heading": "وەرگێڕان",
"hide_specific": "وەرگێڕانی دیاریکراو بشارەوە",
"remove": "لابردن"
}
},
"notifications": {
"label": "ئاگادارییەکان",
"notifications": {
"label": "ڕێکخستنەکانی ئاگادارکردنەوەکان"
},
"push_notifications": {
"alerts": {
"favourite": "دڵخوازەکان",
"follow": "شوێنکەوتووی نوێ",
"mention": "ئاماژە",
"poll": "دەنگ",
"reblog": "بابەتەکەت دووبارە بنووسەوە",
"title": "چ ئاگادارکردنەوەیەک وەربگرین؟"
},
"description": "تەنانەت کاتێک کە Elk بەکارناهێنیت ئاگادارکردنەوەکان وەربگرە.",
"instructions": "لەبیرت نەچێت گۆڕانکارییەکانت بە بەکارهێنانی دوگمەی @:settings.notifications.push_notifications.save_settings پاشەکەوت بکەیت!",
"label": "ڕێکخستنەکانی ئاگادارکردنەوەکانی پاڵدان",
"policy": {
"all": "لە هەر کەسێکەوە",
"followed": "لە کەسانێک کە شوێنیان دەکەوم",
"follower": "لە کەسانێک کە شوێنم دەکەون",
"none": "لە هیچ کەس",
"title": "لە کێ دەتوانم ئاگادارکردنەوە وەرگرم؟"
},
"save_settings": "ڕێکخستنەکان پاشەکەوت بکە",
"subscription_error": {
"clear_error": "هەڵە بسڕەوە",
"error_hint": "دەتوانیت ڕاوێژ بە لیستی پرسیارە زۆرەکان بکەیت بۆ ئەوەی هەوڵی چارەسەرکردنی کێشەکە بدەیت: {0}.",
"invalid_vapid_key": "پێدەچێت کلیلی گشتی VAPID نادروست بێت.",
"permission_denied": "مۆڵەت ڕەتکرایەوە: ئاگادارکردنەوەکان لە وێبگەڕەکەتدا چالاک بکە.",
"repo_link": "کۆگای Elk لە گیتهاب",
"request_error": "هەڵەیەک لە کاتی داوای بەشداریکردندا ڕوویدا، دووبارە هەوڵبدەرەوە و ئەگەر هەڵەکە بەردەوام بوو، تکایە کێشەکە گوزارش بدە بە کۆگای Elk.",
"title": "نەتوانرا بەشداری بکات بۆ ئاگادارکردنەوەکانی پاڵدان",
"too_many_registrations": "بەهۆی سنووردارکردنی وێبگەڕەوە، Elk ناتوانێت خزمەتگوزاری ئاگادارکردنەوەی پاڵنەر بەکاربهێنێت بۆ چەندین هەژمار لەسەر ڕاژەکارە جیاوازەکان. پێویستە بەشداری بکەیت لە پاڵنانی ئاگانامەکان لەسەر هەژمارێکی تر و دووبارە هەوڵ بدە.",
"vapid_not_supported": "وێبگەڕەکەت پشتگیری لە ئاگادارییەکانی Web Push دەکات، بەڵام پێناچێت پرۆتۆکۆڵی VAPID جێبەجێ بکات."
},
"title": "ڕێکخستنەکانی ئاگادارکردنەوەکانی پاڵدان",
"undo_settings": "گۆڕانکارییەکان بگەڕێنەوە",
"unsubscribe": "ئاگادارکردنەوەکانی پاڵدان لەکاربخە",
"unsupported": "وێبگەڕەکەت پشتگیری لە ئاگادارکردنەوەکانی پاڵدان ناکات.",
"warning": {
"enable_close": "داخستن",
"enable_description": "بۆ وەرگرتنی ئاگادارکردنەوەکان کاتێک Elk کراوە نییە، ئاگادارکردنەوەکانی پاڵدان چالاک بکە. دەتوانیت بە وردی کۆنتڕۆڵی ئەوە بکەیت کە چ جۆرە کارلێکێک ئاگادارییەکانی پاڵنەر دروست دەکات لە ڕێگەی دوگمەی \"@:settings.notifications.show_btn{'\"'}ی سەرەوە کاتێک چالاک کرا.",
"enable_description_desktop": "بۆ وەرگرتنی ئاگادارکردنەوە کاتێک Elk کراوە نییە، ئاگادارکردنەوەکانی پاڵدان چالاک بکە. دەتوانیت بە وردی کۆنتڕۆڵی ئەوە بکەیت کە چ جۆرە کارلێکێک ئاگادارکردنەوەی پاڵدان دروست دەکات لە \"ڕێکخستنەکان > ئاگادارکردنەوەکان > ڕێکخستنەکانی ئاگادارکردنەوەکانی پاڵدان\" کاتێک چالاک کرا.",
"enable_description_mobile": "هەروەها دەتوانیت بە بەکارهێنانی مینیوی گەشتکردن \"ڕێکخستنەکان > ئاگادارکردنەوەکان > ڕێکخستنەکانی ئاگادارکردنەوە پاڵدان\"، دەستت بگات بە ڕێکخستنەکان.",
"enable_description_settings": "بۆ وەرگرتنی ئاگادارکردنەوەکان کاتێک Elk کراوە نییە، ئاگادارکردنەوەکانی پاڵدان چالاک بکە. دەتوانیت بە وردی کۆنتڕۆڵی ئەوە بکەیت کە چ جۆرە کارلێکێک ئاگادارکردنەوەی پاڵنەر لەسەر هەمان ئەم شاشەیە دروست دەکات کاتێک چالاکیان دەکەیت.",
"enable_desktop": "ئاگادارکردنەوەکانی پاڵدان چالاک بکە",
"enable_title": "هەرگیز هیچ شتێک لەدەست مەدە",
"re_auth": "وا دیارە ڕاژەکارەکەت پشتگیری لە ئاگادارکردنەوەکانی پاڵدان ناکات. هەوڵبدە بچیتە دەرەوە و دووبارە بچۆرەوە ژوورەوە، ئەگەر ئەم پەیامە هێشتا دەرکەوت پەیوەندی بە بەڕێوەبەری سێرڤەرەکەتەوە بکە."
}
},
"show_btn": "بڕۆ بۆ ڕێکخستنەکانی ئاگادارکردنەوەکان",
"under_construction": "لەژێر دروستکردنەوەدایە"
},
"notifications_settings": "ئاگاداریەکان",
"preferences": {
"enable_autoplay": "چالاککردنی لێدانی خۆکار",
"enable_data_saving": "چالاککردنی پاشەکەوتکردنی زانیاری",
"enable_data_saving_description": "زانیاری پاشەکەوت بکە بە ڕێگریکردن لە لکێندراوەکان لە بارکردنی خۆکارانە.",
"enable_pinch_to_zoom": "چالاککردنی پینچ بۆ گەورەنوێیی",
"github_cards": "کاردەکانی گیتهاب",
"github_cards_description": "کاتێک بەستەری گیتهاب بڵاودەکرێتەوە، کارتێکی HTML بە بەکارهێنانی مێتای گرافی کۆمەڵایەتی لە جیاتی وێنەی کۆمەڵایەتی پیشان دەدرێت.",
"grayscale_mode": "دۆخی خۆڵەمێشی",
"hide_account_hover_card": "شاردنەوەی کارتی هۆڤەری ئەکاونت",
"hide_alt_indi_on_posts": "شاردنەوەی نیشاندەری سەردێر لەسەر بابەتەکان",
"hide_boost_count": "شاردنەوەی ژمارەی هابەشکردنەوە",
"hide_favorite_count": "ژمارەی دڵخوازەکان بشارەوە",
"hide_follower_count": "ژمارەی شوێنکەوتوو/شوێنکەوتووان بشارەوە",
"hide_news": "شاردنەوەی هەواڵەکان",
"hide_reply_count": "ژمارەی وەڵامەکان بشارەوە",
"hide_translation": "وەرگێڕان بشارەوە",
"hide_username_emojis": "شاردنەوەی ئیمۆجیەکانی ناوی بەکارهێنەر",
"hide_username_emojis_description": "شاردنەوەی ئیمۆجیەکان لە ناوی بەکارهێنەر لە هێڵی کات. ئیمۆجییەکان هێشتا لە پرۆفایلەکانیاندا دەبینرێن.",
"label": "هەڵبژاردن",
"title": "تایبەتمەندییە تاقیکارییەکان",
"use_star_favorite_icon": "ئایکۆنی دڵخوازی ئەستێرە بەکاربهێنە",
"user_picker": "هەڵبژێرەری بەکارهێنەر",
"user_picker_description": "هەموو وێنۆچکەکانی هەژمارەکانی تۆمارکراوەکان لە خوارەوەی چەپ پیشان دەدات بۆ ئەوەی بتوانیت بە خێرایی لە نێوانیاندا بگۆڕیت.",
"virtual_scroll": "سکڕۆڵکردنی مەجازی",
"virtual_scroll_description": "لیستی مەجازی لە هێڵە کاتییەکاندا بەکاربهێنە، بۆ ئەوەی ژمارەیەکی زیاتر لە بابەتە بە شێوەیەکی کارا ڕەندەر بکرێت.",
"wellbeing": "خۆشگوزەرانی",
"zen_mode": "شێوەی Zen",
"zen_mode_description": "لایەک بشارەوە مەگەر ئاماژەدەری ماوسەکە لەسەریان نەبێت. هەروەها هەندێک توخم لە هێڵی کاتی بشارەوە."
},
"profile": {
"appearance": {
"bio": "ژیاننامە",
"description": "دەستکاری وێنۆچکە، ناوی بەکارهێنەر، پڕۆفایل و هتد.",
"display_name": "ناوی پیشاندراو",
"label": "پیشان‌دان",
"profile_metadata": "مێتاداتای پڕۆفایلی",
"profile_metadata_desc": "دەتوانیت تا {0} شت وەک خشتەیەک لە پڕۆفایلی خۆتدا پیشان بدەیت",
"profile_metadata_label": "نیشانە",
"profile_metadata_value": "ناوەڕۆک",
"title": "دەستکاریکردنی پرۆفایل"
},
"featured_tags": {
"description": "خەڵک دەتوانن لە ژێر ئەم هاشتاگانەدا لە بابەتە گشتیەکانتاندا بگەڕێن.",
"label": "هاشتاگی تایبەت"
},
"label": "پرۆفایل"
},
"select_a_settings": "ڕێکخستنێک هەڵبژێرە",
"users": {
"export": "هەناردەکردنی تۆکنەکانی بەکارهێنەر",
"import": "هاوردەکردنی تۆکنەکانی بەکارهێنەر",
"label": "بەکارهێنەرانی چوونەژوورەوە"
}
},
"state": {
"attachments_exceed_server_limit": "ژمارەی هاوپێچەکان سنووری بۆ هەر بابەتێک تێپەڕاند.",
"attachments_limit_error": "سنوور بۆ هەر بابەتێک تێپەڕی",
"edited": "(دەستکاری کراوە)",
"editing": "دەستکاریکردن",
"loading": "خرمەخرم ...",
"publish_failed": "بڵاوکردنەوە سەرکەوتوو نەبوو",
"publishing": "بڵاوکردنەوە",
"save_failed": "هەڵگرتن سەرکەوتوو نەبوو",
"upload_failed": "بارکردن سەرکەوتوو نەبوو",
"uploading": "بارکردنەوە..."
},
"status": {
"account": {
"suspended_message": "هەژمارکردنی ئەم دۆخە ڕاگیراوە.",
"suspended_show": "بەهەرحاڵ ناوەڕۆک نیشان بدە؟"
},
"boosted_by": "هاوبەشکردن لە لایەن",
"edited": "{0} دەستکاریکراو",
"favourited_by": "پەسەندکراوە لەلایەن",
"filter_hidden_phrase": "پاڵێوراوە لەلایەن",
"filter_show_anyway": "بەهەر حاڵ پیشان بدە",
"img_alt": {
"ALT": "ALT",
"desc": "وەسف",
"dismiss": "ڕێپێنەدان",
"read": "وەسفی {0} بخوێنەوە"
},
"poll": {
"count": "{0} دەنگ|{0} دەنگ|{0} دەنگ",
"ends": "کۆتایی بە {0} دێت",
"finished": "تەواو بوو {0}"
},
"replying_to": "وەڵامدانەوەی {0}",
"show_full_thread": "تەوەرەی تەواو پیشان بدە",
"someone": "کەسێک",
"spoiler_media_hidden": "میدیای شاراوە",
"spoiler_show_less": "کەمتر پیشان بدە",
"spoiler_show_more": "زیاتر نیشان دە",
"thread": "Thread",
"try_original_site": "سایتی ئەسڵی تاقی بکەرەوە"
},
"status_history": {
"created": "دروستکراوە {0}",
"edited": "دەستکاری کراوە {0}"
},
"tab": {
"accounts": "هەژمارەکان",
"for_you": "بۆ تۆ",
"hashtags": "هاشتاگەکان",
"list": "لیست",
"media": "مێدیا",
"news": "هەواڵ",
"notifications_all": "هەموو",
"notifications_mention": "باسکردن",
"posts": "بابەتەکان",
"posts_with_replies": "بابەت و وەڵام"
},
"tag": {
"follow": "بەدواداچوون",
"follow_label": "شوێنکەوتنی تاگی {0} بکە",
"unfollow": "شوێن نەکەوتن",
"unfollow_label": "شوێنکەوتنی تاگی {0} مەکە"
},
"time_ago_options": {
"day_future": "لە 0 ڕۆژدا|سبەی|لە {n} ڕۆژدا",
"day_past": "0 ڕۆژ پێش ئێستا|دوێنێ|{n} ڕۆژ پێش ئێستا",
"hour_future": "لە 0 کاتژمێردا|لە 1 کاتژمێردا|لە {n} کاتژمێردا",
"hour_past": "0 کاتژمێر پێش ئێستا|1 کاتژمێر پێش ئێستا|{n} کاتژمێر پێش ئێستا",
"just_now": "هەر ئێستا",
"minute_future": "لە 0 خولەکدا|لە 1 خولەکدا|لە {n} خولەکدا",
"minute_past": "0 خولەک پێش ئێستا|1 خولەک پێش ئێستا|{n} خولەک پێش ئێستا",
"month_future": "لە 0 مانگ|مانگی داهاتوو|لە {n} مانگ",
"month_past": "0 مانگ پێش ئێستا|مانگی ڕابردوو|{n} مانگ پێش ئێستا",
"second_future": "تەنها ئێستا|لە {n} چرکە|لە {n} چرکە",
"second_past": "تەنها ئێستا|{n} چرکە پێش ئێستا|{n} چرکە پێش ئێستا",
"short_day_future": "لە {n}ڕۆژ",
"short_day_past": "{n}ڕۆژ",
"short_hour_future": "لە {n}کاژێر",
"short_hour_past": "{n}کاژێر",
"short_minute_future": "لە {n}خولەک",
"short_minute_past": "{n}خولەک",
"short_month_future": "لە {n}مانگ",
"short_month_past": "{n}مانگ",
"short_second_future": "لە {n}چرکه",
"short_second_past": "{n}چرکه",
"short_week_future": "لامەرکەزیدا {n}هەفتە",
"short_week_past": "{n}هەفتە",
"short_year_future": "لە {n}ساڵ",
"short_year_past": "{n}ساڵ",
"week_future": "لە 0 هەفتە|هەفتەی داهاتوو|لە {n} هەفتە",
"week_past": "0 هەفتە پێش ئێستا|هەفتەی ڕابردوو|{n} هەفتە پێش ئێستا",
"year_future": "لە 0 ساڵ|ساڵی داهاتوو|لە {n} ساڵ",
"year_past": "0 ساڵ لەمەوبەر|ساڵی ڕابردوو|{n} ساڵ لەمەوبەر"
},
"timeline": {
"show_new_items": "{v} بابەتی نوێ پیشان بدە|{v} بابەتی نوێ پیشان بدە|{v} بابەتی نوێ پیشان بدە",
"view_older_posts": "ڕەنگە بابەتە کۆنەکانی نموونەکانی تر پیشان نەدرێت."
},
"title": {
"federated_timeline": "هێڵی کاتی فێدرێرکراو",
"local_timeline": "هێڵی کاتی ناوخۆیی"
},
"tooltip": {
"add_content_warning": "ئاگادارکردنەوەی ناوەڕۆک زیاد بکە",
"add_emojis": "ئیمۆجی زیاد بکە",
"add_media": "زیادکردنی وێنە، ڤیدیۆ یان پەڕگەیێکی دەنگی",
"add_publishable_content": "ناوەڕۆک زیاد بکە بۆ بڵاوکردنەوە",
"change_content_visibility": "گۆڕینی بینینی ناوەڕۆک",
"change_language": "گۆڕینی زمان",
"emoji": "ئیمۆجی",
"explore_links_intro": "ئەم هەواڵانە لەلایەن ئەندامان و ڕاژەکارەکانی دیکەی تۆڕی کۆمەڵایەتییەوە باس دەکرێن.",
"explore_posts_intro": "ئەم بابەتانە لەم ڕاژەکارە و ڕاژەکارەکانی تر لە تۆڕی لامەرکەزی ئێستا لەسەر ئەم ڕاژەکارە ڕاکێشن.",
"explore_tags_intro": "ئەم هاشتاگانە لە ئێستادا لە نێو ئەندامانی سەر ئەم ڕاژەکارە و ڕاژەکارەکانی تری تۆڕی لامەرکەزیدا جێگەی خۆیان دەگرن.",
"open_editor_tools": "ئامرازەکانی سەرنوسەر",
"pick_an_icon": "ئایکۆنێک هەڵبژێرە",
"publish_failed": "نامە شکستخواردووەکان لە سەرەوەی سەرنوسەر دابخە بۆ دووبارە بڵاوکردنەوەی پۆستەکان",
"toggle_bold": "قەڵەو کردن",
"toggle_code_block": "بلۆکی کۆد",
"toggle_italic": "لار کردن"
},
"user": {
"add_existing": "هەژمارەیەکی بەردەست زیاد بکە",
"server_address_label": "ناونیشانی ڕاژەکاری ماستۆدۆن",
"sign_in_desc": "چوونەژوورەوە بۆ شوێنکەوتنی پڕۆفایل یان هاشتاگەکان، دڵخوازەکان، هاوبەشکردن و وەڵامدانەوەی بابەتەکان، یان کارلێککردن لە هەژمارەکەتەوە لەسەر ڕاژەکارێکی جیاواز.",
"sign_in_notice_title": "بینینی {0} داتا گشتیەکان",
"sign_out_account": "چوونە دەرەوە {0}",
"single_instance_sign_in_desc": "چوونەژوورەوە بۆ شوێنکەوتنی پڕۆفایل یان هاشتاگەکان، دڵخوازەکان، هاوبەشکردن و وەڵامدانەوەی بابەتەکان،.",
"tip_no_account": "ئەگەر هێشتا هەژمارەیێکی ماستۆدۆنت نییە، {0}.",
"tip_register_account": "ڕاژەکارەکەت هەڵبژێرە و یەکێکیان تۆمار بکە"
},
"visibility": {
"direct": "ڕاستەوخۆ",
"direct_desc": "بینراو تەنها بۆ بەکارهێنەرە ئاماژەپێکراو",
"private": "تەنها شوێنکەوتووان",
"private_desc": "بینراو تەنها بۆ شوێنکەوتووان",
"public": "گشتی",
"public_desc": "بینراو بۆ هەمووان",
"unlisted": "لیست نەکراوە",
"unlisted_desc": "بینراو بۆ هەمووان، بەڵام هەڵبژێردراو لە تایبەتمەندییەکانی دۆزینەوە"
}
}

Wyświetl plik

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Cancel",
"confirm": "Mute",
"days": "days|day|days",
"description": "Are you sure you want to mute {0}?",
"hours": "hours|hour|hours",
"minute": "minutes|minute|minutes",
"notifications": "Mute notifications",
"specify_duration": "Specify mute duration",
"title": "Mute account"
},
"show_reblogs": {
@ -304,6 +309,7 @@
"explore": "Explore",
"favourites": "Favorites",
"federated": "Federated",
"hashtags": "Hashtags",
"home": "Home",
"list": "List",
"lists": "Lists",
@ -536,6 +542,7 @@
"hide_follower_count": "Hide following/follower count",
"hide_news": "Hide news",
"hide_reply_count": "Hide reply count",
"hide_tag_hover_card": "Hide tag hover card",
"hide_translation": "Hide translation",
"hide_username_emojis": "Hide username emojis",
"hide_username_emojis_description": "Hides emojis from usernames in timelines. Emojis will still be visible in their profiles.",

Wyświetl plik

@ -304,6 +304,7 @@
"explore": "Explorar",
"favourites": "Favoritas",
"federated": "Federados",
"hashtags": "Etiquetas",
"home": "Inicio",
"list": "Lista",
"lists": "Listas",
@ -536,6 +537,7 @@
"hide_follower_count": "Ocultar número de seguidores",
"hide_news": "Ocultar noticias",
"hide_reply_count": "Ocultar número de respuestas",
"hide_tag_hover_card": "Ocultar tarjeta flotante de etiqueta",
"hide_translation": "Ocultar traducción",
"hide_username_emojis": "Ocultar emojis en el nombre de usuario",
"hide_username_emojis_description": "Oculta los emojis de los nombres de usuarios en la línea de tiempo. Los emojis permanecerán visibles en sus perfiles.",

Wyświetl plik

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Utzi",
"confirm": "Mututu",
"days": "egun|egun|egun",
"description": "Ziur {0} mututu nahi duzula?",
"hours": "ordu|ordu|ordu",
"minute": "minutu|minutu|minutu",
"notifications": "Mututu jakinarazpenak",
"specify_duration": "Zehaztu mututzearen iraupena",
"title": "Mututu kontua"
},
"show_reblogs": {
@ -228,16 +233,27 @@
"compose": "Idatzi",
"favourite": "Egin gogoko",
"search": "Bilatu",
"show_new_items": "Erakutsi elementu berriak",
"title": "Ekintzak"
},
"media": {
"title": "Multimedia"
},
"navigation": {
"go_to_bookmarks": "Laster-markak",
"go_to_conversations": "Elkarrizketak",
"go_to_explore": "Arakatu",
"go_to_favourites": "Gogokoak",
"go_to_federated": "Federatua",
"go_to_home": "Hasiera",
"go_to_lists": "Zerrendak",
"go_to_local": "Lokala",
"go_to_notifications": "Jakinarazpenak",
"next_status": "Hurrengo egoera",
"previous_status": "Aurreko egoera",
"go_to_profile": "Profila",
"go_to_search": "Bilatu",
"go_to_settings": "Ezarpenak",
"next_status": "Hurrengo bidalketa",
"previous_status": "Aurreko bidalketa",
"shortcut_help": "Laster-teklak",
"title": "Nabigazioa"
}
@ -293,6 +309,7 @@
"explore": "Arakatu",
"favourites": "Gogokoak",
"federated": "Federatua",
"hashtags": "Traolak",
"home": "Hasiera",
"list": "Zerrenda",
"lists": "Zerrendak",
@ -304,22 +321,22 @@
"search": "Bilaketa",
"select_feature_flags": "Aldatu ezaugarrien adierazleak (Toggle Feature Flags)",
"select_font_size": "Letra-tipoaren tamaina",
"select_language": "Hizkuntza",
"select_language": "Interfazearen hizkuntza",
"settings": "Ezarpenak",
"show_intro": "Erakutsi aurkezpena",
"toggle_theme": "Gai argia/iluna",
"zen_mode": "ZEN modua"
},
"notification": {
"favourited_post": "zure bidalketa gogoko egin du",
"favourited_post": "(e)k zure bidalketa gogoko egin du",
"followed_you": "(e)k jarraitu dizu",
"followed_you_count": "{0} pertsonak jarraitu dizute|pertsona {0}ek jarraitu dizu|{0} pertsonak jarraitu dizute",
"missing_type": "MISSING notification.type:",
"reblogged_post": "zure bidalketari bultzada eman dio",
"reblogged_post": "(e)k zure bidalketari bultzada eman dio",
"reported": "{0}(e)k {1} salatu du",
"request_to_follow": "jarraipen-eskaera bidali dizu",
"signed_up": "izena eman du",
"update_status": "bidalketa eguneratu du"
"request_to_follow": "(e)k jarraipen-eskaera bidali dizu",
"signed_up": "(e)k izena eman du",
"update_status": "(e)k bidalketa eguneratu du"
},
"placeholder": {
"content_warning": "Idatzi oharra hemen",
@ -374,7 +391,7 @@
}
},
"report": {
"additional_comments": "Ohar gehigarriak",
"additional_comments": "Iruzkin gehigarriak",
"another_server": "Salatzen ari zaren erabiltzailea beste zerbitzari batekoa da",
"anything_else": "Ba al dago jakin beharko genukeen beste ezer?",
"block_desc": "Ez duzu erabiltzaile honen bidalketarik ikusiko. Ezin izango ditu zure bidalketak ikusi edo zuri jarraitu. Blokeatu duzula jakingo du.",
@ -395,10 +412,10 @@
"limiting": "Mugatu {0}",
"mute_desc": "Ez duzu erabiltzaile honen bidalketarik ikusiko. Zure bidalketak ikusi eta zuri jarraitu diezazuke. Ez du jakingo mututu duzunik.",
"other": "Beste zerbait da",
"other_desc": "Arazoa ez da beste kategorietan sartzen",
"other_desc": "Arazoa ez dator bat beste kategoriekin",
"reporting": "{0} salatzen",
"select_many": "Hautatu bat datozen guztiak:",
"select_one": "Aukeratu hobekien datorrena:",
"select_many": "Hautatu dagozkion guztiak:",
"select_one": "Aukeratu hobekien doakiona:",
"select_posts": "Salaketa hau sostengatzen duen bidalketarik al dago?",
"select_posts_other": "Ba al dago salaketa sostengatzen duen beste bidalketarik?",
"spam": "Spama da",
@ -441,9 +458,9 @@
"theme_color": "Gaiaren kolorea"
},
"language": {
"display_language": "Hizkuntza",
"display_language": "Interfazearen hizkuntza",
"label": "Hizkuntza",
"post_language": "Argitalpenaren hizkuntza",
"post_language": "Bidalketen hizkuntza",
"status": "Itzulpenaren egoera: {1} kateetatik {0} itzulita (%{2}a)",
"translations": {
"add": "Gehitu",
@ -518,13 +535,14 @@
"github_cards": "GitHub txartelak",
"github_cards_description": "GitHub-eko esteka argitaratzean, HTML txartel irisgarri bat erakusten du gizarte-grafikoaren metadatuak erabiliz, irudi sozialaren ordez.",
"grayscale_mode": "Gris modua",
"hide_account_hover_card": "Ezkutatu kontuaren geruza (Hide account hover card)",
"hide_account_hover_card": "Ezkutatu kontuen aurrebista-txartelak sagua gainetik pasatzean",
"hide_alt_indi_on_posts": "Ezkutatu ALT adierazlea bidalketetan",
"hide_boost_count": "Ezkutatu bultzaden kopurua",
"hide_favorite_count": "Ezkutatu gogokoen kopurua",
"hide_follower_count": "Ezkutatu jarraitzaile kopurua",
"hide_news": "Ezkutatu berriak",
"hide_reply_count": "Ezkutatu erantzunen kopurua",
"hide_tag_hover_card": "Ezkutatu traolen aurrebista-txartelak sagua gainetik pasatzean",
"hide_translation": "Ezkutatu itzulpenak",
"hide_username_emojis": "Ezkutatu emojiak erabiltzaile izenetan",
"hide_username_emojis_description": "Denbora-lerroetan erabiltzaile izenetako emojiak ezkutatzen ditu. Emojiak ikusgai egoten jarraituko dute euren profiletan.",
@ -537,7 +555,7 @@
"virtual_scroll": "Korritze birtuala",
"virtual_scroll_description": "Zerrenda birtual bat erabiltzen du denbora-lerroetan, item kopuru handiagoa modu eraginkorrean erakutsi ahal izateko.",
"wellbeing": "Ongizatea",
"zen_mode": "Zen modua",
"zen_mode": "ZEN modua",
"zen_mode_description": "Aldamenetako elementuak ezkutatzen ditu xagua gainean jarri arte. Denbora-lerroko elementu batzuk ere ezkutatzen ditu."
},
"profile": {
@ -585,7 +603,7 @@
},
"status": {
"account": {
"suspended_message": "Argitalpen honen egileari zigorra jarri zaio.",
"suspended_message": "Bidalketa honen egileari zigorra jarri zaio.",
"suspended_show": "Erakutsi edukia hala ere?"
},
"boosted_by": "Bultzatu dute:",

715
locales/fa-IR.json 100644
Wyświetl plik

@ -0,0 +1,715 @@
{
"a11y": {
"loading_page": "در حال بارگذاری صفحه، لطفا صبر کنید",
"loading_titled_page": "در حال بارگذاری صفحه {0}، لطفا صبر کنید",
"locale_changed": "زبان به {0} تغییر کرد",
"locale_changing": "در حال تغییر زبان، لطفا صبر کنید",
"route_loaded": "صفحه {0} بارگذاری شد"
},
"account": {
"authorize": "اجازه دنبال کردن بدهید",
"authorized": "شما درخواست را تأیید کردید",
"avatar_description": "آواتار {0}",
"blocked_by": "شما توسط این کاربر مسدود شده‌اید.",
"blocked_domains": "دامنه‌های مسدود شده",
"blocked_users": "کاربران مسدود شده",
"blocking": "مسدود شده",
"bot": "ربات",
"copy_account_name": "رونوشت از نام حساب",
"favourites": "موارد مورد علاقه",
"follow": "دنبال کنید",
"follow_back": "دنبال کردن متقابل",
"follow_requested": "درخواست شده",
"followers": "دنبال‌کنندگان",
"followers_count": "{0} دنبال‌کننده",
"following": "دنبال‌شده",
"following_count": "{0} در حال دنبال کردن",
"follows_you": "شما را دنبال می‌کند",
"go_to_profile": "به نمایه بروید",
"joined": "پیوسته",
"moved_title": "اعلام کرده که این حساب کاربری جدید ایشان است:",
"muted_users": "کاربران بی‌صدا شده",
"muting": "بی صدا",
"mutuals": "مشترکات",
"notifications_on_post_disable": "دیگر هنگامی که {username} فرسته ای ارسال می‌کند مرا با خبر نکن",
"notifications_on_post_enable": "هنگامی که {username} فرسته ای‌ را ارسال‌ می‌کند مرا با خبر کن",
"pinned": "سنجاق شده",
"posts": "فرسته‌ها",
"posts_count": "{0} فرسته|{0} فرسته|{0} فرسته",
"profile_description": "توضیحات بالای صفحه نمایه {0}",
"profile_personal_note": "یادداشت شخصی",
"profile_unavailable": "نمایه در دسترس نیست",
"reject": "رد درخواست",
"rejected": "درخواست را رد کردید",
"request_follow": "درخواست برای دنبال کردن",
"requested": "{0} درخواست دنبال کردن شما را دارد",
"unblock": "رفع مسدودیت",
"unfollow": "دنبال نکردن",
"unmute": "باصدا",
"view_other_followers": "دنبال‌کنندگان از نمونه‌های دیگر ممکن است نمایش داده نشوند.",
"view_other_following": "دنبال شوندگان از نمونه‌های دیگر ممکن است نمایش داده نشوند.",
"withdraw_follow_request": "درخواست دنبال‌کردن را پس بگیرید"
},
"action": {
"apply": "اعمال",
"bookmark": "نشانک",
"bookmarked": "نشانک زده شده",
"boost": "تقویت",
"boost_count": "{0}",
"boosted": "تقویت شده",
"clear_publish_failed": "پاک کردن خطاهای انتشار",
"clear_save_failed": "پاک کردن خطاهای ذخیره‌سازی",
"clear_upload_failed": "پاک کردن خطاهای بارگذاری فایل",
"close": "بستن",
"compose": "نوشتن",
"confirm": "تایید",
"done": "انجام شد",
"edit": "ویرایش",
"enter_app": "ورود به برنامه",
"favourite": "مورد علاقه",
"favourite_count": "{0}",
"favourited": "به علاقه‌مندی‌ها افزوده شد",
"more": "بیشتر",
"next": "بعدی",
"prev": "قبلی",
"publish": "انتشار",
"reply": "پاسخ",
"reply_count": "{0}",
"reset": "بازنشانی",
"save": "ذخیره",
"save_changes": "ذخیره تغییرات",
"sign_in": "ورود",
"sign_in_to": "ورود به {0}",
"switch_account": "تغییر حساب کاربری",
"vote": "رای"
},
"app_desc_short": "یک کارخواه وب چابک برای ماستودون",
"app_logo": "لوگوی نرم‌افزار",
"app_name": "Elk",
"attachment": {
"edit_title": "توضیحات",
"remove_label": "حذف پیوست"
},
"command": {
"activate": "فعال‌سازی",
"complete": "کامل کردن",
"compose_desc": "نوشتن فرسته جدید",
"n_people_in_the_past_n_days": "{0} نفر در {1} روز گذشته",
"select_lang": "انتخاب زبان",
"sign_in_desc": "افزودن حساب کاربری موجود",
"switch_account": "تغییر به {0}",
"switch_account_desc": "تغییر حساب به حساب دیگری",
"toggle_dark_mode": "تغییر حالت تاریک",
"toggle_zen_mode": "تغییر حالت آرام"
},
"common": {
"end_of_list": "پایان لیست",
"error": "خطا",
"fetching": "در حال بارگیری...",
"in": "در",
"no_bookmarks": "هنوز هیچ فرسته نشانه گذاری شده ای وجود ندارد",
"no_favourites": "فرسته پسندیده شده ای هنوز وجود ندارد",
"not_found": "۴۰۴ پیدا نشد",
"offline_desc": "به نظر می‌رسد شما آفلاین هستید. لطفا اتصال شبکه خود را بررسی کنید."
},
"confirm": {
"block_account": {
"cancel": "لغو",
"confirm": "مسدود کردن",
"title": "آیا از مسدود کردن {0} اطمینان دارید؟"
},
"block_domain": {
"cancel": "لغو",
"confirm": "مسدود کردن",
"title": "آیا از مسدود کردن دامنه {0} اطمینان دارید؟"
},
"common": {
"cancel": "خیر",
"confirm": "بله"
},
"delete_list": {
"cancel": "لغو",
"confirm": "حذف",
"title": "آیا از حذف لیست {0} اطمینان دارید؟"
},
"delete_posts": {
"cancel": "لغو",
"confirm": "حذف",
"title": "آیا از حذف این فرسته اطمینان دارید؟"
},
"mute_account": {
"cancel": "لغو",
"confirm": "بی‌صدا کردن",
"title": "آیا از بی‌صدا کردن {0} اطمینان دارید؟"
},
"show_reblogs": {
"cancel": "لغو",
"confirm": "نمایش",
"title": "آیا می‌خواهید بازنشرها از {0} را نمایش دهید؟"
},
"unfollow": {
"cancel": "لغو",
"confirm": "دنبال نکردن",
"title": "آیا از دنبال نکردن اطمینان دارید؟"
}
},
"conversation": {
"with": "با"
},
"custom_cards": {
"stackblitz": {
"lines": "خطوط {0}",
"open": "باز کردن",
"snippet_from": "تکه کد از {0}"
}
},
"error": {
"account_not_found": "حساب {0} یافت نشد",
"explore_list_empty": "هیچ چیز تازه‌ای وجود ندارد. بعداً بررسی کنید!",
"file_size_cannot_exceed_n_mb": "حجم فایل نمی‌تواند از {0}MB بیشتر باشد",
"sign_in_error": "امکان برقراری ارتباط با سرور وجود ندارد.",
"status_not_found": "فرسته یافت نشد",
"unsupported_file_format": "قالب فایل پشتیبانی نمی‌شود"
},
"help": {
"build_preview": {
"desc1": "شما در حال مشاهده نسخه پیش‌نمایش جامعه نرم‌افزار هستید - {0}.",
"desc2": "ممکن است شامل تغییرات بررسی نشده یا حتی مخرب باشد.",
"desc3": "با حساب کاربری واقعی خود وارد نشوید.",
"title": "استقرار پیش‌نمایش"
},
"desc_highlight": "انتظار برخی اشکالات و ویژگی‌های ناقص را داشته باشید.",
"desc_para1": "از علاقه شما به امتحان کردن نرم‌افزار، کارخواه وب در دست توسعه ماستودون تشکر می‌کنیم!",
"desc_para2": "ما به سختی در حال کار بر روی توسعه و بهبود آن با گذر زمان هستیم.",
"desc_para3": "برای تقویت توسعه، می‌توانید از طریق GitHub Sponsors از تیم حمایت کنید. امیدواریم از نرم‌افزار لذت ببرید!",
"desc_para4": "نرم‌افزار یک منبع باز است. اگر دوست دارید در تست‌کردن، ارائه بازخورد، یا مشارکت کمک کنید،",
"desc_para5": "از طریق GitHub با ما تماس بگیرید",
"desc_para6": "و مشارکت کنید.",
"footer_team": "تیم نرم‌افزار",
"title": "نرم‌افزار در حالت پیش نمایش است!"
},
"language": {
"search": "جستجو"
},
"list": {
"add_account": "اضافه کردن حساب به لیست",
"cancel_edit": "لغو ویرایش",
"clear_error": "پاک کردن خطا",
"create": "ایجاد کردن",
"delete": "حذف این لیست",
"delete_error": "خطایی هنگام حذف لیست رخ داد",
"edit": "ویرایش این لیست",
"edit_error": "خطایی هنگام به‌روزرسانی لیست رخ داد",
"error": "خطایی هنگام ایجاد لیست رخ داد",
"error_prefix": "خطا: ",
"list_title_placeholder": "عنوان لیست",
"modify_account": "تغییر دادن لیست‌ها با حساب کاربری",
"remove_account": "حذف حساب از لیست",
"save": "ذخیره تغییرات"
},
"magic_keys": {
"dialog_header": "میانبرهای صفحه‌کلید",
"groups": {
"actions": {
"boost": "تقویت",
"command_mode": "حالت فرمان",
"compose": "تهیه فرسته",
"favourite": "مورد علاقه",
"search": "جستجو",
"title": "اقدامات"
},
"media": {
"title": "رسانه"
},
"navigation": {
"go_to_home": "خانه",
"go_to_notifications": "اعلان‌ها",
"next_status": "فرسته بعدی",
"previous_status": "فرسته قبلی",
"shortcut_help": "راهنمای میانبرها",
"title": "ناوبری"
}
},
"sequence_then": "در ادامه دنباله"
},
"menu": {
"add_personal_note": "افزودن یادداشت شخصی به {0}",
"block_account": "مسدود کردن {0}",
"block_domain": "مسدود کردن دامنه {0}",
"copy_link_to_post": "کپی لینک این فرسته",
"copy_original_link_to_post": "کپی لینک اصلی این فرسته",
"delete": "حذف",
"delete_and_redraft": "حذف و بازنویسی",
"direct_message_account": "پیام خصوصی {0}",
"edit": "ویرایش",
"hide_reblogs": "پنهان کردن بوست‌ها از {0}",
"mention_account": "ذکر {0}",
"mute_account": "ساکت کردن {0}",
"mute_conversation": "ساکت کردن این فرسته",
"open_in_original_site": "باز کردن در سایت اصلی",
"pin_on_profile": "به نمایه سنجاق کنید",
"remove_personal_note": "یادداشت شخصی را از {0} حذف کنید",
"report_account": "گزارش {0}",
"share_account": "اشتراک‌گذاری {0}",
"share_post": "اشتراک‌گذاری این فرسته",
"show_favourited_and_boosted_by": "نمایش کسانی که پسند و به اشتراک گذاشته‌اند",
"show_reblogs": "نمایش به اشتراک‌گذاری‌ها از {0}",
"show_untranslated": "نمایش بدون ترجمه",
"toggle_theme": {
"dark": "حالت تاریک را تغییر دهید",
"light": "حالت روشن را تغییر دهید"
},
"translate_post": "ترجمه فرسته",
"unblock_account": "رفع انسداد {0}",
"unblock_domain": "رفع انسداد دامنه {0}",
"unfollow_account": "دنبال نکردن {0}",
"unmute_account": "بی‌صدا نکردن {0}",
"unmute_conversation": "بی‌صدا نکردن این فرسته",
"unpin_on_profile": "از سنجاق خارج کردن در نمایه"
},
"modals": {
"aria_label_close": "بستن"
},
"nav": {
"back": "بازگشت",
"blocked_domains": "دامنه‌های مسدود شده",
"blocked_users": "کاربران مسدود شده",
"bookmarks": "نشان‌ها",
"built_at": "ساخته شده {0}",
"compose": "نوشتن",
"conversations": "گفتگوها",
"explore": "کاوش کنید",
"favourites": "موارد مورد علاقه",
"federated": "عمومی",
"home": "خانه",
"list": "لیست",
"lists": "لیست‌ها",
"local": "محلی",
"muted_users": "کاربران با صدای خاموش",
"notifications": "اعلانات",
"privacy": "حریم خصوصی",
"profile": "نمایه",
"search": "جستجو",
"select_feature_flags": "تغییر ویژگی‌های پرچم",
"select_font_size": "اندازه قلم",
"select_language": "زبان نمایش",
"settings": "تنظیمات",
"show_intro": "نمایش مقدمه",
"toggle_theme": "تغییر تم",
"zen_mode": "حالت آرام"
},
"notification": {
"favourited_post": "فرسته شما را پسندید",
"followed_you": "شما را دنبال کرد",
"followed_you_count": "{0} نفر شما را دنبال کردند|{0} نفر شما را دنبال کرد|{0} نفر شما را دنبال کردند",
"missing_type": "اعلان از نوع ناقص:",
"reblogged_post": "فرسته شما را باز نشر کرد",
"reported": "{0} گزارش داد {1}",
"request_to_follow": "درخواست دنبال کردن شما را داد",
"signed_up": "ثبت نام کرد",
"update_status": "فرسته خود را به‌روزرسانی کرد"
},
"placeholder": {
"content_warning": "اخطار خود را اینجا بنویسید",
"default_1": "چه فکری می‌کنید؟",
"reply_to_account": "پاسخ به {0}",
"replying": "در حال پاسخ دادن"
},
"polls": {
"allow_multiple": "امکان انتخاب چندگزینه‌ای",
"cancel": "لغو",
"create": "ایجاد نظرسنجی",
"disallow_multiple": "عدم امکان انتخاب چندگزینه‌ای",
"expiration": "انقضای نظرسنجی",
"hide_votes": "مخفی کردن تعداد آرا تا پایان",
"option_placeholder": "گزینه نظرسنجی {current}/{max}",
"remove_option": "حذف گزینه",
"settings": "تنظیمات نظرسنجی",
"show_votes": "نمایش دائمی تعداد آرا"
},
"pwa": {
"dismiss": "رد کردن",
"install": "نصب کردن",
"install_title": "نصب Elk",
"screenshots": {
"dark": "تصویری از Elk در حالت تیره",
"light": "تصویری از Elk در حالت روشن"
},
"title": "به‌روزرسانی جدید Elk موجود است!",
"update": "به‌روزرسانی",
"update_available_short": "به‌روزرسانی Elk",
"webmanifest": {
"canary": {
"description": "یک مشتری وب سبک و پیشرفته مستودون (canary)",
"name": "Elk (پیش‌انتشار)",
"short_name": "Elk (پیش‌انتشار)"
},
"dev": {
"description": "یک کارخواه سبک و پیشرفته ماستودون (پیش‌نمایش)",
"name": "Elk (dev)",
"short_name": "Elk (dev)"
},
"preview": {
"description": "یک کارخواه وب چابک برای ماستودون (پیش نمایش)",
"name": "نرم‌افزار (پیش نمایش)",
"short_name": "نرم‌افزار (پیش نمایش)"
},
"release": {
"description": "یک کارخواه وب چابک برای ماستودون",
"name": "نرم‌افزار",
"short_name": "نرم‌افزار"
}
}
},
"report": {
"additional_comments": "نظرات اضافی",
"another_server": "کاربری که در حال گزارش آن هستید از سرور دیگری است",
"anything_else": "آیا چیز دیگری هست که فکر می‌کنید ما باید بدانیم؟",
"block_desc": "دیگر فرسته‌های این کاربر را مشاهده نخواهید کرد. آن‌ها نمی‌توانند فرسته‌های شما را ببینند و یا شما را دنبال کنند. آن‌ها قادر خواهند بود درک کنند که مسدود شده‌اند.",
"dontlike": "من دوست ندارم",
"dontlike_desc": "چیزی نیست که مایل به دیدن آن باشید",
"forward": "بله، این گزارش را برای {0} ارسال کنید",
"forward_question": "آیا می‌خواهید یک نسخه ناشناس از این گزارش را نیز برای آن سرور ارسال کنید؟",
"further_actions": {
"limit": {
"description": "در اینجا گزینه‌های شما برای کنترل آنچه می‌بینید موجود است:",
"title": "نمی‌خواهید این را ببینید؟"
},
"report": {
"description": "در حالی که ما این موضوع را بررسی می‌کنیم، در اینجا اقداماتی هست که می‌توانید انجام دهید:",
"title": "از گزارش شما متشکریم، ما به آن رسیدگی خواهیم کرد."
}
},
"limiting": "محدود کردن {0}",
"mute_desc": "دیگر هیچ فرستهی از این کاربر را نخواهید دید. آن‌ها همچنان می‌توانند شما را دنبال کنند و فرسته‌های شما را ببینند. آن‌ها متوجه بی‌صدا شدن نخواهند شد.",
"other": "مورد دیگری است",
"other_desc": "مشکلی که مطرح شده در دسته‌بندی‌های دیگر نمی‌گنجد",
"reporting": "گزارش {0}",
"select_many": "تمام موارد مرتبط را انتخاب کنید:",
"select_one": "بهترین تطابق را انتخاب کنید:",
"select_posts": "آیا فرسته‌هایی وجود دارد که این گزارش را پشتیبانی می‌کند؟",
"select_posts_other": "آیا فرسته‌های دیگری وجود دارد که این گزارش را پشتیبانی می‌کند؟",
"spam": "هرزنامه است",
"spam_desc": "پیوندهای مخرب، تعاملات تقلبی، یا پاسخ‌های تکراری",
"submit": "ارسال گزارش",
"unfollow_desc": "دیگر فرسته‌های این کاربر را در فید خانگی خود نخواهید دید. ممکن است در جاهای دیگر فرسته‌های آن‌ها را ببینید.",
"violation": "یک یا چند قوانین سرور را نقض می‌کند",
"whats_wrong_account": "بگویید چه مشکلی با این حساب کاربری وجود دارد",
"whats_wrong_post": "بگویید چه مشکلی با این فرسته وجود دارد"
},
"search": {
"search_desc": "جستجوی افراد و برچسب‌ها",
"search_empty": "هیچ موردی برای اصطلاحات جستجو شده پیدا نشد"
},
"settings": {
"about": {
"built_at": "ساخته شده در",
"label": "درباره",
"meet_the_team": "آشنایی با تیم",
"sponsor_action": "حمایت از ما",
"sponsor_action_desc": "برای حمایت از تیم توسعه‌دهنده Elk,",
"sponsors": "حامیان",
"sponsors_body_1": "Elk با حمایت سخاوتمندانه و کمک‌ های:",
"sponsors_body_2": "و تمام شرکت‌ها و افرادی که از تیم Elk و اعضاء آن حمایت می‌کنند، امکان‌پذیر شده است.",
"sponsors_body_3": "اگر از برنامه لذت می‌برید، لطفا از ما حمایت کنید:",
"version": "نسخه"
},
"account_settings": {
"description": "تنظیمات حساب کاربری خود را در رابط کاربری ماستودون ویرایش کنید",
"label": "تنظیمات حساب کاربری"
},
"interface": {
"color_mode": "حالت رنگ",
"dark_mode": "تاریک",
"default": " (پیش‌فرض)",
"font_size": "اندازه فونت",
"label": "رابط کاربری",
"light_mode": "روشن",
"system_mode": "سیستم",
"theme_color": "رنگ تم"
},
"language": {
"display_language": "زبان نمایش",
"label": "زبان",
"post_language": "زبان ارسال",
"status": "وضعیت ترجمه: {0}/{1} ({2}٪)",
"translations": {
"add": "اضافه کردن",
"choose_language": "انتخاب زبان",
"heading": "ترجمه‌ها",
"hide_specific": "پنهان کردن ترجمه‌های خاص",
"remove": "حذف کردن"
}
},
"notifications": {
"label": "اعلان‌ها",
"notifications": {
"label": "تنظیمات اعلان‌ها"
},
"push_notifications": {
"alerts": {
"favourite": "مورد علاقه‌ها",
"follow": "دنبال‌کنندگان جدید",
"mention": "اشاره‌ها",
"poll": "نظرسنجی‌ها",
"reblog": "انتشارات",
"title": "کدام اعلان‌ها را دریافت کنیم؟"
},
"description": "اعلان‌ها را حتی زمانی که از Elk استفاده نمی‌کنید دریافت کنید.",
"instructions": "فراموش نکنید که تغییرات خود را با استفاده از دکمه ذخیره تنظیمات اعلان‌های سریع بالا ذخیره کنید!",
"label": "تنظیمات اعلان‌های سریع",
"policy": {
"all": "از همه",
"followed": "از افرادی که دنبال می‌کنم",
"follower": "از افرادی که من را دنبال می‌کنند",
"none": "از هیچ‌کس",
"title": "از چه کسی می‌توانم اعلان‌ها را دریافت کنم؟"
},
"save_settings": "ذخیره تنظیمات",
"subscription_error": {
"clear_error": "پاک کردن خطا",
"error_hint": "می‌توانید به لیست سوالات متداول مراجعه کنید تا مشکل را حل کنید: {0}.",
"invalid_vapid_key": "کلید عمومی VAPID به نظر نامعتبر است.",
"permission_denied": "اجازه دسترسی رد شد: اعلان‌ها را در مرورگر خود فعال کنید.",
"repo_link": "مخزن Elk در گیت‌هاب",
"request_error": "هنگام درخواست اشتراک‌گذاری خطایی رخ داد، دوباره تلاش کنید و اگر مشکل ادامه یافت، لطفاً موضوع را در مخزن Elk گزارش دهید.",
"title": "توانایی اشتراک‌گذاری در اعلان‌های سریع وجود ندارد",
"too_many_registrations": "به دلیل محدودیت‌های مرورگر، Elk نمی‌تواند از سرویس اعلان‌های سریع برای حساب‌های متعدد در سرورهای مختلف استفاده کند. باید از اعلان‌های سریع در یک حساب دیگر لغو اشتراک کنید و دوباره تلاش کنید.",
"vapid_not_supported": "مرورگر شما از اعلان‌های وب پشتیبانی می‌کند، اما به نظر می‌رسد پروتکل VAPID را پیاده‌سازی نمی‌کند."
},
"title": "تنظیمات اعلان‌های سریع",
"undo_settings": "لغو تغییرات",
"unsubscribe": "غیرفعال کردن اعلان‌های سریع",
"unsupported": "مرورگر شما از اعلان‌های سریع پشتیبانی نمی‌کند.",
"warning": {
"enable_close": "بستن",
"enable_description": "برای دریافت اعلان‌ها وقتی Elk باز نیست، اعلان‌های سریع را فعال کنید. شما می‌توانید دقیقاً کنترل کنید که چه نوع تعاملاتی اعلان‌های سریع ایجاد کند از طریق دکمه فوق که بعد از فعال‌سازی نشان داده می‌شود.",
"enable_description_desktop": "برای دریافت اعلان‌ها وقتی Elk باز نیست، اعلان‌های سریع را فعال کنید. شما می‌توانید دقیقاً کنترل کنید که چه نوع تعاملاتی اعلان‌های سریع ایجاد کند در تنظیمات > اعلان‌ها > تنظیمات اعلان‌های سریع پس از فعال‌سازی.",
"enable_description_mobile": "همچنین می‌توانید از منوی ناوبری به تنظیمات > اعلان‌ها > تنظیمات اعلان‌های سریع دسترسی پیدا کنید.",
"enable_description_settings": "برای دریافت اعلان‌ها وقتی Elk باز نیست، اعلان‌های سریع را فعال کنید. شما خواهید توانست دقیقاً کنترل کنید که چه نوع تعاملاتی اعلان‌های سریع ایجاد کند در همین صفحه پس از فعال‌سازی آن‌ها.",
"enable_desktop": "فعال‌سازی اعلان‌های سریع",
"enable_title": "هیچ‌چیزی را از دست ندهید",
"re_auth": "به نظر می‌رسد سرور شما از اعلان‌های سریع پشتیبانی نمی‌کند. خروج و ورود مجدد را امتحان کنید، اگر این پیام همچنان ظاهر شد با مدیر سرور خود تماس بگیرید."
}
},
"show_btn": "رفتن به تنظیمات اعلان‌ها",
"under_construction": "در دست ساخت"
},
"notifications_settings": "اعلان‌ها",
"preferences": {
"embedded_media": "پخش‌کننده رسانه توکار",
"embedded_media_description": "نمایش یک پخش‌کننده توکار به جای کارت پیش‌نمایش معمولی هنگام گسترش پیوندهای رسانه‌ای به اشتراک گذاشته شده.",
"enable_autoplay": "فعال‌سازی خودکارپخش",
"enable_data_saving": "فعال‌سازی صرفه‌جویی در مصرف داده",
"enable_data_saving_description": "صرفه‌جویی در داده‌ها با جلوگیری از بارگذاری خودکار پیوست‌ها.",
"enable_pinch_to_zoom": "فعال‌سازی بزرگنمایی با دو انگشت",
"github_cards": "کارت‌های گیت‌هاب",
"github_cards_description": "هنگام ارسال پیوند گیت‌هاب، یک کارت HTML قابل دسترس با استفاده از نمایش شبکه‌های اجتماعی به نمایش درمی‌آید به جای تصویر اجتماعی.",
"grayscale_mode": "حالت خاکستری",
"hide_account_hover_card": "پنهان کردن کارت شناور حساب",
"hide_alt_indi_on_posts": "پنهان کردن نشانگر جایگزین در فرسته‌ها",
"hide_boost_count": "پنهان کردن شمارش انتشارات",
"hide_favorite_count": "پنهان کردن شمارش موردهای علاقه‌مندی",
"hide_follower_count": "پنهان کردن شمارش دنبال‌کنندگان و دنبال‌شوندگان",
"hide_news": "پنهان کردن خبرها",
"hide_reply_count": "پنهان کردن شمارش پاسخ‌ها",
"hide_translation": "پنهان کردن ترجمه",
"hide_username_emojis": "پنهان کردن اموجی‌های نام کاربری",
"hide_username_emojis_description": "پنهان کردن اموجی‌ها از نام‌های کاربری در زمان خطوط. اموجی‌ها هنوز در نمایه‌های آن‌ها قابل مشاهده خواهند بود.",
"label": "ترجیحات",
"title": "ویژگی‌های تجربی",
"use_star_favorite_icon": "استفاده از نماد ستاره موردهای علاقه‌مندی",
"user_picker": "انتخاب‌کننده کاربر",
"user_picker_description": "نمایش تمام آواتارهای حساب‌های ورود شده در پایین-چپ تا شما بتوانید به سرعت بین آن‌ها تعویض کنید.",
"virtual_scroll": "پیمایش مجازی",
"virtual_scroll_description": "استفاده از لیست مجازی در خطوط زمانی، برای نمایش تعداد بیشتری آیتم با عملکرد بهتر.",
"wellbeing": "سلامتی",
"zen_mode": "حالت آرامش",
"zen_mode_description": "پنهان سازی حواشی مگر آنکه نشانگر موس روی آنها باشد. همچنین پنهان‌سازی بعضی المان‌ها از خط زمانی."
},
"profile": {
"appearance": {
"bio": "بیوگرافی",
"description": "ویرایش آواتار، نام کاربری، نمایه و غیره.",
"display_name": "نام نمایشی",
"label": "ظاهر",
"profile_metadata": "توضیحات نمایه",
"profile_metadata_desc": "شما می‌توانید تا {0} مورد را به صورت جدول در نمایه خود نمایش دهید",
"profile_metadata_label": "برچسب",
"profile_metadata_value": "محتوا",
"title": "ویرایش نمایه"
},
"featured_tags": {
"description": "افراد می‌توانند فرسته‌های عمومی شما را زیر این برچسب‌ها مرور کنند.",
"label": "برچسب‌های برجسته",
"under_construction": "در دست ساخت"
},
"label": "نمایه"
},
"select_a_settings": "یک تنظیم را انتخاب کنید",
"users": {
"export": "صادر کردن توکن‌های کاربر",
"import": "وارد کردن توکن‌های کاربر",
"label": "کاربران وارد شده"
}
},
"share_target": {
"description": "نرم‌افزار را می‌توانید طوری پیکربندی کنید که از سایر برنامه‌ها محتوا را به اشتراک بگذارید، تنها کافیست نرم‌افزار را روی دستگاه یا کامپیوتر خود نصب کرده و وارد شوید.",
"hint": "برای به اشتراک گذاشتن محتوا با نرم‌افزار، باید نرم‌افزار نصب شده باشد و شما وارد حساب کاربری خود شده باشید.",
"title": "به اشتراک گذاشتن با نرم‌افزار"
},
"state": {
"attachments_exceed_server_limit": "تعداد پیوست‌ها از حد مجاز هر فرسته تجاوز کرده است.",
"attachments_limit_error": "حد مجاز فرسته تجاوز شده",
"edited": "(ویرایش شده)",
"editing": "در حال ویرایش",
"loading": "در حال بارگذاری...",
"publish_failed": "انتشار ناموفق بود",
"publishing": "در حال انتشار",
"save_failed": "ذخیره ناموفق بود",
"upload_failed": "بارگذاری ناموفق بود",
"uploading": "در حال بارگذاری..."
},
"status": {
"account": {
"suspended_message": "حساب کاربری این فرسته تعلیق شده است.",
"suspended_show": "با این حال محتوا را نشان دهم؟"
},
"boosted_by": "تقویت شده توسط",
"edited": "ویرایش شده {0}",
"embedded_warning": "پخش این ممکن است آدرس IP شما را برای دیگران آشکار کند.",
"favourited_by": "مورد علاقه توسط",
"filter_hidden_phrase": "مخفی شده توسط فیلتر",
"filter_show_anyway": "با این حال نشان بده",
"img_alt": {
"ALT": "ALT",
"desc": "توصیف",
"dismiss": "رد کردن",
"read": "خواندن توصیف {0}"
},
"poll": {
"count": "{0} رای|{0} رای|{0} رای",
"ends": "پایان {0}",
"finished": "به پایان رسید {0}"
},
"replying_to": "در پاسخ به {0}",
"show_full_thread": "نمایش کامل رشته",
"someone": "یک نفر",
"spoiler_media_hidden": "رسانه مخفی شده",
"spoiler_show_less": "نمایش کمتر",
"spoiler_show_more": "نمایش بیشتر",
"thread": "رشته",
"try_original_site": "سایت اصلی را امتحان کنید"
},
"status_history": {
"created": "ایجاد شده {0}",
"edited": "ویرایش شده {0}"
},
"tab": {
"accounts": "حساب‌ها",
"for_you": "برای شما",
"hashtags": "برچسب‌ها",
"list": "لیست",
"media": "رسانه",
"news": "اخبار",
"notifications_admin": {
"report": "گزارش",
"sign_up": "ثبت نام"
},
"notifications_all": "همه",
"notifications_favourite": "مورد علاقه",
"notifications_follow": "دنبال کردن",
"notifications_follow_request": "درخواست دنبال کردن",
"notifications_mention": "اشاره",
"notifications_more_tooltip": "نوع اعلان‌ها را بر اساس نوع فیلتر کنید",
"notifications_poll": "نظرسنجی",
"notifications_reblog": "بازنشر",
"notifications_status": "وضعیت",
"notifications_update": "بروزرسانی",
"posts": "فرسته‌ها",
"posts_with_replies": "فرسته‌ها و پاسخ‌ها"
},
"tag": {
"follow": "دنبال کردن",
"follow_label": "دنبال کردن برچسب {0}",
"unfollow": "انصراف از دنبال کردن",
"unfollow_label": "انصراف از دنبال کردن برچسب {0}"
},
"time_ago_options": {
"day_future": "در 0 روز|فردا|در {n} روز",
"day_past": "0 روز پیش|دیروز|{n} روز پیش",
"hour_future": "در 0 ساعت|در 1 ساعت|در {n} ساعت",
"hour_past": "0 ساعت پیش|1 ساعت پیش|{n} ساعت پیش",
"just_now": "همین الان",
"minute_future": "در 0 دقیقه|در 1 دقیقه|در {n} دقیقه",
"minute_past": "0 دقیقه پیش|1 دقیقه پیش|{n} دقیقه پیش",
"month_future": "در 0 ماه|ماه بعد|در {n} ماه",
"month_past": "0 ماه پیش|ماه گذشته|{n} ماه پیش",
"second_future": "همین الان|در {n} ثانیه|در {n} ثانیه",
"second_past": "همین الان|{n} ثانیه پیش|{n} ثانیه پیش",
"short_day_future": "در {n}روز",
"short_day_past": "{n}روز",
"short_hour_future": "در {n}س",
"short_hour_past": "{n}س",
"short_minute_future": "در {n}دقیقه",
"short_minute_past": "{n}دقیقه",
"short_month_future": "در {n}م",
"short_month_past": "{n}م",
"short_second_future": "در {n}ث",
"short_second_past": "{n}ث",
"short_week_future": "در {n}هفته",
"short_week_past": "{n}هفته",
"short_year_future": "در {n}سال",
"short_year_past": "{n}سال",
"week_future": "در 0 هفته|هفته بعد|در {n} هفته",
"week_past": "0 هفته پیش|هفته گذشته|{n} هفته پیش",
"year_future": "در 0 سال|سال بعد|در {n} سال",
"year_past": "0 سال پیش|سال گذشته|{n} سال پیش"
},
"timeline": {
"show_new_items": "نمایش {v} مورد جدید|نمایش {v} مورد جدید|نمایش {v} مورد جدید",
"view_older_posts": "فرسته‌های قدیمی‌تر از دیگر موارد ممکن است نمایش داده نشوند."
},
"title": {
"federated_timeline": "جریان اتحادی",
"local_timeline": "جریان محلی"
},
"tooltip": {
"add_content_warning": "اضافه کردن هشدار محتوا",
"add_emojis": "اضافه کردن شکلک‌ها",
"add_media": "اضافه کردن تصاویر، ویدیو یا فایل صوتی",
"add_publishable_content": "اضافه کردن محتوای قابل انتشار",
"change_content_visibility": "تغییر دیده‌بانی محتوا",
"change_language": "تغییر زبان",
"emoji": "شکلک",
"explore_links_intro": "این داستان‌های خبری، در حال حاضر توسط افراد در این و دیگر نمونه‌های شبکه غیرمتمرکز مورد بحث قرار می‌گیرد.",
"explore_posts_intro": "این فرسته‌ها از این و دیگر نمونه‌های در شبکه غیرمتمرکز هم اکنون در این سرور محبوبیت دارند.",
"explore_tags_intro": "این برچسب‌ها در حال حاضر میان افراد در این و دیگر سرورهای شبکه غیرمتمرکز مشهور شده‌اند.",
"open_editor_tools": "ابزار ویراستار",
"pick_an_icon": "انتخاب یک آیکون",
"publish_failed": "پیام‌های ناموفق را در بالای ویرایشگر ببندید تا مجدد فرسته‌ها را انتشار دهید",
"toggle_bold": "تغییر به حالت توپر",
"toggle_code_block": "تغییر به بلوک کد",
"toggle_italic": "تغییر به حالت کج"
},
"user": {
"add_existing": "اضافه کردن حساب کاربری موجود",
"server_address_label": "آدرس سرور ماستودون",
"sign_in_desc": "برای دنبال کردن نمایه‌ها یا برچسب‌ها، پسندیدن، به اشتراک‌گذاری و پاسخ دادن به فرسته‌ها وارد شوید، یا از حساب کاربری خود در سرور دیگر ارتباط برقرار کنید.",
"sign_in_notice_title": "مشاهده داده‌های عمومی {0}",
"sign_out_account": "خروج از حساب کاربری {0}",
"single_instance_sign_in_desc": "برای دنبال کردن نمایه‌ها یا برچسب‌ها، پسندیدن، به اشتراک‌گذاری و پاسخ دادن به فرسته‌ها وارد شوید.",
"tip_no_account": "اگر هنوز حساب کاربری ماستودون ندارید، {0}.",
"tip_register_account": "سرور خود را انتخاب کرده و یکی بسازید"
},
"visibility": {
"direct": "مستقیم",
"direct_desc": "فقط برای کاربران منشن‌شده قابل مشاهده",
"private": "فقط دنبال‌کنندگان",
"private_desc": "فقط برای دنبال‌کنندگان قابل مشاهده",
"public": "عمومی",
"public_desc": "برای همه قابل مشاهده",
"unlisted": "فهرست نشده",
"unlisted_desc": "برای همه قابل مشاهده اما از ویژگی‌های کشف خارج شده‌است"
}
}

Wyświetl plik

@ -214,8 +214,7 @@
"command_mode": "Mode commande",
"compose": "Composer",
"favourite": "J'aime",
"title": "Actions",
"zen_mode": "Mode Zen"
"title": "Actions"
},
"media": {
"title": "Média"
@ -550,9 +549,6 @@
"label": "Comptes connectés"
}
},
"share-target": {
"title": ""
},
"share_target": {
"description": "Elk peut être configuré pour que vous puissiez partager du contenu à partir d'autres applications, installez simplement Elk sur votre appareil ou ordinateur et connectez-vous.",
"hint": "Pour partager du contenu avec Elk, Elk doit être installé et vous devez être connecté.",
@ -605,7 +601,6 @@
"edited": "a édité {0}"
},
"tab": {
"account": "Compte",
"accounts": "Comptes",
"for_you": "Pour vous",
"hashtags": "Hashtags",

Wyświetl plik

@ -94,7 +94,6 @@
"activate": "Aktivál",
"complete": "Befejez",
"compose_desc": "Új bejegyzés írása",
"n-people-in-the-past-n-days": "{0} felhasználó az elmúlt {1} napban",
"select_lang": "Nyelv kiválasztása",
"sign_in_desc": "Létező fiók hozzáadása",
"switch_account": "Váltás: {0}",
@ -169,7 +168,6 @@
},
"error": {
"account_not_found": "Fiók {0} nem található",
"explore_list-empty": "Nincs most itt semmi... Nézz vissza később!",
"file_size_cannot_exceed_n_mb": "A fájl mérete nem haladhatja meg a {0}MB-ot",
"sign_in_error": "Nem lehetséges a csatlakozás.",
"status_not_found": "A bejegyzés nem található",
@ -557,11 +555,6 @@
"label": "Bejelentkezett felhasználók"
}
},
"share-target": {
"description": "Az Elk konfigurálható úgy, hogy más alkalmazásokból is megoszthasson tartalmat, egyszerűen telepítse az Elket eszközére vagy számítógépére, és jelentkezzen be.",
"hint": "A tartalom Elkkel való megosztásához telepíteni kell az Elket, és be kell jelentkeznie.",
"title": "Megosztás Elkkel"
},
"state": {
"attachments_exceed_server_limit": "A mellékletek száma meghaladta a bejegyzésenkénti korlátot.",
"attachments_limit_error": "Túllépte a bejegyzésenkénti korlátot",

Wyświetl plik

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Annulla",
"confirm": "Silenzia",
"days": "giorni|giorno|giorni",
"description": "Confermi di voler silenziare {0}?",
"hours": "ore|ora|ore",
"minute": "minuti|minuto|minuti",
"notifications": "Silenzia notifiche",
"specify_duration": "Specifica durata silenziamento",
"title": "Silenzia account"
},
"show_reblogs": {
@ -304,6 +309,7 @@
"explore": "Esplora",
"favourites": "Preferiti",
"federated": "Federata",
"hashtags": "Hashtag",
"home": "Home",
"list": "Lista",
"lists": "Liste",
@ -536,6 +542,7 @@
"hide_follower_count": "Nascondi contatore seguaci/seguiti",
"hide_news": "Nascondi notizie",
"hide_reply_count": "Nascondi contatore risposte",
"hide_tag_hover_card": "Nascondi anteprima tag al passaggio del mouse",
"hide_translation": "Nascondi traduzione",
"hide_username_emojis": "Nascondi emoji dai nomi utente",
"hide_username_emojis_description": "Nasconde le emoji all'interno dei nomi utente nella cronologia. Le emoji saranno comunque visibili nelle pagine dei profili.",

Wyświetl plik

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Cancelar",
"confirm": "Silenciar",
"days": "dias|dia|dias",
"description": "Tem a certeza que pretende silenciar {0}?",
"hours": "horas|hora|horas",
"minute": "minutos|minuto|minutos",
"notifications": "Silenciar notificações",
"specify_duration": "Especificar duração do silêncio",
"title": "Silenciar conta"
},
"show_reblogs": {
@ -226,16 +231,27 @@
"boost": "Partilhar",
"command_mode": "Menu de comandos",
"compose": "Compor",
"favourite": "Adcionar aos favoritos",
"favourite": "Adicionar aos favoritos",
"search": "Pesquisar",
"show_new_items": "Mostrar novos itens",
"title": "Ações"
},
"media": {
"title": "Media"
},
"navigation": {
"go_to_bookmarks": "Itens Salvos",
"go_to_conversations": "Conversas",
"go_to_explore": "Explorar",
"go_to_favourites": "Favoritos",
"go_to_federated": "Federada",
"go_to_home": "Início",
"go_to_lists": "Listas",
"go_to_local": "Local",
"go_to_notifications": "Notificações",
"go_to_profile": "Perfil",
"go_to_search": "Pesquisa",
"go_to_settings": "Definições",
"next_status": "Publicação seguinte",
"previous_status": "Publicação anterior",
"shortcut_help": "Lista de atalhos",
@ -293,6 +309,7 @@
"explore": "Explorar",
"favourites": "Favoritos",
"federated": "Federada",
"hashtags": "Hashtags",
"home": "Início",
"list": "Lista",
"lists": "Listas",
@ -525,6 +542,7 @@
"hide_follower_count": "Esconder contagem de seguidores",
"hide_news": "Esconder notícias",
"hide_reply_count": "Esconder contagem de respostas",
"hide_tag_hover_card": "Esconder cartão flutuante de hashtag",
"hide_translation": "Esconder botão de tradução",
"hide_username_emojis": "Esconder emojis do nome de utilizador",
"hide_username_emojis_description": "Esconde os emojis do nome de utilizador nas cronologias. Os Emojis continuarão a ser visíveis nos seus perfis.",

Wyświetl plik

@ -7,6 +7,8 @@
"route_loaded": "Naloload na ang pahina {0}"
},
"account": {
"authorize": "Pahintulutan na sumunod",
"authorized": "Pinahintulutan mo ang kahilingan",
"avatar_description": "Avatar ni {0}",
"blocked_by": "Ika'y na-block ng user na ito.",
"blocked_domains": "Mga naka-block na domain",
@ -25,6 +27,7 @@
"follows_you": "Sinusundan ka",
"go_to_profile": "Pumunta sa profile",
"joined": "Sumali",
"lock": "Ikandado",
"moved_title": "nagpahiwatig na ang kanilang bagong account ay:",
"muted_users": "Mga naka-mute na user",
"muting": "Naka-mute",
@ -37,36 +40,42 @@
"profile_description": "Header ng profile ni {0}",
"profile_personal_note": "Personal na Tala",
"profile_unavailable": "Hindi magamit ang profile",
"reject": "Tanggihan na sumunod",
"rejected": "Tinanggihan mo ang kahilingan",
"request_follow": "Humiling ng pagsunod",
"requested": "{0} ay humiling na sundan ka",
"unblock": "Tanggalin ang pagka-block",
"unfollow": "Huminto sa pagsunod",
"unmute": "Tanggalin ang pagka-mute",
"view_other_followers": "Ang mga tagasunod mula sa ibang mga instance ay hindi maipapakita.",
"view_other_following": "Ang mga sinusundan mula sa ibang mga instance ay hindi maipapakita."
"view_other_following": "Ang mga sinusundan mula sa ibang mga instance ay hindi maipapakita.",
"withdraw_follow_request": "Bawiin ang kahilingan na sumunod"
},
"action": {
"apply": "Mag-apply",
"bookmark": "I-bookmark",
"bookmarked": "Nai-bookmark na",
"boost": "I-boost",
"boost_count": "{0} ang nag-boost",
"boost_count": "{0} nag-boost",
"boosted": "Nai-boost na",
"clear_publish_failed": "Tanggalin ang mga error sa pag-publish",
"clear_upload_failed": "Tanggalin ang mga error sa pag-upload ng file",
"clear_publish_failed": "I-clear ang mga error sa pag-publish",
"clear_save_failed": "I-clear ang mga error sa pag-save",
"clear_upload_failed": "I-clear ang mga error sa pag-upload ng file",
"close": "Isara",
"compose": "Mag-compose",
"confirm": "Kumpirmahin",
"done": "Tapos na",
"edit": "I-edit",
"enter_app": "Tumuloy sa App",
"favourite": "I-favorite",
"favourite_count": "{0} ang nag-favorite",
"favourite_count": "{0} nag-favorite",
"favourited": "Nai-favorite na",
"more": "Iba pa",
"next": "Susunod",
"prev": "Nakaraan",
"publish": "I-publish",
"reply": "Sumagot",
"reply_count": "{0} ang sumagot",
"reply_count": "{0} sumagot",
"reset": "I-reset",
"save": "I-save",
"save_changes": "I-save ang mga pagbabago",
@ -99,6 +108,8 @@
"error": "ERROR",
"fetching": "Kumukuha...",
"in": "sa",
"no_bookmarks": "Wala pang naka-bookmark na mga post",
"no_favourites": "Wala pang ni-like na post",
"not_found": "404 Hindi Nakita",
"offline_desc": "Mukhang offline ka. Mangyaring suriin ang iyong koneksyon sa network."
},
@ -110,12 +121,14 @@
"block_account": {
"cancel": "Kanselahin",
"confirm": "I-block",
"description": "Sigurado ka bang gusto mong i-block si {0}?"
"description": "Sigurado ka bang gusto mong i-block si {0}?",
"title": "I-block ang account"
},
"block_domain": {
"cancel": "Kanselahin",
"confirm": "I-block",
"description": "Sigurado ka bang gusto mong i-block ang {0}?"
"description": "Sigurado ka bang gusto mong i-block ang {0}?",
"title": "I-block ang domain"
},
"common": {
"cancel": "Hindi",
@ -124,27 +137,37 @@
"delete_list": {
"cancel": "Kanselahin",
"confirm": "Burahin",
"description": "Sigurado ka bang gusto mong burahin ang listahan na \"{0}\"?"
"description": "Sigurado ka bang gusto mong burahin ang listahan na \"{0}\"?",
"title": "I-delete ang list"
},
"delete_posts": {
"cancel": "Kanselahin",
"confirm": "Burahin",
"description": "Sigurado ka bang gusto mong burahin ang post na ito?"
"description": "Sigurado ka bang gusto mong burahin ang post na ito?",
"title": "I-delete post"
},
"mute_account": {
"cancel": "Kanselahin",
"confirm": "I-mute",
"description": "Sigurado ka bang gusto mong i-mute si {0}?"
"days": "mga araw|araw|mga araw",
"description": "Sigurado ka bang gusto mong i-mute si {0}?",
"hours": "mga oras|oras|mga oras",
"minute": "mga minuto|minuto|mga minuto",
"notifications": "I-mute ang notifications",
"specify_duration": "Tukuyin ang tagal ng pag-mute",
"title": "I-mute ang account"
},
"show_reblogs": {
"cancel": "Kanselahin",
"confirm": "Ipakita",
"description": "Sigurado ka bang gusto mong ipakita ang mga boosts mula kay {0}?"
"description": "Sigurado ka bang gusto mong ipakita ang mga boosts mula kay {0}?",
"title": "Ipakita ang boosts"
},
"unfollow": {
"cancel": "Kanselahin",
"confirm": "Huminto sa pagsunod",
"description": "Sigurado ka bang gusto mong huminto sa pagsunod?"
"confirm": "Itigil ang pagsunod",
"description": "Sigurado ka bang gusto mong huminto sa pagsunod?",
"title": "Itigil ang pagsunod"
}
},
"conversation": {
@ -196,7 +219,7 @@
"edit_error": "Mayroong error sa pag-update ng listahan",
"error": "Mayroong error sa paglikha ng listahan",
"error_prefix": "Error: ",
"list_title_placeholder": "Pamagat ng listahan",
"list_title_placeholder": "Pangalan ng listahan",
"modify_account": "Baguhin ang mga listahan sa account",
"remove_account": "Tanggalin ang account sa listahan",
"save": "I-save ang mga pagbabago"
@ -209,24 +232,36 @@
"command_mode": "Mode ng Command",
"compose": "Mag-compose",
"favourite": "Paborito",
"search": "Hanapin",
"show_new_items": "Ipakita ang mga bagong item",
"title": "Mga aksyon"
},
"media": {
"title": "Media"
},
"navigation": {
"go_to_bookmarks": "Mga Tandang-Pahina",
"go_to_conversations": "Mga Usapang Pribado",
"go_to_explore": "Mag-Explore",
"go_to_favourites": "Mga Paborito",
"go_to_federated": "Pederal",
"go_to_home": "Tungo sa Home",
"go_to_lists": "Mga Listahan",
"go_to_local": "Lokal",
"go_to_notifications": "Tungo sa mga Abiso",
"go_to_profile": "Profile",
"go_to_search": "Hanapin",
"go_to_settings": "Mga Setting",
"next_status": "Susunod na status",
"previous_status": "Nakaraang status",
"shortcut_help": "Tulong sa shortcut",
"title": "Pag-navigate"
}
},
"sequence_then": "pagkatapos"
"sequence_then": "tapos"
},
"menu": {
"add_personal_note": "Magdagdag ng personal na note sa {0}",
"add_personal_note": "Sumulat ng personal na tala",
"block_account": "I-block si {0}",
"block_domain": "I-block ang domain ng {0}",
"copy_link_to_post": "Kopyahin ang link",
@ -236,12 +271,14 @@
"direct_message_account": "I-message ng direkta si {0}",
"edit": "I-edit",
"hide_reblogs": "Itago ang mga boost mula kay {0}",
"mention_account": "Banggitin si {0}",
"mention_account": "Tumugon kay {0}",
"mute_account": "I-mute si {0}",
"mute_conversation": "I-mute ang post na ito",
"open_in_original_site": "Buksan sa orihinal na site",
"pin_on_profile": "I-pin sa profile",
"remove_personal_note": "Tanggalin ang personal na note sa {0}",
"remove_personal_note": "Tanggalin ang personal na tala",
"report_account": "I-report si {0}",
"share_account": "I-share si {0}",
"share_post": "I-share ang post na ito",
"show_favourited_and_boosted_by": "Ipakita ang mga nag-favorite at nag-boost",
"show_reblogs": "Ipakita ang mga boost mula kay {0}",
@ -253,6 +290,7 @@
"translate_post": "I-translate ang post",
"unblock_account": "I-unblock ang {0}",
"unblock_domain": "I-unblock ang domain ng {0}",
"unfollow_account": "Unfollow {0}",
"unmute_account": "I-unmute si {0}",
"unmute_conversation": "I-unmute ang post na ito",
"unpin_on_profile": "I-unpin sa profile"
@ -265,12 +303,13 @@
"blocked_domains": "Mga Naka-Block na Domain",
"blocked_users": "Mga Naka-Block na Users",
"bookmarks": "Mga Tandang-Pahina",
"built_at": "Ginawa noong {0}",
"built_at": "Build version mula noong {0}",
"compose": "Lumikha ng Mensahe",
"conversations": "Mga Usapang Pribado",
"explore": "Mag-Explore",
"favourites": "Mga Paborito",
"federated": "Pederal",
"hashtags": "Mga Hashtags",
"home": "Tahanan",
"list": "Listahan",
"lists": "Mga Listahan",
@ -304,10 +343,26 @@
"reply_to_account": "Sagot kay {0}",
"replying": "Sumasagot"
},
"polls": {
"allow_multiple": "Payagan ang maramihang pagboto",
"cancel": "Kanselahin",
"create": "Likhain ang poll",
"disallow_multiple": "Huwag payagan ang maramihang pagboto",
"expiration": "Katapusan ng pagboto",
"hide_votes": "Itago ang bilang ng mga boto hanggang sa katapusan",
"option_placeholder": "Poll choice {current}/{max}",
"remove_option": "Remove choice",
"settings": "Poll options",
"show_votes": "Always show vote totals"
},
"pwa": {
"dismiss": "I-dismiss",
"install": "I-install",
"install_title": "I-install ang Elk",
"screenshots": {
"dark": "Screenshot of Elk running in dark mode",
"light": "Screenshot of Elk running in light mode"
},
"title": "May bagong update para sa Elk!",
"update": "I-update",
"update_available_short": "I-update ang Elk",
@ -334,6 +389,42 @@
}
}
},
"report": {
"additional_comments": "Karagdagang mga komento",
"another_server": "Ang user na iyong inire-report ay mula sa ibang server",
"anything_else": "May iba pa ba kaming kailangan malaman?",
"block_desc": "Hindi mo na makikita ang mga post mula sa user na ito. Hindi rin nila masusundan ang iyong account o makikita ang iyong mga post. Malalaman nilang naka-block sila.",
"dontlike": "Hindi ko ito gusto",
"dontlike_desc": "Hindi mo ito gustong makita",
"forward": "Oo, ipasa ang report na ito sa {0}",
"forward_question": "Gusto mo bang magpadala din ng anonymous na kopya ng report na ito sa server na iyon?",
"further_actions": {
"limit": {
"description": "Narito ang iyong mga pwedeng gawin upang ma-control iyong nakikita:",
"title": "Ayaw mong makita ito?"
},
"report": {
"description": "Habang sinusuri namin ang iyong report, narito ang mga maaari mong gawin:",
"title": "Salamat sa pag-report, titingnan namin ito"
}
},
"limiting": "Inili-limit {0}",
"mute_desc": "Hindi mo na makikita ang mga post mula sa user na ito. Maaari ka pa rin nilang sundan at makita ang iyong mga post. Hindi nila malalaman na sila ay naka-mute",
"other": "Iba ang aking dahilan",
"other_desc": "Ang isyu ay hindi umaangkop sa mga nabanggit na kategorya",
"reporting": "Pag-report si {0}",
"select_many": "Piliin ang lahat ng tugma:",
"select_one": "Piliin ang pinaka-tugma:",
"select_posts": "Mayroon bang mga post na nagba-back up sa report na ito?",
"select_posts_other": "Mayroon pa bang mga post na nagba-back up sa report na ito?",
"spam": "Ito ay spam",
"spam_desc": "May mga malicious na link, pekeng engagement, o paulit-ulit na reply",
"submit": "I-sumite ang report",
"unfollow_desc": "Hindi mo na makikita ang mga post mula sa user na ito sa iyong feed na Tahanan. Maaari ka pa ring makakita ng mga post mula sa kanila sa ibang lugar.",
"violation": "Lumalabag ito sa mga rules ng server",
"whats_wrong_account": "Sabihin sa amin kung ano ang mali sa account na ito",
"whats_wrong_post": "Sabihin sa amin kung ano ang mali sa post na ito"
},
"search": {
"search_desc": "Maghanap ng mga tao at hashtag",
"search_empty": "Walang nahanap para sa mga terminong ito"
@ -368,6 +459,7 @@
"language": {
"display_language": "Ipakita ang Wika",
"label": "Wika",
"post_language": "Posting Language",
"status": "Kalagayan ng Pagsasalin: {0}/{1} ({2}%)",
"translations": {
"add": "Magdagdag",
@ -386,7 +478,7 @@
"alerts": {
"favourite": "Mga Paborito",
"follow": "Mga Bagong Tagasunod",
"mention": "Mga Mention",
"mention": "Mga Tugon",
"poll": "Mga Poll",
"reblog": "Mga Reblog ng iyong Post",
"title": "Anong mga abiso ang nais mong matanggap?"
@ -433,25 +525,33 @@
},
"notifications_settings": "Mga Notification",
"preferences": {
"embedded_media": "Naka-Embed na Media Player",
"embedded_media_description": "Magpakita ng naka-embed na player sa halip na preview card para sa mga post na may media streaming.",
"enable_autoplay": "Paganahin ang Autoplay",
"enable_data_saving": "Paganahin ang pag-save ng data",
"enable_data_saving_description": "I-save ang data sa pamamagitan ng pagpigil sa mga attachment na auto-loading.",
"enable_pinch_to_zoom": "Paganahin ang pinch-to-zoom",
"github_cards": "Mga Card ng GitHub",
"github_cards_description": "Kapag may post na GitHub link, ipakita ang isang HTML preview card na naglalaman ng social graph meta sa halip na ang social image.",
"grayscale_mode": "Grayscale mode",
"hide_account_hover_card": "Itago ang account hover card",
"hide_alt_indi_on_posts": "Itago ang alt indicator sa mga post",
"hide_boost_count": "Itago ang boost count",
"hide_favorite_count": "Itago ang favorite count",
"hide_follower_count": "Itago ang following/follower count",
"hide_news": "Itago ang mga balita",
"hide_reply_count": "Itago ang reply count",
"hide_tag_hover_card": "Itago ang tag hover card",
"hide_translation": "Itago ang translation",
"hide_username_emojis": "Itago ang username emojis",
"hide_username_emojis_description": "Itinatago ang mga emojis mula sa mga usernames sa timelines. Makikita pa rin ang mga emojis sa kanilang mga profile.",
"label": "Mga Nais",
"optimize_for_low_performance_device": "I-optimize para sa device na mabagal",
"title": "Mga Experimental na Tampok",
"user_picker": "User Picker",
"virtual_scroll": "Virtual Scrolling",
"use_star_favorite_icon": "Gumamit ng star na icon para sa pag-paborito",
"user_picker": "Pagpipilian na mga Account",
"user_picker_description": "Ipakita ang mga avatar ng mga naka-login na account sa kaliwang ibaba para makalipat sa mga ito.",
"virtual_scroll": "Virtual na Scrolling",
"wellbeing": "Kalusugan at Kagalingan",
"zen_mode": "Modong Zen",
"zen_mode_description": "Itago ang ibang mga elemento sa timeline at mga asides maliban kung naka-focus ang mouse cursor sa kanila."
@ -495,6 +595,7 @@
"loading": "Nagloload...",
"publish_failed": "Nabigo sa pagpapaskil",
"publishing": "Nagpapaskil",
"save_failed": "Nabigo ang pag-save",
"upload_failed": "Nabigo sa pag-upload",
"uploading": "Naguuupload..."
},
@ -503,8 +604,9 @@
"suspended_message": "Ang account ng status na ito ay nakasuspinde.",
"suspended_show": "Ipakita pa rin ang nilalaman?"
},
"boosted_by": "Binuhay muli ni",
"boosted_by": "Ini-boost ni",
"edited": "Naedit {0}",
"embedded_warning": "Ang pag-play nito ay maaaring magbunyag ng iyong IP address sa iba.",
"favourited_by": "Pumaborito si",
"filter_hidden_phrase": "Nakafilter dahil sa",
"filter_show_anyway": "Ipakita pa rin",
@ -539,8 +641,20 @@
"list": "Listahan",
"media": "Media",
"news": "Balita",
"notifications_admin": {
"report": "Mga Report",
"sign_up": "Mga Sign-Up"
},
"notifications_all": "Lahat",
"notifications_mention": "Mention",
"notifications_favourite": "Mga Paborito",
"notifications_follow": "Mga Pagsunod",
"notifications_follow_request": "Mga Hiling ng Pagsunod",
"notifications_mention": "Mga Tugon",
"notifications_more_tooltip": "I-filter ang mga notification ayon sa uri",
"notifications_poll": "Mga Poll",
"notifications_reblog": "Mga Boost",
"notifications_status": "Mga Sinusundang Status",
"notifications_update": "Mga Update",
"posts": "Mga Post",
"posts_with_replies": "Mga Post at Mga Tugon"
},

Wyświetl plik

@ -89,7 +89,10 @@
"common": {
"end_of_list": "Кінець списку",
"error": "ПОМИЛКА",
"fetching": "Завантаження...",
"in": "в",
"no_bookmarks": "Немає збережених дописів",
"no_favourites": "Немає вподобаних дописів",
"not_found": "404 Не знайдено",
"offline_desc": "Схоже, ви відключені від мережі. Будь ласка, перевірте ваше підключення до мережі."
},
@ -98,14 +101,51 @@
"drafts": "Чернетки ({v})"
},
"confirm": {
"block_account": {
"cancel": "Скасувати",
"confirm": "Блокувати",
"description": "Ви впевнені, що бажаєте заблокувати {0}?",
"title": "Заблокувати користувача"
},
"block_domain": {
"cancel": "Скасувати",
"confirm": "Блокувати",
"description": "Ви впевнені, що бажаєте заблокувати {0}?",
"title": "Заблокувати домен"
},
"common": {
"cancel": "Відмінити",
"cancel": "Скасувати",
"confirm": "Так"
},
"delete_list": {
"cancel": "Скасувати",
"confirm": "Видалити",
"description": "Ви впевнені, що бажаєте видалити список \"{0}\"?",
"title": "Видалити список"
},
"delete_posts": {
"cancel": "Скасувати",
"confirm": "Видалити",
"description": "Ви впевнені, що хочете видалити цей допис?"
"description": "Ви впевнені, що хочете видалити цей допис?",
"title": "Видалити допис"
},
"mute_account": {
"cancel": "Скасувати",
"confirm": "Приховати",
"description": "Ви впевнені, що бажаєте приховати {0}?",
"title": "Приховати обліковий запис"
},
"show_reblogs": {
"cancel": "Скасувати",
"confirm": "Показати",
"description": "Ви впевнені, що хочете показати поширення від {0}?",
"title": "Показати поширення"
},
"unfollow": {
"cancel": "Скасувати",
"confirm": "Відписатися",
"description": "Ви впевнені, що бажаєте відписатися від {0}?",
"title": "Відписатися"
}
},
"conversation": {
@ -127,25 +167,86 @@
"desc_para4": "До цього, якщо ви хочете допомогти з тестуванням, надіслати відгук або зробити внесок,",
"desc_para5": "зв’яжіться з нами на GitHub",
"desc_para6": "і долучіться.",
"footer_team": "Команда Elk",
"title": "Elk у попередньому перегляді!"
},
"language": {
"search": "Пошук"
},
"list": {
"add_account": "Додати обліковий запис до списку",
"cancel_edit": "Скасувати редагування",
"clear_error": "Очистити помилку",
"create": "Створити",
"delete": "Видалити список",
"delete_error": "Під час видалення списку сталася помилка",
"edit": "Редагувати список",
"edit_error": "Під час редагування списку сталася помилка",
"error": "Під час створення списку сталася помилка",
"error_prefix": "Помилка:",
"list_title_placeholder": "Назва списку",
"modify_account": "Редагувати списки з цим обліковим записом",
"remove_account": "Видалити обліковий запис зі списку",
"save": "Зберегти зміни"
},
"magic_keys": {
"dialog_header": "Гарячі клавіші",
"groups": {
"actions": {
"boost": "Поширити",
"command_mode": "Командний режим",
"compose": "Написати",
"favourite": "Вподобати",
"search": "Пошук",
"show_new_items": "Показати нові елементи",
"title": "Дії"
},
"media": {
"title": "Медіа"
},
"navigation": {
"go_to_bookmarks": "Закладки",
"go_to_conversations": "Розмови",
"go_to_explore": "Огляд",
"go_to_favourites": "Вподобане",
"go_to_federated": "Глобальна",
"go_to_home": "Головна",
"go_to_lists": "Списки",
"go_to_local": "Локальна",
"go_to_notifications": "Сповіщення",
"go_to_profile": "Профіль",
"go_to_search": "Пошук",
"go_to_settings": "Налаштування",
"next_status": "Наступний допис",
"previous_status": "Попередній допис",
"shortcut_help": "Допомога з гарячими клавішами",
"title": "Навігація"
}
},
"sequence_then": "потім"
},
"menu": {
"add_personal_note": "Додати нотатку до {0}",
"block_account": "Заблокувати {0}",
"block_domain": "Заблокувати домен {0}",
"copy_link_to_post": "Скопіювати посилання на цей допис",
"copy_original_link_to_post": "Скопіювати оригінальне посилання на цей допис",
"delete": "Видалити",
"delete_and_redraft": "Видалити і переписати",
"direct_message_account": "Пряме повідомлення {0}",
"edit": "Редагувати",
"hide_reblogs": "Приховати поширення від {0}",
"mention_account": "Згадати {0}",
"mute_account": "Приховати {0}",
"mute_conversation": "Ігнорувати цей допис",
"open_in_original_site": "Відкрити на оригінальному сайті",
"pin_on_profile": "Закріпити на профілі",
"remove_personal_note": "Вилучити нотатку з {0}",
"report_account": "Повідомити про зловживання {0}",
"share_account": "Поділитися {0}",
"share_post": "Поділіться цим дописом",
"show_favourited_and_boosted_by": "Показати, хто вподобав та поширив",
"show_reblogs": "Показати поширення від {0}",
"show_untranslated": "Показати без перекладу",
"toggle_theme": {
"dark": "Увімкнути темний режим",
@ -154,6 +255,7 @@
"translate_post": "Перекласти допис",
"unblock_account": "Розблокувати {0}",
"unblock_domain": "Розблокувати домен {0}",
"unfollow_account": "Скасувати підписку на {0}",
"unmute_account": "Не приховувати {0}",
"unmute_conversation": "Не ігнорувати цей допис",
"unpin_on_profile": "Відкріпити з профілю"
@ -164,14 +266,19 @@
"blocked_users": "Заблоковані користувачі",
"bookmarks": "Закладки",
"built_at": "Оновлено {0}",
"conversations": "Прямі повідомлення",
"compose": "Написати",
"conversations": "Розмови",
"explore": "Огляд",
"favourites": "Вподобане",
"federated": "Глобальна",
"federated": "Глобальна стрічка",
"hashtags": "Хештеґи",
"home": "Головна",
"local": "Локальна",
"list": "Список",
"lists": "Списки",
"local": "Локальна стрічка",
"muted_users": "Приховані користувачі",
"notifications": "Сповіщення",
"privacy": "Конфіденційність",
"profile": "Профіль",
"search": "Пошук",
"select_feature_flags": "Налаштування функцій",
@ -183,14 +290,14 @@
"zen_mode": "Zen-режим"
},
"notification": {
"favourited_post": "додали ваший допис до вибраного",
"favourited_post": "вподобав ваший допис",
"followed_you": "підписались на вас",
"followed_you_count": "{0} людей підписалися на вас|{0} людина підписалися на вас|{0} людини підписалися на вас|{0} людей підписалися на вас",
"missing_type": "ВІДСУТНІЙ notification.type:",
"reblogged_post": "поширили ваш допис",
"request_to_follow": "попросили підписатися на вас",
"signed_up": "зареєструвалися",
"update_status": "оновили свою публікацію"
"update_status": "оновили свій допис"
},
"placeholder": {
"content_warning": "Напишіть ваше попередження тут",
@ -200,9 +307,37 @@
},
"pwa": {
"dismiss": "Закрити",
"install": "Встановити",
"install_title": "Встановити Elk",
"screenshots": {
"dark": "Знімок екрану Elk, в темному режимі",
"light": "Знімок екрану Elk, в світлому режимі"
},
"title": "Доступна нова версія Elk!",
"update": "Оновити",
"update_available_short": "Оновити Elk"
"update_available_short": "Оновити Elk",
"webmanifest": {
"canary": {
"description": "Спритний веб-клієнт для Mastodon (canary)",
"name": "Elk (canary)",
"short_name": "Elk (canary)"
},
"dev": {
"description": "Спритний веб-клієнт для Mastodon (dev)",
"name": "Elk (dev)",
"short_name": "Elk (dev)"
},
"preview": {
"description": "Спритний веб-клієнт для Mastodon (preview)",
"name": "Elk (preview)",
"short_name": "Elk (preview)"
},
"release": {
"description": "Спритний веб-клієнт для Mastodon",
"name": "Elk",
"short_name": "Elk"
}
}
},
"search": {
"search_desc": "Пошук користувачів та хештеґів",
@ -222,11 +357,22 @@
"default": " (за замовчуванням)",
"font_size": "Розмір шрифта",
"label": "Інтерфейс",
"light_mode": "Світла"
"light_mode": "Світла",
"system_mode": "Cистемна",
"theme_color": "Колір теми"
},
"language": {
"display_language": "Мова інтерфейсу",
"label": "Мова"
"label": "Мова",
"post_language": "Мова дописів",
"status": "Статус перекладу: {0}/{1} ({2}%)",
"translations": {
"add": "Додати",
"choose_language": "Виберіть мову",
"heading": "Переклад",
"hide_specific": "Приховати переклад з мов",
"remove": "Видалити"
}
},
"notifications": {
"label": "Сповіщення",
@ -274,7 +420,34 @@
},
"notifications_settings": "Сповіщення",
"preferences": {
"label": "Налаштування"
"embedded_media": "Вбудований медіаплеєр",
"embedded_media_description": "Відображати вбудований медіаплеєр замість картки, коли допис містить посилання на медіа.",
"enable_autoplay": "Увімкнути автовідтворення",
"enable_data_saving": "Увімкнути економію трафіку",
"enable_data_saving_description": "Економте трафік, відключивши автоматичне завантаження вкладень.",
"github_cards": "Картки GitHub",
"grayscale_mode": "Режим відтінків сірого",
"hide_account_hover_card": "Не відображати картку при наведенні на обліковий запис",
"hide_alt_indi_on_posts": "Приховати індикатор альтернативного тексту у дописах",
"hide_boost_count": "Приховати кількість поширень",
"hide_favorite_count": "Приховати кількість вподобань",
"hide_follower_count": "Приховати кількість підписок/підписників",
"hide_news": "Приховати новини",
"hide_reply_count": "Приховати кількість відповідей",
"hide_tag_hover_card": "Не відображати картку при наведенні на хештеґ",
"hide_translation": "Приховати переклад",
"hide_username_emojis": "Приховати емодзі в іменах користувачів",
"hide_username_emojis_description": "Приховати емодзі в іменах користувачів у стрічках дописів. \nЕмодзі все одно відображатимуться на сторінках профілів.",
"label": "Налаштування",
"optimize_for_low_performance_device": "Оптимізувати для низькопродуктивних пристроїв",
"title": "Експериментальні налаштування",
"use_star_favorite_icon": "Використовувати піктограму \"зірка\" для вподобань",
"user_picker": "Перемикач облікових записів",
"user_picker_description": "Відображати аватари ваших облікових записів у нижньому лівому куті, щоб ви могли швидко перемикатися між ними.",
"virtual_scroll": "Віртуальний список",
"virtual_scroll_description": "Використовувати віртуальний список у стрічках дописів. Це дозволяє відображати більшу кількість елементів без втрати продуктивності.",
"zen_mode": "Дзен режим",
"zen_mode_description": "Приховати бокові панелі, якщо на них не наведено курсор миші. \nТакож приховує деякі елементи у стрічці дописів."
},
"profile": {
"appearance": {
@ -392,7 +565,7 @@
"add_media": "Додати зображення, відео або аудіо",
"change_content_visibility": "Змінити видимість вмісту",
"change_language": "Змінити мову",
"emoji": "Емоджі",
"emoji": "Емодзі",
"explore_links_intro": "Ці новини розповідають історії про людей на цих та інших серверах децентралізованої мережі прямо зараз.",
"explore_posts_intro": "Ці дописи з цього та інших серверів децентралізованої мережі зараз набирають популярності на цьому сервері.",
"explore_tags_intro": "Ці хештеґи зараз набирають популярності серед людей на цьому та інших серверах децентралізованої мережі.",
@ -401,9 +574,10 @@
"user": {
"add_existing": "Додати аккаунт",
"server_address_label": "Адреса серверу Mastodon",
"sign_in_desc": "Увійдіть, щоб слідкувати за профілями або хештеґами, додавати до обраного, розповсюджувати і відповідати на дописи, або взаємодіяти з вашого аккаунту на іншому сервері.",
"sign_in_desc": "Увійдіть, щоб стежити за профілями або хештеґами, додавати до обраного, ділитися дописами та відповідати на них, або взаємодіяти з вашого аккаунту на іншому сервері.",
"sign_in_notice_title": "Перегляд публічних даних {0}",
"sign_out_account": "Вийти з {0}",
"single_instance_sign_in_desc": "Увійдіть, щоб стежити за профілями чи хештеґами, додавати до обраного, ділитися дописами та відповідати на них.",
"tip_no_account": "Якщо у вас ще немає аккаунту Mastodon, {0}.",
"tip_register_account": "оберіть сервер і зареєструйтесь"
},

Wyświetl plik

@ -95,7 +95,7 @@
"activate": "Kích hoạt",
"complete": "Hoàn thành",
"compose_desc": "Soạn tút mới",
"n_people_in_the_past_n_days": "{0} người nhắc đến trong {1} ngày gần đây",
"n_people_in_the_past_n_days": "{0} người dùng trong {1} ngày qua",
"select_lang": "Chọn ngôn ngữ",
"sign_in_desc": "Thêm một tài khoản khác",
"switch_account": "Chuyển sang {0}",
@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Hủy bỏ",
"confirm": "Ẩn",
"days": "ngày|ngày|ngày",
"description": "Bạn có chắc muốn ẩn {0}?",
"hours": "giờ|giờ|giờ",
"minute": "phút|phút|phút",
"notifications": "Ẩn thông báo",
"specify_duration": "Thời hạn ẩn cụ thể",
"title": "Ẩn người"
},
"show_reblogs": {
@ -228,14 +233,25 @@
"compose": "Soạn",
"favourite": "Thích",
"search": "Tìm kiếm",
"show_new_items": "Hiện những tút mới",
"title": "Hành động"
},
"media": {
"title": "Media"
},
"navigation": {
"go_to_bookmarks": "Tút đã lưu",
"go_to_conversations": "Nhắn riêng",
"go_to_explore": "Khám phá",
"go_to_favourites": "Lượt thích",
"go_to_federated": "Liên hợp",
"go_to_home": "Trang chủ",
"go_to_lists": "Danh sách",
"go_to_local": "Máy chủ",
"go_to_notifications": "Thông báo",
"go_to_profile": "Hồ sơ",
"go_to_search": "Tìm kiếm",
"go_to_settings": "Cài đặt",
"next_status": "Tút tiếp theo",
"previous_status": "Tút trước đó",
"shortcut_help": "Trợ giúp phím tắt",
@ -264,7 +280,7 @@
"report_account": "Báo cáo {0}",
"share_account": "Chia sẻ {0}",
"share_post": "Chia sẻ tút",
"show_favourited_and_boosted_by": "Xem lượt thích đăng lại",
"show_favourited_and_boosted_by": "Xem lượt thích & đăng lại",
"show_reblogs": "Xem đăng lại từ {0}",
"show_untranslated": "Xem bản chưa dịch",
"toggle_theme": {
@ -293,6 +309,7 @@
"explore": "Khám phá",
"favourites": "Lượt thích",
"federated": "Liên hợp",
"hashtags": "Hashtag",
"home": "Trang chủ",
"list": "Danh sách",
"lists": "Danh sách",
@ -525,6 +542,7 @@
"hide_follower_count": "Ẩn số lượt người theo dõi/đang theo dõi",
"hide_news": "Ẩn tin tức",
"hide_reply_count": "Ẩn số lượt trả lời",
"hide_tag_hover_card": "Ẩn xem trước hashtag",
"hide_translation": "Ẩn chức năng dịch",
"hide_username_emojis": "Ẩn emoji trong tên người dùng",
"hide_username_emojis_description": "Ẩn emoji khỏi tên người dùng, emoji vẫn sẽ hiển thị trong mô tả của họ.",

Wyświetl plik

@ -13,5 +13,7 @@ export const nodePasteRule = proxy
export const VueNodeViewRenderer = proxy
export const findChildren = proxy
export const VueRenderer = proxy
export const callOrReturn = proxy
export const InputRule = proxy
export { proxy as default }

Wyświetl plik

@ -28,7 +28,8 @@ export default defineNuxtModule({
.map(async (l) => {
const exists = await isFile(resolver.resolve(`../node_modules/@emoji-mart/data/i18n/${l}.json`))
return [l, exists] as [code: string, exists: boolean]
}))
}),
)
.then(l => l.filter(l => l[1]).map(l => l[0]))
const switchStmt = locales.filter(l => l[1]).map((l) => {
return `

Wyświetl plik

@ -10,8 +10,8 @@ export function configurePWAOptions(options: Partial<VitePWAOptions>, nuxt: Nuxt
let config: Partial<
import('workbox-build').BasePartial
& import('workbox-build').GlobPartial
& import('workbox-build').RequiredGlobDirectoryPartial
& import('workbox-build').GlobPartial
& import('workbox-build').RequiredGlobDirectoryPartial
>
if (options.strategies === 'injectManifest') {

Wyświetl plik

@ -4,6 +4,7 @@ import { createResolver } from '@nuxt/kit'
import type { ManifestOptions } from 'vite-plugin-pwa'
import { getEnv } from '../../config/env'
import { currentLocales } from '../../config/i18n'
import { THEME_COLORS } from '../../constants/index'
export type LocalizedWebManifest = Record<string, Partial<ManifestOptions>>
@ -217,8 +218,8 @@ export async function createI18n(): Promise<LocalizedWebManifest> {
short_name,
description,
dir,
background_color: '#ffffff',
theme_color: '#ffffff',
background_color: THEME_COLORS.backgroundLight,
theme_color: THEME_COLORS.themeLight,
...manifestEntries,
shortcuts,
screenshots,
@ -229,8 +230,8 @@ export async function createI18n(): Promise<LocalizedWebManifest> {
short_name,
description,
dir,
background_color: '#111111',
theme_color: '#111111',
background_color: THEME_COLORS.backgroundDark,
theme_color: THEME_COLORS.themeDark,
...manifestEntries,
shortcuts,
screenshots,

Wyświetl plik

@ -36,7 +36,8 @@ export default defineNuxtPlugin(() => {
}
const {
needRefresh, updateServiceWorker,
needRefresh,
updateServiceWorker,
} = useRegisterSW({
immediate: true,
onRegisterError() {

Wyświetl plik

@ -13,7 +13,6 @@ export default defineNuxtPlugin(() => {
}
window.addEventListener('unhandledrejection', err =>
log.error(err.reason),
)
log.error(err.reason))
window.addEventListener('error', err => log.error(err.error), true)
})

Wyświetl plik

@ -55,10 +55,15 @@ export default defineNuxtPlugin(async () => {
const localCall = createCall(toNodeListener(h3App) as any)
const localFetch = createLocalFetch(localCall, globalThis.fetch)
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore error TS2321: Excessive stack depth comparing types
globalThis.$fetch = createFetch({
// @ts-expect-error slight differences in api
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore slight differences in api
fetch: localFetch,
Headers,
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore error TS2321: Excessive stack depth comparing types
defaults: { baseURL: config.app.baseURL },
})

Wyświetl plik

@ -1,10 +1,10 @@
[build]
publish = "dist"
command = "pnpm run build"
publish = "dist"
command = "pnpm run build"
# Redirect to Discord server
[[redirects]]
from = "https://chat.elk.zone"
to = "https://discord.gg/vAZSDU9J"
status = 301
force = true
from = "https://chat.elk.zone"
to = "https://discord.gg/vAZSDU9J"
status = 301
force = true

Wyświetl plik

@ -95,16 +95,42 @@ export default defineNuxtConfig({
},
optimizeDeps: {
include: [
'@tiptap/vue-3', 'string-length', 'vue-virtual-scroller', 'emoji-mart', 'iso-639-1',
'@tiptap/extension-placeholder', '@tiptap/extension-document', '@tiptap/extension-paragraph',
'@tiptap/extension-text', '@tiptap/extension-mention', '@tiptap/extension-hard-break',
'@tiptap/extension-bold', '@tiptap/extension-italic', '@tiptap/extension-code',
'@tiptap/extension-history', 'prosemirror-state', 'browser-fs-access', 'blurhash',
'@vueuse/integrations/useFocusTrap', '@tiptap/extension-code-block', 'prosemirror-highlight',
'@tiptap/core', 'tippy.js', 'prosemirror-highlight/shiki', '@fnando/sparkline',
'@vueuse/gesture', 'github-reserved-names', 'file-saver', 'slimeform', 'vue-advanced-cropper',
'workbox-window', 'workbox-precaching', 'workbox-routing', 'workbox-cacheable-response',
'workbox-strategies', 'workbox-expiration',
'@tiptap/vue-3',
'string-length',
'vue-virtual-scroller',
'emoji-mart',
'iso-639-1',
'@tiptap/extension-placeholder',
'@tiptap/extension-document',
'@tiptap/extension-paragraph',
'@tiptap/extension-text',
'@tiptap/extension-mention',
'@tiptap/extension-hard-break',
'@tiptap/extension-bold',
'@tiptap/extension-italic',
'@tiptap/extension-code',
'@tiptap/extension-history',
'prosemirror-state',
'browser-fs-access',
'blurhash',
'@vueuse/integrations/useFocusTrap',
'@tiptap/extension-code-block',
'prosemirror-highlight',
'@tiptap/core',
'tippy.js',
'prosemirror-highlight/shiki',
'@fnando/sparkline',
'@vueuse/gesture',
'github-reserved-names',
'file-saver',
'slimeform',
'vue-advanced-cropper',
'workbox-window',
'workbox-precaching',
'workbox-routing',
'workbox-cacheable-response',
'workbox-strategies',
'workbox-expiration',
],
},
},
@ -250,7 +276,8 @@ export default defineNuxtConfig({
],
},
},
// eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore nuxt-security is conditional
security: {
headers: {
@ -298,7 +325,7 @@ export default defineNuxtConfig({
})
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
// eslint-disable-next-line ts/no-namespace
namespace NodeJS {
interface Process {
mock?: Record<string, any>

Wyświetl plik

@ -1,7 +1,7 @@
{
"name": "@elk-zone/elk",
"type": "module",
"version": "0.11.0",
"version": "0.13.0",
"packageManager": "pnpm@8.15.3",
"license": "MIT",
"homepage": "https://elk.zone/",
@ -38,7 +38,7 @@
"@iconify/json": "^2.2.170",
"@iconify/utils": "^2.1.22",
"@nuxt/devtools": "^1.0.8",
"@nuxt/test-utils": "^3.11.0",
"@nuxt/test-utils": "^3.12.0",
"@nuxtjs/color-mode": "^3.3.2",
"@nuxtjs/i18n": "^8.1.1",
"@pinia/nuxt": "^0.5.1",
@ -60,7 +60,7 @@
"@upstash/redis": "^1.27.1",
"@vercel/kv": "^1.0.1",
"@vue-macros/nuxt": "^1.6.0",
"@vueuse/core": "^10.8.0",
"@vueuse/core": "^10.9.0",
"@vueuse/gesture": "^2.0.0",
"@vueuse/integrations": "^10.8.0",
"@vueuse/math": "^10.8.0",
@ -101,7 +101,7 @@
"theme-vitesse": "^0.7.2",
"tiny-decode": "^0.1.3",
"tippy.js": "^6.3.7",
"ufo": "^1.4.0",
"ufo": "^1.5.1",
"ultrahtml": "^1.5.3",
"unimport": "^3.7.1",
"vite-plugin-pwa": "^0.19.2",
@ -112,7 +112,7 @@
"ws": "^8.15.1"
},
"devDependencies": {
"@antfu/eslint-config": "^0.43.1",
"@antfu/eslint-config": "^2.8.1",
"@antfu/ni": "^0.21.12",
"@types/chroma-js": "^2.4.4",
"@types/file-saver": "^2.0.7",
@ -124,34 +124,36 @@
"@types/wicg-file-system-access": "^2020.9.8",
"@types/ws": "^8.5.10",
"@unlazy/nuxt": "^0.11.1",
"@vue/test-utils": "^2.4.4",
"bumpp": "^9.3.0",
"@unocss/eslint-config": "^0.58.5",
"@vue/test-utils": "2.4.5",
"bumpp": "^9.4.0",
"consola": "^3.2.3",
"eslint": "^8.49.0",
"eslint": "^8.57.0",
"eslint-plugin-format": "^0.1.0",
"flat": "^5.0.2",
"fs-extra": "^11.2.0",
"lint-staged": "^14.0.1",
"nuxt": "^3.10.3",
"nuxt": "^3.11.0",
"prettier": "^3.0.3",
"sharp": "^0.33.2",
"sharp-ico": "^0.1.5",
"simple-git-hooks": "^2.9.0",
"simple-git-hooks": "^2.10.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "1.3.1",
"vue-tsc": "^1.8.27"
"typescript": "^5.4.2",
"vitest": "1.4.0",
"vue-tsc": "^2.0.6"
},
"pnpm": {
"overrides": {
"unstorage": "^1.10.1"
"unstorage": "^1.10.2"
},
"patchedDependencies": {
"nuxt-security@0.13.1": "patches/nuxt-security@0.13.1.patch"
}
},
"resolutions": {
"vitest": "1.3.1",
"vue": "^3.4.19"
"vitest": "1.4.0",
"vue": "^3.4.21"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"

Wyświetl plik

@ -21,7 +21,7 @@ const { data: status, pending, refresh: refreshStatus } = useAsyncData(
)
const { client } = useMasto()
const { data: context, pending: pendingContext, refresh: refreshContext } = useAsyncData(
`context:${id}`,
`context:${id.value}`,
async () => client.value.v1.statuses.$select(id.value).context.fetch(),
{ watch: [isHydrated], immediate: isHydrated.value, lazy: true, default: () => shallowRef() },
)

Wyświetl plik

@ -9,7 +9,7 @@ const accountName = computed(() => toShortHandle(params.account as string))
const { t } = useI18n()
const { data: account, pending, refresh } = await useAsyncData(() => fetchAccountByHandle(accountName.value).catch(() => null), { immediate: import.meta.client, default: () => shallowRef() })
const relationship = computed(() => account ? useRelationship(account.value).value : undefined)
const relationship = computed(() => account.value ? useRelationship(account.value).value : undefined)
const userSettings = useUserSettings()

Wyświetl plik

@ -43,7 +43,7 @@ const tabs = computed<CommonRouteTabOption[]>(() => [
<MainContent>
<template #title>
<span timeline-title-style flex items-center gap-2 cursor-pointer @click="$scrollToTop">
<div i-ri:hashtag />
<div i-ri:compass-3-line />
<span>{{ t('nav.explore') }}</span>
</span>
</template>

Wyświetl plik

@ -1,7 +1,8 @@
<script lang="ts" setup>
import { STORAGE_KEY_HIDE_EXPLORE_POSTS_TIPS } from '~~/constants'
import { STORAGE_KEY_HIDE_EXPLORE_POSTS_TIPS, STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE } from '~~/constants'
const { t } = useI18n()
const route = useRoute()
const paginator = useMastoClient().v1.trends.statuses.list()
@ -10,6 +11,13 @@ const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_POSTS_TIPS, false)
useHydratedHead({
title: () => `${t('tab.posts')} | ${t('nav.explore')}`,
})
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
onActivated(() => {
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
})
</script>
<template>

Wyświetl plik

@ -1,7 +1,8 @@
<script lang="ts" setup>
import { STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS } from '~~/constants'
import { STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS, STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE } from '~~/constants'
const { t } = useI18n()
const route = useRoute()
const paginator = useMastoClient().v1.trends.links.list()
@ -10,6 +11,13 @@ const hideNewsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_NEWS_TIPS, false)
useHydratedHead({
title: () => `${t('tab.news')} | ${t('nav.explore')}`,
})
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
onActivated(() => {
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
})
</script>
<template>

Wyświetl plik

@ -1,9 +1,10 @@
<script lang="ts" setup>
import { STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS } from '~~/constants'
import { STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS, STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE } from '~~/constants'
const { t } = useI18n()
const route = useRoute()
const { client } = useMasto()
const paginator = client.value.v1.trends.tags.list({
limit: 20,
})
@ -13,6 +14,13 @@ const hideTagsTips = useLocalStorage(STORAGE_KEY_HIDE_EXPLORE_TAGS_TIPS, false)
useHydratedHead({
title: () => `${t('tab.hashtags')} | ${t('nav.explore')}`,
})
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
onActivated(() => {
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
})
</script>
<template>

Wyświetl plik

@ -1,5 +1,8 @@
<script lang="ts" setup>
import { STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE } from '~/constants'
const { t } = useI18n()
const route = useRoute()
// limit: 20 is the default configuration of the official client
const paginator = useMastoClient().v2.suggestions.list({ limit: 20 })
@ -7,6 +10,13 @@ const paginator = useMastoClient().v2.suggestions.list({ limit: 20 })
useHydratedHead({
title: () => `${t('tab.for_you')} | ${t('nav.explore')}`,
})
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
onActivated(() => {
lastAccessedExploreRoute.value = route.path.replace(/(.*\/explore\/?)/, '')
})
</script>
<template>

Wyświetl plik

@ -1,5 +1,4 @@
<script setup lang="ts">
const { t } = useI18n()
useHydratedHead({

29
pages/hashtags.vue 100644
Wyświetl plik

@ -0,0 +1,29 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
})
const { t } = useI18n()
const { client } = useMasto()
const paginator = client.value.v1.followedTags.list({
limit: 20,
})
useHydratedHead({
title: () => t('nav.hashtags'),
})
</script>
<template>
<MainContent>
<template #title>
<NuxtLink to="/hashtags" timeline-title-style flex items-center gap-2 @click="$scrollToTop">
<div class="i-ri:hashtag" />
<span>{{ t('nav.hashtags') }}</span>
</NuxtLink>
</template>
<TagCardPaginator v-bind="{ paginator }" />
</MainContent>
</template>

Wyświetl plik

@ -32,6 +32,8 @@ const filter = computed<mastodon.v1.NotificationType | undefined>(() => {
const actualFilter = Array.isArray(rawFilter) ? rawFilter[0] : rawFilter
if (isNotificationFilter(actualFilter))
return actualFilter
return undefined
})
const filterIconMap: Record<mastodon.v1.NotificationType, string> = {

Wyświetl plik

@ -12,6 +12,8 @@ const filter = computed<mastodon.v1.NotificationType | undefined>(() => {
const actualFilter = Array.isArray(rawFilter) ? rawFilter[0] : rawFilter
if (isNotification(actualFilter))
return actualFilter
return undefined
})
useHydratedHead({

Wyświetl plik

@ -27,6 +27,12 @@ const userSettings = useUserSettings()
>
{{ $t('settings.preferences.hide_account_hover_card') }}
</SettingsToggleItem>
<SettingsToggleItem
:checked="getPreferences(userSettings, 'hideTagHoverCard')"
@click="togglePreferences('hideTagHoverCard')"
>
{{ $t('settings.preferences.hide_tag_hover_card') }}
</SettingsToggleItem>
<SettingsToggleItem
:checked="getPreferences(userSettings, 'enableAutoplay')"
:disabled="getPreferences(userSettings, 'enableDataSaving')"

Some files were not shown because too many files have changed in this diff Show More