Merge branch 'main' into feature/allow-mixture-media

This commit is contained in:
Tianwei Dong 2024-03-07 09:54:53 +00:00 committed by GitHub
commit d057720f80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
600 changed files with 10290 additions and 6139 deletions

View File

@ -5,7 +5,7 @@
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features": { "features": {
"ghcr.io/devcontainers/features/sshd:1": {}, "ghcr.io/devcontainers/features/sshd:1": {}
}, },
"runServices": ["app", "db", "redis"], "runServices": ["app", "db", "redis"],
@ -15,16 +15,16 @@
"portsAttributes": { "portsAttributes": {
"3000": { "3000": {
"label": "web", "label": "web",
"onAutoForward": "notify", "onAutoForward": "notify"
}, },
"4000": { "4000": {
"label": "stream", "label": "stream",
"onAutoForward": "silent", "onAutoForward": "silent"
}, }
}, },
"otherPortsAttributes": { "otherPortsAttributes": {
"onAutoForward": "silent", "onAutoForward": "silent"
}, },
"remoteEnv": { "remoteEnv": {
@ -33,7 +33,7 @@
"STREAMING_API_BASE_URL": "https://${localEnv:CODESPACE_NAME}-4000.app.github.dev", "STREAMING_API_BASE_URL": "https://${localEnv:CODESPACE_NAME}-4000.app.github.dev",
"DISABLE_FORGERY_REQUEST_PROTECTION": "true", "DISABLE_FORGERY_REQUEST_PROTECTION": "true",
"ES_ENABLED": "", "ES_ENABLED": "",
"LIBRE_TRANSLATE_ENDPOINT": "", "LIBRE_TRANSLATE_ENDPOINT": ""
}, },
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}", "onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
@ -43,7 +43,7 @@
"customizations": { "customizations": {
"vscode": { "vscode": {
"settings": {}, "settings": {},
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"], "extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
}, }
}, }
} }

View File

@ -5,7 +5,7 @@
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
"features": { "features": {
"ghcr.io/devcontainers/features/sshd:1": {}, "ghcr.io/devcontainers/features/sshd:1": {}
}, },
"forwardPorts": [3000, 4000], "forwardPorts": [3000, 4000],
@ -14,17 +14,17 @@
"3000": { "3000": {
"label": "web", "label": "web",
"onAutoForward": "notify", "onAutoForward": "notify",
"requireLocalPort": true, "requireLocalPort": true
}, },
"4000": { "4000": {
"label": "stream", "label": "stream",
"onAutoForward": "silent", "onAutoForward": "silent",
"requireLocalPort": true, "requireLocalPort": true
}, }
}, },
"otherPortsAttributes": { "otherPortsAttributes": {
"onAutoForward": "silent", "onAutoForward": "silent"
}, },
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}", "onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
@ -34,7 +34,7 @@
"customizations": { "customizations": {
"vscode": { "vscode": {
"settings": {}, "settings": {},
"extensions": ["EditorConfig.EditorConfig", "webben.browserslist"], "extensions": ["EditorConfig.EditorConfig", "webben.browserslist"]
}, }
}, }
} }

View File

@ -70,7 +70,7 @@ services:
hard: -1 hard: -1
libretranslate: libretranslate:
image: libretranslate/libretranslate:v1.5.4 image: libretranslate/libretranslate:v1.5.5
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- lt-data:/home/libretranslate/.local - lt-data:/home/libretranslate/.local

View File

@ -338,7 +338,6 @@ module.exports = defineConfig({
'plugin:import/typescript', 'plugin:import/typescript',
'plugin:promise/recommended', 'plugin:promise/recommended',
'plugin:jsdoc/recommended-typescript', 'plugin:jsdoc/recommended-typescript',
'plugin:prettier/recommended',
], ],
parserOptions: { parserOptions: {
@ -347,6 +346,9 @@ module.exports = defineConfig({
}, },
rules: { rules: {
// Disable formatting rules that have been enabled in the base config
'indent': 'off',
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],

4
.github/codecov.yml vendored
View File

@ -1,3 +1,4 @@
comment: false # Do not leave PR comments
coverage: coverage:
status: status:
project: project:
@ -8,6 +9,3 @@ coverage:
default: default:
# Github status check is not blocking # Github status check is not blocking
informational: true informational: true
comment:
# Only write a comment in PR if there are changes
require_changes: true

View File

@ -38,7 +38,7 @@ jobs:
tags: | tags: |
type=raw,value=edge type=raw,value=edge
type=raw,value=nightly type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} type=raw,value=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit secrets: inherit
build-image-streaming: build-image-streaming:
@ -60,5 +60,5 @@ jobs:
tags: | tags: |
type=raw,value=edge type=raw,value=edge
type=raw,value=nightly type=raw,value=nightly
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }} type=raw,value=${{ needs.compute-suffix.outputs.prerelease }}
secrets: inherit secrets: inherit

View File

@ -52,7 +52,7 @@ jobs:
# Create or update the pull request # Create or update the pull request
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.2 uses: peter-evans/create-pull-request@v6.0.1
with: with:
commit-message: 'New Crowdin translations' commit-message: 'New Crowdin translations'
title: 'New Crowdin Translations (automated)' title: 'New Crowdin Translations (automated)'

18
.github/workflows/format-check.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: Check formatting
on:
push:
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Check formatting with Prettier
run: yarn format:check

View File

@ -43,4 +43,4 @@ jobs:
- run: echo "::add-matcher::.github/stylelint-matcher.json" - run: echo "::add-matcher::.github/stylelint-matcher.json"
- name: Stylelint - name: Stylelint
run: yarn lint:sass run: yarn lint:css

View File

@ -36,4 +36,4 @@ jobs:
- name: Run haml-lint - name: Run haml-lint
run: | run: |
echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json" echo "::add-matcher::.github/workflows/haml-lint-problem-matcher.json"
bundle exec haml-lint bundle exec haml-lint --reporter github

View File

@ -1,38 +0,0 @@
name: JSON Linting
on:
push:
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.prettier*'
- '**/*.json'
- '.github/workflows/lint-json.yml'
- '!app/javascript/mastodon/locales/*.json'
pull_request:
paths:
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.prettier*'
- '**/*.json'
- '.github/workflows/lint-json.yml'
- '!app/javascript/mastodon/locales/*.json'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Prettier
run: yarn lint:json

View File

@ -1,38 +0,0 @@
name: Markdown Linting
on:
push:
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- '.github/workflows/lint-md.yml'
- '.nvmrc'
- '.prettier*'
- '**/*.md'
- '!AUTHORS.md'
- 'package.json'
- 'yarn.lock'
pull_request:
paths:
- '.github/workflows/lint-md.yml'
- '.nvmrc'
- '.prettier*'
- '**/*.md'
- '!AUTHORS.md'
- 'package.json'
- 'yarn.lock'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Prettier
run: yarn lint:md

View File

@ -1,40 +0,0 @@
name: YML Linting
on:
push:
branches-ignore:
- 'dependabot/**'
- 'renovate/**'
paths:
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.prettier*'
- '**/*.yaml'
- '**/*.yml'
- '.github/workflows/lint-yml.yml'
- '!config/locales/*.yml'
pull_request:
paths:
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.prettier*'
- '**/*.yaml'
- '**/*.yml'
- '.github/workflows/lint-yml.yml'
- '!config/locales/*.yml'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Prettier
run: yarn lint:yml

View File

@ -139,7 +139,7 @@ jobs:
- name: Upload coverage reports to Codecov - name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version' if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v4
with: with:
files: coverage/lcov/mastodon.lcov files: coverage/lcov/mastodon.lcov
@ -224,7 +224,7 @@ jobs:
if: failure() if: failure()
with: with:
name: e2e-screenshots name: e2e-screenshots
path: tmp/screenshots/ path: tmp/capybara/
test-search: test-search:
name: Elastic Search integration testing name: Elastic Search integration testing
@ -328,4 +328,4 @@ jobs:
if: failure() if: failure()
with: with:
name: test-search-screenshots name: test-search-screenshots
path: tmp/screenshots/ path: tmp/capybara/

View File

@ -1,4 +1 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged yarn lint-staged

View File

@ -54,6 +54,13 @@
# Ignore Docker option files # Ignore Docker option files
docker-compose.override.yml docker-compose.override.yml
# Ignore public
/public/assets
/public/emoji
/public/packs
/public/packs-test
/public/system
# Ignore emoji map file # Ignore emoji map file
/app/javascript/mastodon/features/emoji/emoji_map.json /app/javascript/mastodon/features/emoji/emoji_map.json
@ -74,4 +81,5 @@ app/javascript/styles/mastodon/reset.scss
# Ignore the generated AUTHORS.md # Ignore the generated AUTHORS.md
AUTHORS.md AUTHORS.md
# Process a few selected JS files
!lint-staged.config.js !lint-staged.config.js

View File

@ -96,12 +96,6 @@ Rails/FilePath:
Rails/HttpStatus: Rails/HttpStatus:
EnforcedStyle: numeric EnforcedStyle: numeric
# Reason: Allowed in boot ENV checker
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsexit
Rails/Exit:
Exclude:
- 'config/boot.rb'
# Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions # Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter # https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter
Rails/LexicallyScopedActionFilter: Rails/LexicallyScopedActionFilter:
@ -134,6 +128,11 @@ Rails/UnusedIgnoredColumns:
Rails/NegateInclude: Rails/NegateInclude:
Enabled: false Enabled: false
# Reason: Enforce default limit, but allow some elements to span lines
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecexamplelength
RSpec/ExampleLength:
CountAsOne: ['array', 'heredoc', 'method_call']
# Reason: Deprecated cop, will be removed in 3.0, replaced by SpecFilePathFormat # Reason: Deprecated cop, will be removed in 3.0, replaced by SpecFilePathFormat
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath # https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
RSpec/FilePath: RSpec/FilePath:
@ -211,11 +210,6 @@ Style/RedundantBegin:
Style/RescueStandardError: Style/RescueStandardError:
EnforcedStyle: implicit EnforcedStyle: implicit
# Reason: Simplify some spec layouts
# https://docs.rubocop.org/rubocop/cops_style.html#stylesemicolon
Style/Semicolon:
AllowAsExpressionSeparator: true
# Reason: Originally disabled for CodeClimate, and no config consensus has been found # Reason: Originally disabled for CodeClimate, and no config consensus has been found
# https://docs.rubocop.org/rubocop/cops_style.html#stylesymbolarray # https://docs.rubocop.org/rubocop/cops_style.html#stylesymbolarray
Style/SymbolArray: Style/SymbolArray:

View File

@ -36,10 +36,10 @@ Metrics/PerceivedComplexity:
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 22 Max: 20 # Override default of 5
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
Max: 8 Max: 7
# Configuration parameters: AllowSubject. # Configuration parameters: AllowSubject.
RSpec/MultipleMemoizedHelpers: RSpec/MultipleMemoizedHelpers:

View File

@ -2,6 +2,101 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [4.2.7] - 2024-02-16
### Fixed
- Fix OmniAuth tests and edge cases in error handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/29201), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/29207))
- Fix new installs by upgrading to the latest release of the `nsa` gem, instead of a no longer existing commit ([mjankowski](https://github.com/mastodon/mastodon/pull/29065))
### Security
- Fix insufficient checking of remote posts ([GHSA-jhrq-qvrm-qr36](https://github.com/mastodon/mastodon/security/advisories/GHSA-jhrq-qvrm-qr36))
## [4.2.6] - 2024-02-14
### Security
- Update the `sidekiq-unique-jobs` dependency (see [GHSA-cmh9-rx85-xj38](https://github.com/mhenrixon/sidekiq-unique-jobs/security/advisories/GHSA-cmh9-rx85-xj38))
In addition, we have disabled the web interface for `sidekiq-unique-jobs` out of caution.
If you need it, you can re-enable it by setting `ENABLE_SIDEKIQ_UNIQUE_JOBS_UI=true`.
If you only need to clear all locks, you can now use `bundle exec rake sidekiq_unique_jobs:delete_all_locks`.
- Update the `nokogiri` dependency (see [GHSA-xc9x-jj77-9p9j](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-xc9x-jj77-9p9j))
- Disable administrative Doorkeeper routes ([ThisIsMissEm](https://github.com/mastodon/mastodon/pull/29187))
- Fix ongoing streaming sessions not being invalidated when applications get deleted in some cases ([GHSA-7w3c-p9j8-mq3x](https://github.com/mastodon/mastodon/security/advisories/GHSA-7w3c-p9j8-mq3x))
In some rare cases, the streaming server was not notified of access tokens revocation on application deletion.
- Change external authentication behavior to never reattach a new identity to an existing user by default ([GHSA-vm39-j3vx-pch3](https://github.com/mastodon/mastodon/security/advisories/GHSA-vm39-j3vx-pch3))
Up until now, Mastodon has allowed new identities from external authentication providers to attach to an existing local user based on their verified e-mail address.
This allowed upgrading users from a database-stored password to an external authentication provider, or move from one authentication provider to another.
However, this behavior may be unexpected, and means that when multiple authentication providers are configured, the overall security would be that of the least secure authentication provider.
For these reasons, this behavior is now locked under the `ALLOW_UNSAFE_AUTH_PROVIDER_REATTACH` environment variable.
In addition, regardless of this environment variable, Mastodon will refuse to attach two identities from the same authentication provider to the same account.
## [4.2.5] - 2024-02-01
### Security
- Fix insufficient origin validation (CVE-2024-23832, [GHSA-3fjr-858r-92rw](https://github.com/mastodon/mastodon/security/advisories/GHSA-3fjr-858r-92rw))
## [4.2.4] - 2024-01-24
### Fixed
- Fix error when processing remote files with unusually long names ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28823))
- Fix processing of compacted single-item JSON-LD collections ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28816))
- Retry 401 errors on replies fetching ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/28788))
- Fix `RecordNotUnique` errors in LinkCrawlWorker ([tribela](https://github.com/mastodon/mastodon/pull/28748))
- Fix Mastodon not correctly processing HTTP Signatures with query strings ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28443), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28476))
- Fix potential redirection loop of streaming endpoint ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28665))
- Fix streaming API redirection ignoring the port of `streaming_api_base_url` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28558))
- Fix error when processing link preview with an array as `inLanguage` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28252))
- Fix unsupported time zone or locale preventing sign-up ([Gargron](https://github.com/mastodon/mastodon/pull/28035))
- Fix "Hide these posts from home" list setting not refreshing when switching lists ([brianholley](https://github.com/mastodon/mastodon/pull/27763))
- Fix missing background behind dismissable banner in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/27479))
- Fix line wrapping of language selection button with long locale codes ([gunchleoc](https://github.com/mastodon/mastodon/pull/27100), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27127))
- Fix `Undo Announce` activity not being sent to non-follower authors ([MitarashiDango](https://github.com/mastodon/mastodon/pull/18482))
- Fix N+1s because of association preloaders not actually getting called ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28339))
- Fix empty column explainer getting cropped under certain conditions ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28337))
- Fix `LinkCrawlWorker` error when encountering empty OEmbed response ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28268))
- Fix call to inefficient `delete_matched` cache method in domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28367))
### Security
- Add rate-limit of TOTP authentication attempts at controller level ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/28801))
## [4.2.3] - 2023-12-05
### Fixed
- Fix dependency on `json-canonicalization` version that has been made unavailable since last release
## [4.2.2] - 2023-12-04
### Changed
- Change dismissed banners to be stored server-side ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27055))
- Change GIF max matrix size error to explicitly mention GIF files ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27927))
- Change `Follow` activities delivery to bypass availability check ([ShadowJonathan](https://github.com/mastodon/mastodon/pull/27586))
- Change single-column navigation notice to be displayed outside of the logo container ([renchap](https://github.com/mastodon/mastodon/pull/27462), [renchap](https://github.com/mastodon/mastodon/pull/27476))
- Change Content-Security-Policy to be tighter on media paths ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26889))
- Change post language code to include country code when relevant ([gunchleoc](https://github.com/mastodon/mastodon/pull/27099), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27207))
### Fixed
- Fix upper border radius of onboarding columns ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27890))
- Fix incoming status creation date not being restricted to standard ISO8601 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27655), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/28081))
- Fix some posts from threads received out-of-order sometimes not being inserted into timelines ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27653))
- Fix posts from force-sensitized accounts being able to trend ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27620))
- Fix error when trying to delete already-deleted file with OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27569))
- Fix batch attachment deletion when using OpenStack Swift ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27554))
- Fix processing LDSigned activities from actors with unknown public keys ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27474))
- Fix error and incorrect URLs in `/api/v1/accounts/:id/featured_tags` for remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27459))
- Fix report processing notice not mentioning the report number when performing a custom action ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27442))
- Fix handling of `inLanguage` attribute in preview card processing ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27423))
- Fix own posts being removed from home timeline when unfollowing a used hashtag ([kmycode](https://github.com/mastodon/mastodon/pull/27391))
- Fix some link anchors being recognized as hashtags ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27271), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/27584))
- Fix format-dependent redirects being cached regardless of requested format ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/27634))
## [4.2.1] - 2023-10-10 ## [4.2.1] - 2023-10-10
### Added ### Added

View File

@ -26,7 +26,7 @@ gem 'blurhash', '~> 0.1'
gem 'active_model_serializers', '~> 0.10' gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.8' gem 'addressable', '~> 2.8'
gem 'bootsnap', '~> 1.17.0', require: false gem 'bootsnap', '~> 1.18.0', require: false
gem 'browser' gem 'browser'
gem 'charlock_holmes', '~> 0.7.7' gem 'charlock_holmes', '~> 0.7.7'
gem 'chewy', '~> 7.3' gem 'chewy', '~> 7.3'
@ -63,7 +63,7 @@ gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0' gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar' gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar'
gem 'nokogiri', '~> 1.15' gem 'nokogiri', '~> 1.15'
gem 'nsa', github: 'jhawthorn/nsa', ref: 'e020fcc3a54d993ab45b7194d89ab720296c111b' gem 'nsa'
gem 'oj', '~> 3.14' gem 'oj', '~> 3.14'
gem 'ox', '~> 2.14' gem 'ox', '~> 2.14'
gem 'parslet' gem 'parslet'

View File

@ -7,49 +7,38 @@ GIT
hkdf (~> 0.2) hkdf (~> 0.2)
jwt (~> 2.0) jwt (~> 2.0)
GIT
remote: https://github.com/jhawthorn/nsa.git
revision: e020fcc3a54d993ab45b7194d89ab720296c111b
ref: e020fcc3a54d993ab45b7194d89ab720296c111b
specs:
nsa (0.2.8)
activesupport (>= 4.2, < 7.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.1.3) actioncable (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (7.1.3) actionmailbox (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.1.3) actionmailer (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
actionview (= 7.1.3) actionview (= 7.1.3.2)
activejob (= 7.1.3) activejob (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (7.1.3) actionpack (7.1.3.2)
actionview (= 7.1.3) actionview (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
racc racc
rack (>= 2.2.4) rack (>= 2.2.4)
@ -57,15 +46,15 @@ GEM
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
actiontext (7.1.3) actiontext (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
activerecord (= 7.1.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.1.3) actionview (7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
@ -75,22 +64,22 @@ GEM
activemodel (>= 4.1) activemodel (>= 4.1)
case_transform (>= 0.2) case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3) jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.1.3) activejob (7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.1.3) activemodel (7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
activerecord (7.1.3) activerecord (7.1.3.2)
activemodel (= 7.1.3) activemodel (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (7.1.3) activestorage (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
activejob (= 7.1.3) activejob (= 7.1.3.2)
activerecord (= 7.1.3) activerecord (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.1.3) activesupport (7.1.3.2)
base64 base64
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
@ -155,9 +144,9 @@ GEM
binding_of_caller (1.0.0) binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
blurhash (0.1.7) blurhash (0.1.7)
bootsnap (1.17.1) bootsnap (1.18.3)
msgpack (~> 1.2) msgpack (~> 1.2)
brakeman (6.1.1) brakeman (6.1.2)
racc racc
browser (5.3.1) browser (5.3.1)
brpoplpush-redis_script (0.1.3) brpoplpush-redis_script (0.1.3)
@ -193,7 +182,8 @@ GEM
cose (1.3.0) cose (1.3.0)
cbor (~> 0.5.9) cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0) openssl-signature_algorithm (~> 1.0)
crack (0.4.5) crack (0.4.6)
bigdecimal
rexml rexml
crass (1.0.6) crass (1.0.6)
css_parser (1.14.0) css_parser (1.14.0)
@ -229,7 +219,7 @@ GEM
docile (1.4.0) docile (1.4.0)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.6.8) doorkeeper (5.6.9)
railties (>= 5) railties (>= 5)
dotenv (2.8.1) dotenv (2.8.1)
dotenv-rails (2.8.1) dotenv-rails (2.8.1)
@ -319,13 +309,13 @@ GEM
activesupport (>= 5.1) activesupport (>= 5.1)
haml (>= 4.0.6) haml (>= 4.0.6)
railties (>= 5.1) railties (>= 5.1)
haml_lint (0.55.0) haml_lint (0.57.0)
haml (>= 5.0) haml (>= 5.0)
parallel (~> 1.10) parallel (~> 1.10)
rainbow rainbow
rubocop (>= 1.0) rubocop (>= 1.0)
sysexits (~> 1.1) sysexits (~> 1.1)
hashdiff (1.0.1) hashdiff (1.1.0)
hashie (5.0.0) hashie (5.0.0)
hcaptcha (7.1.0) hcaptcha (7.1.0)
json json
@ -343,7 +333,7 @@ GEM
http-form_data (2.3.0) http-form_data (2.3.0)
http_accept_language (2.1.1) http_accept_language (2.1.1)
httpclient (2.8.3) httpclient (2.8.3)
httplog (1.6.2) httplog (1.6.3)
rack (>= 2.0) rack (>= 2.0)
rainbow (>= 2.0.0) rainbow (>= 2.0.0)
i18n (1.14.1) i18n (1.14.1)
@ -361,7 +351,7 @@ GEM
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.5) idn-ruby (0.1.5)
io-console (0.7.2) io-console (0.7.2)
irb (1.11.1) irb (1.11.2)
rdoc rdoc
reline (>= 0.4.2) reline (>= 0.4.2)
jmespath (1.6.2) jmespath (1.6.2)
@ -454,7 +444,7 @@ GEM
uri uri
net-http-persistent (4.0.2) net-http-persistent (4.0.2)
connection_pool (~> 2.2) connection_pool (~> 2.2)
net-imap (0.4.9.1) net-imap (0.4.10)
date date
net-protocol net-protocol
net-ldap (0.19.0) net-ldap (0.19.0)
@ -465,9 +455,14 @@ GEM
net-smtp (0.4.0.1) net-smtp (0.4.0.1)
net-protocol net-protocol
nio4r (2.5.9) nio4r (2.5.9)
nokogiri (1.16.0) nokogiri (1.16.2)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nsa (0.3.0)
activesupport (>= 4.2, < 7.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.16.3) oj (3.16.3)
bigdecimal (>= 3.0) bigdecimal (>= 3.0)
omniauth (2.1.1) omniauth (2.1.1)
@ -510,8 +505,8 @@ GEM
parslet (2.0.0) parslet (2.0.0)
pastel (0.8.0) pastel (0.8.0)
tty-color (~> 0.5) tty-color (~> 0.5)
pg (1.5.4) pg (1.5.5)
pghero (3.4.0) pghero (3.4.1)
activerecord (>= 6) activerecord (>= 6)
posix-spawn (0.3.15) posix-spawn (0.3.15)
premailer (1.21.0) premailer (1.21.0)
@ -537,10 +532,10 @@ GEM
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.4.0) raabro (1.4.0)
racc (1.7.3) racc (1.7.3)
rack (2.2.8) rack (2.2.8.1)
rack-attack (6.7.0) rack-attack (6.7.0)
rack (>= 1.0, < 4) rack (>= 1.0, < 4)
rack-cors (2.0.1) rack-cors (2.0.2)
rack (>= 2.0.0) rack (>= 2.0.0)
rack-oauth2 (1.21.3) rack-oauth2 (1.21.3)
activesupport activesupport
@ -559,20 +554,20 @@ GEM
rackup (1.0.0) rackup (1.0.0)
rack (< 3) rack (< 3)
webrick webrick
rails (7.1.3) rails (7.1.3.2)
actioncable (= 7.1.3) actioncable (= 7.1.3.2)
actionmailbox (= 7.1.3) actionmailbox (= 7.1.3.2)
actionmailer (= 7.1.3) actionmailer (= 7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
actiontext (= 7.1.3) actiontext (= 7.1.3.2)
actionview (= 7.1.3) actionview (= 7.1.3.2)
activejob (= 7.1.3) activejob (= 7.1.3.2)
activemodel (= 7.1.3) activemodel (= 7.1.3.2)
activerecord (= 7.1.3) activerecord (= 7.1.3.2)
activestorage (= 7.1.3) activestorage (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.1.3) railties (= 7.1.3.2)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
@ -587,9 +582,9 @@ GEM
rails-i18n (7.0.8) rails-i18n (7.0.8)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
railties (7.1.3) railties (7.1.3.2)
actionpack (= 7.1.3) actionpack (= 7.1.3.2)
activesupport (= 7.1.3) activesupport (= 7.1.3.2)
irb irb
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
@ -696,7 +691,7 @@ GEM
scenic (1.7.0) scenic (1.7.0)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
railties (>= 4.0.0) railties (>= 4.0.0)
selenium-webdriver (4.17.0) selenium-webdriver (4.18.1)
base64 (~> 0.2) base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0) rubyzip (>= 1.2.2, < 3.0)
@ -712,7 +707,7 @@ GEM
rufus-scheduler (~> 3.2) rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8) sidekiq (>= 6, < 8)
tilt (>= 1.4.0) tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.31) sidekiq-unique-jobs (7.1.33)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0) brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
concurrent-ruby (~> 1.0, >= 1.0.5) concurrent-ruby (~> 1.0, >= 1.0.5)
redis (< 5.0) redis (< 5.0)
@ -749,7 +744,7 @@ GEM
terrapin (1.0.1) terrapin (1.0.1)
climate_control climate_control
test-prof (1.3.1) test-prof (1.3.1)
thor (1.3.0) thor (1.3.1)
tilt (2.3.0) tilt (2.3.0)
timeout (0.4.1) timeout (0.4.1)
tpm-key_attestation (0.12.0) tpm-key_attestation (0.12.0)
@ -771,7 +766,7 @@ GEM
unf (~> 0.1.0) unf (~> 0.1.0)
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
tzinfo-data (1.2023.4) tzinfo-data (1.2024.1)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
@ -798,7 +793,7 @@ GEM
webfinger (1.2.0) webfinger (1.2.0)
activesupport activesupport
httpclient (>= 2.4) httpclient (>= 2.4)
webmock (3.19.1) webmock (3.22.0)
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
@ -816,7 +811,7 @@ GEM
xorcist (1.1.3) xorcist (1.1.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.6.12) zeitwerk (2.6.13)
PLATFORMS PLATFORMS
ruby ruby
@ -829,7 +824,7 @@ DEPENDENCIES
better_errors (~> 2.9) better_errors (~> 2.9)
binding_of_caller (~> 1.0) binding_of_caller (~> 1.0)
blurhash (~> 0.1) blurhash (~> 0.1)
bootsnap (~> 1.17.0) bootsnap (~> 1.18.0)
brakeman (~> 6.0) brakeman (~> 6.0)
browser browser
bundler-audit (~> 0.9) bundler-audit (~> 0.9)
@ -886,7 +881,7 @@ DEPENDENCIES
net-http (~> 0.4.0) net-http (~> 0.4.0)
net-ldap (~> 0.18) net-ldap (~> 0.18)
nokogiri (~> 1.15) nokogiri (~> 1.15)
nsa! nsa
oj (~> 3.14) oj (~> 3.14)
omniauth (~> 2.0) omniauth (~> 2.0)
omniauth-cas (~> 3.0.0.beta.1) omniauth-cas (~> 3.0.0.beta.1)

View File

@ -69,7 +69,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
- **PostgreSQL** 12+ - **PostgreSQL** 12+
- **Redis** 4+ - **Redis** 4+
- **Ruby** 2.7+ - **Ruby** 3.0+
- **Node.js** 16+ - **Node.js** 16+
The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation. The repository includes deployment configurations for **Docker and docker-compose** as well as specific platforms like **Heroku**, **Scalingo**, and **Nanobox**. For Helm charts, reference the [mastodon/chart repository](https://github.com/mastodon/chart). The [**standalone** installation guide](https://docs.joinmastodon.org/admin/install/) is available in the documentation.
@ -83,23 +83,19 @@ A **Vagrant** configuration is included for development purposes. To use it, com
- Install Vagrant and Virtualbox - Install Vagrant and Virtualbox
- Install the `vagrant-hostsupdater` plugin: `vagrant plugin install vagrant-hostsupdater` - Install the `vagrant-hostsupdater` plugin: `vagrant plugin install vagrant-hostsupdater`
- Run `vagrant up` - Run `vagrant up`
- Run `vagrant ssh -c "cd /vagrant && foreman start"` - Run `vagrant ssh -c "cd /vagrant && bin/dev"`
- Open `http://mastodon.local` in your browser - Open `http://mastodon.local` in your browser
### MacOS ### MacOS
To set up **MacOS** for native development, complete the following steps: To set up **MacOS** for native development, complete the following steps:
- Install the latest stable Ruby version (use a Ruby version manager for easy installation and management of Ruby versions) - Use a Ruby version manager to install the specified version from `.ruby-version`
- Run `brew install postgresql@14` - Run `brew install postgresql@14 redis imagemagick libidn` to install required dependencies
- Run `brew install redis` - Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from `.nvmrc`
- Run `brew install imagemagick`
- Run `brew install libidn`
- Install Foreman or a similar tool (such as [overmind](https://github.com/DarthSim/overmind)) to handle multiple process launching.
- Navigate to Mastodon's root directory and run `brew install nvm` then `nvm use` to use the version from .nvmrc
- Run `corepack enable && corepack prepare` - Run `corepack enable && corepack prepare`
- Run `bundle exec rails db:setup` (optionally prepend `RAILS_ENV=development` to target the dev environment) - Run `bundle exec rails db:setup` (optionally prepend `RAILS_ENV=development` to target the dev environment)
- Finally, run `overmind start -f Procfile.dev` - Finally, run `bin/dev` which will launch the local services via `overmind` (if installed) or `foreman`
### Docker ### Docker
@ -108,7 +104,7 @@ For development with **Docker**, complete the following steps:
- Install Docker Desktop - Install Docker Desktop
- Run `docker compose -f .devcontainer/docker-compose.yml up -d` - Run `docker compose -f .devcontainer/docker-compose.yml up -d`
- Run `docker compose -f .devcontainer/docker-compose.yml exec app .devcontainer/post-create.sh` - Run `docker compose -f .devcontainer/docker-compose.yml exec app .devcontainer/post-create.sh`
- Finally, run `docker compose -f .devcontainer/docker-compose.yml exec app foreman start -f Procfile.dev` - Finally, run `docker compose -f .devcontainer/docker-compose.yml exec app bin/dev`
If you are using an IDE with [support for the Development Container specification](https://containers.dev/supporting), it will run the above `docker compose` commands automatically. For **Visual Studio Code** this requires the [Dev Container extension](https://containers.dev/supporting#dev-containers). If you are using an IDE with [support for the Development Container specification](https://containers.dev/supporting), it will run the above `docker compose` commands automatically. For **Visual Studio Code** this requires the [Dev Container extension](https://containers.dev/supporting#dev-containers).
@ -119,7 +115,7 @@ To get you coding in just a few minutes, GitHub Codespaces provides a web-based
- Click this button to create a new codespace:<br> - Click this button to create a new codespace:<br>
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=52281283&devcontainer_path=.devcontainer%2Fcodespaces%2Fdevcontainer.json) [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=52281283&devcontainer_path=.devcontainer%2Fcodespaces%2Fdevcontainer.json)
- Wait for the environment to build. This will take a few minutes. - Wait for the environment to build. This will take a few minutes.
- When the editor is ready, run `foreman start -f Procfile.dev` in the terminal. - When the editor is ready, run `bin/dev` in the terminal.
- After a few seconds, a popup will appear with a button labeled _Open in Browser_. This will open Mastodon. - After a few seconds, a popup will appear with a button labeled _Open in Browser_. This will open Mastodon.
- On the _Ports_ tab, right click on the “stream” row and select _Port visibility__Public_. - On the _Ports_ tab, right click on the “stream” row and select _Port visibility__Public_.

2
Vagrantfile vendored
View File

@ -188,7 +188,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.post_up_message = <<MESSAGE config.vm.post_up_message = <<MESSAGE
To start server To start server
$ vagrant ssh -c "cd /vagrant && foreman start" $ vagrant ssh -c "cd /vagrant && bin/dev"
MESSAGE MESSAGE
end end

View File

@ -62,11 +62,10 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' || signed_request_account.nil? return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' || signed_request_account.nil?
# Re-using the syntax for signature parameters # Re-using the syntax for signature parameters
tree = SignatureParamsParser.new.parse(raw_params) params = SignatureParser.parse(raw_params)
params = SignatureParamsTransformer.new.apply(tree)
ActivityPub::PrepareFollowersSynchronizationService.new.call(signed_request_account, params) ActivityPub::PrepareFollowersSynchronizationService.new.call(signed_request_account, params)
rescue Parslet::ParseFailed rescue SignatureParser::ParsingError
Rails.logger.warn 'Error parsing Collection-Synchronization header' Rails.logger.warn 'Error parsing Collection-Synchronization header'
end end

View File

@ -4,7 +4,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action -> { authorize_if_got_token! :read, :'read:statuses' }
before_action :set_account before_action :set_account
after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) } after_action :insert_pagination_headers
def index def index
cache_if_unauthenticated! cache_if_unauthenticated!

View File

@ -35,6 +35,7 @@ class Api::V1::Admin::ReportsController < Api::BaseController
def update def update
authorize @report, :update? authorize @report, :update?
@report.update!(report_params) @report.update!(report_params)
log_action :update, @report
render json: @report, serializer: REST::Admin::ReportSerializer render json: @report, serializer: REST::Admin::ReportSerializer
end end

View File

@ -71,13 +71,9 @@ class Api::V1::StatusesController < Api::BaseController
with_rate_limit: true with_rate_limit: true
) )
render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer render json: @status, serializer: serializer_for_status
rescue PostStatusService::UnexpectedMentionsError => e rescue PostStatusService::UnexpectedMentionsError => e
unexpected_accounts = ActiveModel::Serializer::CollectionSerializer.new( render json: unexpected_accounts_error_json(e), status: 422
e.accounts,
serializer: REST::AccountSerializer
)
render json: { error: e.message, unexpected_accounts: unexpected_accounts }, status: 422
end end
def update def update
@ -155,6 +151,21 @@ class Api::V1::StatusesController < Api::BaseController
) )
end end
def serializer_for_status
@status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
end
def unexpected_accounts_error_json(error)
{
error: error.message,
unexpected_accounts: serialized_accounts(error.accounts),
}
end
def serialized_accounts(accounts)
ActiveModel::Serializer::CollectionSerializer.new(accounts, serializer: REST::AccountSerializer)
end
def pagination_params(core_params) def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params) params.slice(:limit).permit(:limit).merge(core_params)
end end

View File

@ -178,7 +178,7 @@ class ApplicationController < ActionController::Base
respond_to do |format| respond_to do |format|
format.any { render 'errors/self_destruct', layout: 'auth', status: 410, formats: [:html] } format.any { render 'errors/self_destruct', layout: 'auth', status: 410, formats: [:html] }
format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[410] }, status: code } format.json { render json: { error: Rack::Utils::HTTP_STATUS_CODES[410] }, status: 410 }
end end
end end

View File

@ -7,7 +7,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider) def self.provides_callback_for(provider)
define_method provider do define_method provider do
@provider = provider @provider = provider
@user = User.find_for_oauth(request.env['omniauth.auth'], current_user) @user = User.find_for_omniauth(request.env['omniauth.auth'], current_user)
if @user.persisted? if @user.persisted?
record_login_activity record_login_activity
@ -17,6 +17,9 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
session["devise.#{provider}_data"] = request.env['omniauth.auth'] session["devise.#{provider}_data"] = request.env['omniauth.auth']
redirect_to new_user_registration_url redirect_to new_user_registration_url
end end
rescue ActiveRecord::RecordInvalid
flash[:alert] = I18n.t('devise.failure.omniauth_user_creation_failure') if is_navigational_format?
redirect_to new_user_session_url
end end
end end

View File

@ -183,7 +183,9 @@ class Auth::SessionsController < Devise::SessionsController
) )
# Only send a notification email every hour at most # Only send a notification email every hour at most
return if redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour, get: true).present? return if redis.get("2fa_failure_notification:#{user.id}").present?
redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour)
UserMailer.failed_2fa(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later! UserMailer.failed_2fa(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later!
end end

View File

@ -12,39 +12,6 @@ module SignatureVerification
class SignatureVerificationError < StandardError; end class SignatureVerificationError < StandardError; end
class SignatureParamsParser < Parslet::Parser
rule(:token) { match("[0-9a-zA-Z!#$%&'*+.^_`|~-]").repeat(1).as(:token) }
rule(:quoted_string) { str('"') >> (qdtext | quoted_pair).repeat.as(:quoted_string) >> str('"') }
# qdtext and quoted_pair are not exactly according to spec but meh
rule(:qdtext) { match('[^\\\\"]') }
rule(:quoted_pair) { str('\\') >> any }
rule(:bws) { match('\s').repeat }
rule(:param) { (token.as(:key) >> bws >> str('=') >> bws >> (token | quoted_string).as(:value)).as(:param) }
rule(:comma) { bws >> str(',') >> bws }
# Old versions of node-http-signature add an incorrect "Signature " prefix to the header
rule(:buggy_prefix) { str('Signature ') }
rule(:params) { buggy_prefix.maybe >> (param >> (comma >> param).repeat).as(:params) }
root(:params)
end
class SignatureParamsTransformer < Parslet::Transform
rule(params: subtree(:param)) do
(param.is_a?(Array) ? param : [param]).each_with_object({}) { |(key, value), hash| hash[key] = value }
end
rule(param: { key: simple(:key), value: simple(:val) }) do
[key, val]
end
rule(quoted_string: simple(:string)) do
string.to_s
end
rule(token: simple(:string)) do
string.to_s
end
end
def require_account_signature! def require_account_signature!
render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
end end
@ -135,12 +102,8 @@ module SignatureVerification
end end
def signature_params def signature_params
@signature_params ||= begin @signature_params ||= SignatureParser.parse(request.headers['Signature'])
raw_signature = request.headers['Signature'] rescue SignatureParser::ParsingError
tree = SignatureParamsParser.new.parse(raw_signature)
SignatureParamsTransformer.new.apply(tree)
end
rescue Parslet::ParseFailed
raise SignatureVerificationError, 'Error parsing signature parameters' raise SignatureVerificationError, 'Error parsing signature parameters'
end end

View File

@ -16,6 +16,6 @@ class CustomCssController < ActionController::Base # rubocop:disable Rails/Appli
helper_method :custom_css_styles helper_method :custom_css_styles
def set_user_roles def set_user_roles
@user_roles = UserRole.where(highlighted: true).where.not(color: [nil, '']) @user_roles = UserRole.providing_styles
end end
end end

View File

@ -1,27 +1,26 @@
# frozen_string_literal: true # frozen_string_literal: true
class IntentsController < ApplicationController class IntentsController < ApplicationController
before_action :check_uri EXPECTED_SCHEME = 'web+mastodon'
before_action :handle_invalid_uri, unless: :valid_uri?
rescue_from Addressable::URI::InvalidURIError, with: :handle_invalid_uri rescue_from Addressable::URI::InvalidURIError, with: :handle_invalid_uri
def show def show
if uri.scheme == 'web+mastodon' case uri.host
case uri.host when 'follow'
when 'follow' redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:'))
return redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:')) when 'share'
when 'share' redirect_to share_path(text: uri.query_values['text'])
return redirect_to share_path(text: uri.query_values['text']) else
end handle_invalid_uri
end end
not_found
end end
private private
def check_uri def valid_uri?
not_found if uri.blank? uri.present? && uri.scheme == EXPECTED_SCHEME
end end
def handle_invalid_uri def handle_invalid_uri

View File

@ -174,7 +174,19 @@ module JsonLdHelper
build_request(uri, on_behalf_of, options: request_options).perform do |response| build_request(uri, on_behalf_of, options: request_options).perform do |response|
raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error raise Mastodon::UnexpectedResponseError, response unless response_successful?(response) || response_error_unsalvageable?(response) || !raise_on_temporary_error
body_to_json(response.body_with_limit) if response.code == 200 body_to_json(response.body_with_limit) if response.code == 200 && valid_activitypub_content_type?(response)
end
end
def valid_activitypub_content_type?(response)
return true if response.mime_type == 'application/activity+json'
# When the mime type is `application/ld+json`, we need to check the profile,
# but `http.rb` does not parse it for us.
return false unless response.mime_type == 'application/ld+json'
response.headers[HTTP::Headers::CONTENT_TYPE]&.split(';')&.map(&:strip)&.any? do |str|
str.start_with?('profile="') && str[9...-1].split.include?('https://www.w3.org/ns/activitystreams')
end end
end end

View File

@ -127,7 +127,7 @@ module LanguagesHelper
om: ['Oromo', 'Afaan Oromoo'].freeze, om: ['Oromo', 'Afaan Oromoo'].freeze,
or: ['Oriya', 'ଓଡ଼ିଆ'].freeze, or: ['Oriya', 'ଓଡ଼ିଆ'].freeze,
os: ['Ossetian', 'ирон æвзаг'].freeze, os: ['Ossetian', 'ирон æвзаг'].freeze,
pa: ['Panjabi', 'ਪੰਜਾਬੀ'].freeze, pa: ['Punjabi', 'ਪੰਜਾਬੀ'].freeze,
pi: ['Pāli', 'पाऴि'].freeze, pi: ['Pāli', 'पाऴि'].freeze,
pl: ['Polish', 'Polski'].freeze, pl: ['Polish', 'Polski'].freeze,
ps: ['Pashto', 'پښتو'].freeze, ps: ['Pashto', 'پښتو'].freeze,
@ -191,15 +191,18 @@ module LanguagesHelper
chr: ['Cherokee', 'ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ'].freeze, chr: ['Cherokee', 'ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ'].freeze,
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze, ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
cnr: ['Montenegrin', 'crnogorski'].freeze, cnr: ['Montenegrin', 'crnogorski'].freeze,
csb: ['Kashubian', 'Kaszëbsczi'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze, jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze, kab: ['Kabyle', 'Taqbaylit'].freeze,
ldn: ['Láadan', 'Láadan'].freeze, ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze, lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
pdc: ['Pennsylvania Dutch', 'Pennsilfaani-Deitsch'].freeze,
sco: ['Scots', 'Scots'].freeze, sco: ['Scots', 'Scots'].freeze,
sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze, sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze,
smj: ['Lule Sami', 'Julevsámegiella'].freeze, smj: ['Lule Sami', 'Julevsámegiella'].freeze,
szl: ['Silesian', 'ślůnsko godka'].freeze, szl: ['Silesian', 'ślůnsko godka'].freeze,
tok: ['Toki Pona', 'toki pona'].freeze, tok: ['Toki Pona', 'toki pona'].freeze,
vai: ['Vai', 'ꕙꔤ'].freeze,
xal: ['Kalmyk', 'Хальмг келн'].freeze, xal: ['Kalmyk', 'Хальмг келн'].freeze,
zba: ['Balaibalan', 'باليبلن'].freeze, zba: ['Balaibalan', 'باليبلن'].freeze,
zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze, zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze,

View File

@ -15,9 +15,20 @@ module ReactComponentHelper
div_tag_with_data(data) div_tag_with_data(data)
end end
def serialized_media_attachments(media_attachments)
media_attachments.map { |attachment| serialized_attachment(attachment) }
end
private private
def div_tag_with_data(data) def div_tag_with_data(data)
content_tag(:div, nil, data: data) content_tag(:div, nil, data: data)
end end
def serialized_attachment(attachment)
ActiveModelSerializers::SerializableResource.new(
attachment,
serializer: REST::MediaAttachmentSerializer
).as_json
end
end end

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2024 Paweł Kuna
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1 @@
Images in this folder are based on [Tabler.io icons](https://tabler.io/icons).

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2024 Paweł Kuna
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1 @@
Images in this folder are based on [Tabler.io icons](https://tabler.io/icons).

View File

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 688 B

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 709 B

After

Width:  |  Height:  |  Size: 709 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 939 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -124,7 +124,7 @@ class ReportReasonSelector extends PureComponent {
api().put(`/api/v1/admin/reports/${id}`, { api().put(`/api/v1/admin/reports/${id}`, {
category, category,
rule_ids, rule_ids: category === 'violation' ? rule_ids : [],
}).catch(err => { }).catch(err => {
console.error(err); console.error(err);
}); });

View File

@ -67,7 +67,7 @@ class EditedTimestamp extends PureComponent {
return ( return (
<DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}> <DropdownMenu statusId={statusId} renderItem={this.renderItem} scrollable renderHeader={this.renderHeader} onItemClick={this.handleItemClick}>
<button className='dropdown-menu__text-button'> <button className='dropdown-menu__text-button'>
<FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { hour12: false, month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} /> <FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(timestamp, { month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} /> <Icon id='caret-down' icon={ArrowDropDownIcon} />
</button> </button>
</DropdownMenu> </DropdownMenu>
); );

View File

@ -53,7 +53,6 @@ const messages = defineMessages({
}); });
const dateFormatOptions = { const dateFormatOptions = {
hour12: false,
year: 'numeric', year: 'numeric',
month: 'short', month: 'short',
day: '2-digit', day: '2-digit',

View File

@ -554,7 +554,7 @@ class Status extends ImmutablePureComponent {
<div onClick={this.handleClick} className='status__info'> <div onClick={this.handleClick} className='status__info'>
<a href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time' target='_blank' rel='noopener noreferrer'> <a href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} className='status__relative-time' target='_blank' rel='noopener noreferrer'>
<span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility')} /></span> <span className='status__visibility-icon'><VisibilityIcon visibility={status.get('visibility')} /></span>
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { hour12: false, year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>} <RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
</a> </a>
<a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'> <a onClick={this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>

View File

@ -80,7 +80,7 @@ export default class MediaContainer extends PureComponent {
return ( return (
<IntlProvider> <IntlProvider>
<> <>
{[].map.call(components, (component, i) => { {Array.from(components).map((component, i) => {
const componentName = component.getAttribute('data-component'); const componentName = component.getAttribute('data-component');
const Component = MEDIA_COMPONENTS[componentName]; const Component = MEDIA_COMPONENTS[componentName];
const { media, card, poll, hashtag, ...props } = JSON.parse(component.getAttribute('data-props')); const { media, card, poll, hashtag, ...props } = JSON.parse(component.getAttribute('data-props'));

View File

@ -101,7 +101,6 @@ const dateFormatOptions = {
month: 'short', month: 'short',
day: 'numeric', day: 'numeric',
year: 'numeric', year: 'numeric',
hour12: false,
hour: '2-digit', hour: '2-digit',
minute: '2-digit', minute: '2-digit',
}; };

View File

@ -6,9 +6,9 @@ import { Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import BarChart4BarsIcon from 'mastodon/../material-icons/400-24px/bar_chart_4_bars.svg?react'; import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react';
import CloseIcon from 'mastodon/../material-icons/400-24px/close.svg?react'; import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import PhotoLibraryIcon from 'mastodon/../material-icons/400-24px/photo_library.svg?react'; import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react';
import { cancelReplyCompose } from 'mastodon/actions/compose'; import { cancelReplyCompose } from 'mastodon/actions/compose';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';

View File

@ -10,7 +10,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay'; import Overlay from 'react-overlays/Overlay';
import MoodIcon from 'mastodon/../material-icons/400-24px/mood.svg?react'; import MoodIcon from '@/material-icons/400-20px/mood.svg?react';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
import { assetHost } from 'mastodon/utils/config'; import { assetHost } from 'mastodon/utils/config';

View File

@ -9,9 +9,9 @@ import { supportsPassiveEvents } from 'detect-passive-events';
import fuzzysort from 'fuzzysort'; import fuzzysort from 'fuzzysort';
import Overlay from 'react-overlays/Overlay'; import Overlay from 'react-overlays/Overlay';
import CancelIcon from 'mastodon/../material-icons/400-24px/cancel-fill.svg?react'; import CancelIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
import SearchIcon from 'mastodon/../material-icons/400-24px/search.svg?react'; import SearchIcon from '@/material-icons/400-24px/search.svg?react';
import TranslateIcon from 'mastodon/../material-icons/400-24px/translate.svg?react'; import TranslateIcon from '@/material-icons/400-24px/translate.svg?react';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { languages as preloadedLanguages } from 'mastodon/initial_state'; import { languages as preloadedLanguages } from 'mastodon/initial_state';
@ -141,6 +141,7 @@ class LanguageDropdownMenu extends PureComponent {
case 'Escape': case 'Escape':
onClose(); onClose();
break; break;
case ' ':
case 'Enter': case 'Enter':
this.handleClick(e); this.handleClick(e);
break; break;

View File

@ -4,7 +4,7 @@ import { useIntl, defineMessages } from 'react-intl';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import CloseIcon from 'mastodon/../material-icons/400-24px/close.svg?react'; import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import { cancelReplyCompose } from 'mastodon/actions/compose'; import { cancelReplyCompose } from 'mastodon/actions/compose';
import Account from 'mastodon/components/account'; import Account from 'mastodon/components/account';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';

View File

@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl'; import { defineMessages, injectIntl } from 'react-intl';
import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react'; import BarChart4BarsIcon from '@/material-icons/400-20px/bar_chart_4_bars.svg?react';
import { IconButton } from '../../../components/icon_button'; import { IconButton } from '../../../components/icon_button';

View File

@ -5,16 +5,16 @@ import { injectIntl, defineMessages } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay'; import Overlay from 'react-overlays/Overlay';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import InfoIcon from '@/material-icons/400-24px/info.svg?react';
import LockIcon from '@/material-icons/400-24px/lock.svg?react'; import LockIcon from '@/material-icons/400-24px/lock.svg?react';
import PublicIcon from '@/material-icons/400-24px/public.svg?react'; import PublicIcon from '@/material-icons/400-24px/public.svg?react';
import QuietTimeIcon from '@/material-icons/400-24px/quiet_time.svg?react'; import QuietTimeIcon from '@/material-icons/400-24px/quiet_time.svg?react';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { PrivacyDropdownMenu } from './privacy_dropdown_menu';
const messages = defineMessages({ const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' }, public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
public_long: { id: 'privacy.public.long', defaultMessage: 'Anyone on and off Mastodon' }, public_long: { id: 'privacy.public.long', defaultMessage: 'Anyone on and off Mastodon' },
@ -28,126 +28,6 @@ const messages = defineMessages({
unlisted_extra: { id: 'privacy.unlisted.additional', defaultMessage: 'This behaves exactly like public, except the post will not appear in live feeds or hashtags, explore, or Mastodon search, even if you are opted-in account-wide.' }, unlisted_extra: { id: 'privacy.unlisted.additional', defaultMessage: 'This behaves exactly like public, except the post will not appear in live feeds or hashtags, explore, or Mastodon search, even if you are opted-in account-wide.' },
}); });
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
class PrivacyDropdownMenu extends PureComponent {
static propTypes = {
style: PropTypes.object,
items: PropTypes.array.isRequired,
value: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
};
handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) {
this.props.onClose();
e.stopPropagation();
}
};
handleKeyDown = e => {
const { items } = this.props;
const value = e.currentTarget.getAttribute('data-index');
const index = items.findIndex(item => {
return (item.value === value);
});
let element = null;
switch(e.key) {
case 'Escape':
this.props.onClose();
break;
case 'Enter':
this.handleClick(e);
break;
case 'ArrowDown':
element = this.node.childNodes[index + 1] || this.node.firstChild;
break;
case 'ArrowUp':
element = this.node.childNodes[index - 1] || this.node.lastChild;
break;
case 'Tab':
if (e.shiftKey) {
element = this.node.childNodes[index - 1] || this.node.lastChild;
} else {
element = this.node.childNodes[index + 1] || this.node.firstChild;
}
break;
case 'Home':
element = this.node.firstChild;
break;
case 'End':
element = this.node.lastChild;
break;
}
if (element) {
element.focus();
this.props.onChange(element.getAttribute('data-index'));
e.preventDefault();
e.stopPropagation();
}
};
handleClick = e => {
const value = e.currentTarget.getAttribute('data-index');
e.preventDefault();
this.props.onClose();
this.props.onChange(value);
};
componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
if (this.focusedItem) this.focusedItem.focus({ preventScroll: true });
}
componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
setRef = c => {
this.node = c;
};
setFocusRef = c => {
this.focusedItem = c;
};
render () {
const { style, items, value } = this.props;
return (
<div style={{ ...style }} role='listbox' ref={this.setRef}>
{items.map(item => (
<div role='option' tabIndex={0} key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}>
<div className='privacy-dropdown__option__icon'>
<Icon id={item.icon} icon={item.iconComponent} />
</div>
<div className='privacy-dropdown__option__content'>
<strong>{item.text}</strong>
{item.meta}
</div>
{item.extra && (
<div className='privacy-dropdown__option__additional' title={item.extra}>
<Icon id='info-circle' icon={InfoIcon} />
</div>
)}
</div>
))}
</div>
);
}
}
class PrivacyDropdown extends PureComponent { class PrivacyDropdown extends PureComponent {
static propTypes = { static propTypes = {

View File

@ -0,0 +1,128 @@
import PropTypes from 'prop-types';
import { useCallback, useEffect, useRef, useState } from 'react';
import classNames from 'classnames';
import { supportsPassiveEvents } from 'detect-passive-events';
import InfoIcon from '@/material-icons/400-24px/info.svg?react';
import { Icon } from 'mastodon/components/icon';
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
export const PrivacyDropdownMenu = ({ style, items, value, onClose, onChange }) => {
const nodeRef = useRef(null);
const focusedItemRef = useRef(null);
const [currentValue, setCurrentValue] = useState(value);
const handleDocumentClick = useCallback((e) => {
if (nodeRef.current && !nodeRef.current.contains(e.target)) {
onClose();
e.stopPropagation();
}
}, [nodeRef, onClose]);
const handleClick = useCallback((e) => {
const value = e.currentTarget.getAttribute('data-index');
e.preventDefault();
onClose();
onChange(value);
}, [onClose, onChange]);
const handleKeyDown = useCallback((e) => {
const value = e.currentTarget.getAttribute('data-index');
const index = items.findIndex(item => (item.value === value));
let element = null;
switch (e.key) {
case 'Escape':
onClose();
break;
case ' ':
case 'Enter':
handleClick(e);
break;
case 'ArrowDown':
element = nodeRef.current.childNodes[index + 1] || nodeRef.current.firstChild;
break;
case 'ArrowUp':
element = nodeRef.current.childNodes[index - 1] || nodeRef.current.lastChild;
break;
case 'Tab':
if (e.shiftKey) {
element = nodeRef.current.childNodes[index + 1] || nodeRef.current.firstChild;
} else {
element = nodeRef.current.childNodes[index - 1] || nodeRef.current.lastChild;
}
break;
case 'Home':
element = nodeRef.current.firstChild;
break;
case 'End':
element = nodeRef.current.lastChild;
break;
}
if (element) {
element.focus();
setCurrentValue(element.getAttribute('data-index'));
e.preventDefault();
e.stopPropagation();
}
}, [nodeRef, items, onClose, handleClick, setCurrentValue]);
useEffect(() => {
document.addEventListener('click', handleDocumentClick, { capture: true });
document.addEventListener('touchend', handleDocumentClick, listenerOptions);
focusedItemRef.current?.focus({ preventScroll: true });
return () => {
document.removeEventListener('click', handleDocumentClick, { capture: true });
document.removeEventListener('touchend', handleDocumentClick, listenerOptions);
};
}, [handleDocumentClick]);
return (
<ul style={{ ...style }} role='listbox' ref={nodeRef}>
{items.map(item => (
<li
role='option'
tabIndex={0}
key={item.value}
data-index={item.value}
onKeyDown={handleKeyDown}
onClick={handleClick}
className={classNames('privacy-dropdown__option', { active: item.value === currentValue })}
aria-selected={item.value === currentValue}
ref={item.value === currentValue ? focusedItemRef : null}
>
<div className='privacy-dropdown__option__icon'>
<Icon id={item.icon} icon={item.iconComponent} />
</div>
<div className='privacy-dropdown__option__content'>
<strong>{item.text}</strong>
{item.meta}
</div>
{item.extra && (
<div className='privacy-dropdown__option__additional' title={item.extra}>
<Icon id='info-circle' icon={InfoIcon} />
</div>
)}
</li>
))}
</ul>
);
};
PrivacyDropdownMenu.propTypes = {
style: PropTypes.object,
items: PropTypes.array.isRequired,
value: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
};

View File

@ -9,7 +9,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import spring from 'react-motion/lib/spring'; import spring from 'react-motion/lib/spring';
import CloseIcon from '@/material-icons/400-24px/close.svg?react'; import CloseIcon from '@/material-icons/400-20px/close.svg?react';
import EditIcon from '@/material-icons/400-24px/edit.svg?react'; import EditIcon from '@/material-icons/400-24px/edit.svg?react';
import WarningIcon from '@/material-icons/400-24px/warning.svg?react'; import WarningIcon from '@/material-icons/400-24px/warning.svg?react';
import { Blurhash } from 'mastodon/components/blurhash'; import { Blurhash } from 'mastodon/components/blurhash';

View File

@ -6,7 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react'; import PhotoLibraryIcon from '@/material-icons/400-20px/photo_library.svg?react';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
const messages = defineMessages({ const messages = defineMessages({
@ -65,6 +65,7 @@ class UploadButton extends ImmutablePureComponent {
key={resetFileKey} key={resetFileKey}
ref={this.setRef} ref={this.setRef}
type='file' type='file'
name='file-upload-input'
multiple multiple
accept={acceptContentTypes.toArray().join(',')} accept={acceptContentTypes.toArray().join(',')}
onChange={this.handleChange} onChange={this.handleChange}

View File

@ -2,7 +2,7 @@ import { injectIntl, defineMessages } from 'react-intl';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import WarningIcon from 'mastodon/../material-icons/400-24px/warning.svg?react'; import WarningIcon from '@/material-icons/400-20px/warning.svg?react';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
import { changeComposeSpoilerness } from '../../../actions/compose'; import { changeComposeSpoilerness } from '../../../actions/compose';

View File

@ -3,14 +3,24 @@ import { connect } from 'react-redux';
import { uploadCompose } from '../../../actions/compose'; import { uploadCompose } from '../../../actions/compose';
import UploadButton from '../components/upload_button'; import UploadButton from '../components/upload_button';
const mapStateToProps = state => ({ const mapStateToProps = state => {
disabled: state.getIn(['compose', 'poll']) !== null || state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size + state.getIn(['compose', 'pending_media_attachments']) > 3 || (!state.getIn(['server', 'server', 'configuration', 'media_attachments', 'allow_mix_media'], false) && state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type'))))), const isPoll = state.getIn(['compose', 'poll']) !== null;
resetFileKey: state.getIn(['compose', 'resetFileKey']), const isUploading = state.getIn(['compose', 'is_uploading']);
}); const readyAttachmentsSize = state.getIn(['compose', 'media_attachments']).size ?? 0;
const pendingAttachmentsSize = state.getIn(['compose', 'pending_media_attachments']).size ?? 0;
const attachmentsSize = readyAttachmentsSize + pendingAttachmentsSize;
const isOverLimit = attachmentsSize > 3;
const allowMixMedia = state.getIn(['server', 'server', 'configuration', 'media_attachments', 'allow_mix_media'], false);
const hasVideoOrAudio = state.getIn(['compose', 'media_attachments']).some(m => ['video', 'audio'].includes(m.get('type')));
return {
disabled: isPoll || isUploading || isOverLimit || (!allowMixMedia && hasVideoOrAudio),
resetFileKey: state.getIn(['compose', 'resetFileKey']),
};
};
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
onSelectFile (files) { onSelectFile(files) {
dispatch(uploadCompose(files)); dispatch(uploadCompose(files));
}, },

View File

@ -36,7 +36,7 @@ Object.keys(emojiIndex.emojis).forEach(key => {
let emoji = emojiIndex.emojis[key]; let emoji = emojiIndex.emojis[key];
// Emojis with skin tone modifiers are stored like this // Emojis with skin tone modifiers are stored like this
if (Object.prototype.hasOwnProperty.call(emoji, '1')) { if (Object.hasOwn(emoji, '1')) {
emoji = emoji['1']; emoji = emoji['1'];
} }
@ -88,7 +88,7 @@ Object.keys(emojiIndex.emojis).forEach(key => {
let emoji = emojiIndex.emojis[key]; let emoji = emojiIndex.emojis[key];
// Emojis with skin tone modifiers are stored like this // Emojis with skin tone modifiers are stored like this
if (Object.prototype.hasOwnProperty.call(emoji, '1')) { if (Object.hasOwn(emoji, '1')) {
emoji = emoji['1']; emoji = emoji['1'];
} }

View File

@ -135,19 +135,19 @@ function getData(emoji, skin, set) {
} }
} }
if (Object.prototype.hasOwnProperty.call(data.short_names, emoji)) { if (Object.hasOwn(data.short_names, emoji)) {
emoji = data.short_names[emoji]; emoji = data.short_names[emoji];
} }
if (Object.prototype.hasOwnProperty.call(data.emojis, emoji)) { if (Object.hasOwn(data.emojis, emoji)) {
emojiData = data.emojis[emoji]; emojiData = data.emojis[emoji];
} }
} else if (emoji.id) { } else if (emoji.id) {
if (Object.prototype.hasOwnProperty.call(data.short_names, emoji.id)) { if (Object.hasOwn(data.short_names, emoji.id)) {
emoji.id = data.short_names[emoji.id]; emoji.id = data.short_names[emoji.id];
} }
if (Object.prototype.hasOwnProperty.call(data.emojis, emoji.id)) { if (Object.hasOwn(data.emojis, emoji.id)) {
emojiData = data.emojis[emoji.id]; emojiData = data.emojis[emoji.id];
skin = skin || emoji.skin; skin = skin || emoji.skin;
} }
@ -216,7 +216,7 @@ function deepMerge(a, b) {
let originalValue = a[key], let originalValue = a[key],
value = originalValue; value = originalValue;
if (Object.prototype.hasOwnProperty.call(b, key)) { if (Object.hasOwn(b, key)) {
value = b[key]; value = b[key];
} }

View File

@ -8,8 +8,8 @@ import { NavLink, Switch, Route } from 'react-router-dom';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
import SearchIcon from '@/material-icons/400-24px/search.svg?react'; import SearchIcon from '@/material-icons/400-24px/search.svg?react';
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import Column from 'mastodon/components/column'; import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header'; import ColumnHeader from 'mastodon/components/column_header';
import Search from 'mastodon/features/compose/containers/search_container'; import Search from 'mastodon/features/compose/containers/search_container';
@ -58,8 +58,8 @@ class Explore extends PureComponent {
return ( return (
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}> <Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
<ColumnHeader <ColumnHeader
icon={isSearching ? 'search' : 'hashtag'} icon={isSearching ? 'search' : 'explore'}
iconComponent={isSearching ? SearchIcon : TagIcon} iconComponent={isSearching ? SearchIcon : ExploreIcon}
title={intl.formatMessage(isSearching ? messages.searchResults : messages.title)} title={intl.formatMessage(isSearching ? messages.searchResults : messages.title)}
onClick={this.handleHeaderClick} onClick={this.handleHeaderClick}
multiColumn={multiColumn} multiColumn={multiColumn}

View File

@ -343,7 +343,7 @@ class Announcement extends ImmutablePureComponent {
<div className='announcements__item'> <div className='announcements__item'>
<strong className='announcements__item__range'> <strong className='announcements__item__range'>
<FormattedMessage id='announcement.announcement' defaultMessage='Announcement' /> <FormattedMessage id='announcement.announcement' defaultMessage='Announcement' />
{hasTimeRange && <span> · <FormattedDate value={startsAt} hour12={false} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} hour12={false} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>} {hasTimeRange && <span> · <FormattedDate value={startsAt} year={(skipYear || startsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month='short' day='2-digit' hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /> - <FormattedDate value={endsAt} year={(skipYear || endsAt.getFullYear() === now.getFullYear()) ? undefined : 'numeric'} month={skipEndDate ? undefined : 'short'} day={skipEndDate ? undefined : '2-digit'} hour={skipTime ? undefined : '2-digit'} minute={skipTime ? undefined : '2-digit'} /></span>}
</strong> </strong>
<Content announcement={announcement} /> <Content announcement={announcement} />

View File

@ -112,7 +112,7 @@ class GettingStarted extends ImmutablePureComponent {
if (showTrends) { if (showTrends) {
navItems.push( navItems.push(
<ColumnLink key='explore' icon='hashtag' iconComponent={TagIcon} text={intl.formatMessage(messages.explore)} to='/explore' />, <ColumnLink key='explore' icon='explore' iconComponent={TagIcon} text={intl.formatMessage(messages.explore)} to='/explore' />,
); );
} }

View File

@ -21,6 +21,7 @@ import { DisplayName } from 'mastodon/components/display_name';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
import { VerifiedBadge } from 'mastodon/components/verified_badge'; import { VerifiedBadge } from 'mastodon/components/verified_badge';
import { domain } from 'mastodon/initial_state';
const messages = defineMessages({ const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' }, follow: { id: 'account.follow', defaultMessage: 'Follow' },
@ -28,27 +29,43 @@ const messages = defineMessages({
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' }, previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
next: { id: 'lightbox.next', defaultMessage: 'Next' }, next: { id: 'lightbox.next', defaultMessage: 'Next' },
dismiss: { id: 'follow_suggestions.dismiss', defaultMessage: "Don't show again" }, dismiss: { id: 'follow_suggestions.dismiss', defaultMessage: "Don't show again" },
friendsOfFriendsHint: { id: 'follow_suggestions.hints.friends_of_friends', defaultMessage: 'This profile is popular among the people you follow.' },
similarToRecentlyFollowedHint: { id: 'follow_suggestions.hints.similar_to_recently_followed', defaultMessage: 'This profile is similar to the profiles you have most recently followed.' },
featuredHint: { id: 'follow_suggestions.hints.featured', defaultMessage: 'This profile has been hand-picked by the {domain} team.' },
mostFollowedHint: { id: 'follow_suggestions.hints.most_followed', defaultMessage: 'This profile is one of the most followed on {domain}.'},
mostInteractionsHint: { id: 'follow_suggestions.hints.most_interactions', defaultMessage: 'This profile has been recently getting a lot of attention on {domain}.' },
}); });
const Source = ({ id }) => { const Source = ({ id }) => {
let label; const intl = useIntl();
let label, hint;
switch (id) { switch (id) {
case 'friends_of_friends': case 'friends_of_friends':
hint = intl.formatMessage(messages.friendsOfFriendsHint);
label = <FormattedMessage id='follow_suggestions.personalized_suggestion' defaultMessage='Personalized suggestion' />;
break;
case 'similar_to_recently_followed': case 'similar_to_recently_followed':
hint = intl.formatMessage(messages.similarToRecentlyFollowedHint);
label = <FormattedMessage id='follow_suggestions.personalized_suggestion' defaultMessage='Personalized suggestion' />; label = <FormattedMessage id='follow_suggestions.personalized_suggestion' defaultMessage='Personalized suggestion' />;
break; break;
case 'featured': case 'featured':
label = <FormattedMessage id='follow_suggestions.curated_suggestion' defaultMessage="Editors' Choice" />; hint = intl.formatMessage(messages.featuredHint, { domain });
label = <FormattedMessage id='follow_suggestions.curated_suggestion' defaultMessage='Staff pick' />;
break; break;
case 'most_followed': case 'most_followed':
hint = intl.formatMessage(messages.mostFollowedHint, { domain });
label = <FormattedMessage id='follow_suggestions.popular_suggestion' defaultMessage='Popular suggestion' />;
break;
case 'most_interactions': case 'most_interactions':
hint = intl.formatMessage(messages.mostInteractionsHint, { domain });
label = <FormattedMessage id='follow_suggestions.popular_suggestion' defaultMessage='Popular suggestion' />; label = <FormattedMessage id='follow_suggestions.popular_suggestion' defaultMessage='Popular suggestion' />;
break; break;
} }
return ( return (
<div className='inline-follow-suggestions__body__scrollable__card__text-stack__source'> <div className='inline-follow-suggestions__body__scrollable__card__text-stack__source' title={hint}>
<Icon icon={InfoIcon} /> <Icon icon={InfoIcon} />
{label} {label}
</div> </div>
@ -59,7 +76,7 @@ Source.propTypes = {
id: PropTypes.oneOf(['friends_of_friends', 'similar_to_recently_followed', 'featured', 'most_followed', 'most_interactions']), id: PropTypes.oneOf(['friends_of_friends', 'similar_to_recently_followed', 'featured', 'most_followed', 'most_interactions']),
}; };
const Card = ({ id, source }) => { const Card = ({ id, sources }) => {
const intl = useIntl(); const intl = useIntl();
const account = useSelector(state => state.getIn(['accounts', id])); const account = useSelector(state => state.getIn(['accounts', id]));
const relationship = useSelector(state => state.getIn(['relationships', id])); const relationship = useSelector(state => state.getIn(['relationships', id]));
@ -89,17 +106,17 @@ const Card = ({ id, source }) => {
<div className='inline-follow-suggestions__body__scrollable__card__text-stack'> <div className='inline-follow-suggestions__body__scrollable__card__text-stack'>
<Link to={`/@${account.get('acct')}`}><DisplayName account={account} /></Link> <Link to={`/@${account.get('acct')}`}><DisplayName account={account} /></Link>
{firstVerifiedField ? <VerifiedBadge link={firstVerifiedField.get('value')} /> : <Source id={source.get(0)} />} {firstVerifiedField ? <VerifiedBadge link={firstVerifiedField.get('value')} /> : <Source id={sources.get(0)} />}
</div> </div>
<Button text={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={handleFollow} /> <Button text={intl.formatMessage(following ? messages.unfollow : messages.follow)} secondary={following} onClick={handleFollow} />
</div> </div>
); );
}; };
Card.propTypes = { Card.propTypes = {
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
source: ImmutablePropTypes.list, sources: ImmutablePropTypes.list,
}; };
const DISMISSIBLE_ID = 'home/follow-suggestions'; const DISMISSIBLE_ID = 'home/follow-suggestions';
@ -175,7 +192,7 @@ export const InlineFollowSuggestions = ({ hidden }) => {
<Card <Card
key={suggestion.get('account')} key={suggestion.get('account')}
id={suggestion.get('account')} id={suggestion.get('account')}
source={suggestion.get('source')} sources={suggestion.get('sources')}
/> />
))} ))}
</div> </div>

View File

@ -92,6 +92,10 @@ export default class Card extends PureComponent {
this.setState({ embedded: true }); this.setState({ embedded: true });
}; };
handleExternalLinkClick = (e) => {
e.stopPropagation();
};
setRef = c => { setRef = c => {
this.node = c; this.node = c;
}; };
@ -201,7 +205,7 @@ export default class Card extends PureComponent {
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'> <div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
<div> <div>
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button> <button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
<a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a> <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
</div> </div>
</div> </div>
) : spoilerButton} ) : spoilerButton}

View File

@ -311,7 +311,7 @@ class DetailedStatus extends ImmutablePureComponent {
<div className='detailed-status__meta'> <div className='detailed-status__meta'>
<a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'> <a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
<FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' /> <FormattedDate value={new Date(status.get('created_at'))} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
</a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink} </a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink}
</div> </div>
</div> </div>

View File

@ -7,6 +7,7 @@ import { Link } from 'react-router-dom';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react'; import BookmarksIcon from '@/material-icons/400-24px/bookmarks-fill.svg?react';
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react'; import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react'; import ListAltIcon from '@/material-icons/400-24px/list_alt.svg?react';
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
@ -14,7 +15,6 @@ import PublicIcon from '@/material-icons/400-24px/public.svg?react';
import SearchIcon from '@/material-icons/400-24px/search.svg?react'; import SearchIcon from '@/material-icons/400-24px/search.svg?react';
import SettingsIcon from '@/material-icons/400-24px/settings-fill.svg?react'; import SettingsIcon from '@/material-icons/400-24px/settings-fill.svg?react';
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
import TagIcon from '@/material-icons/400-24px/tag.svg?react';
import { WordmarkLogo } from 'mastodon/components/logo'; import { WordmarkLogo } from 'mastodon/components/logo';
import { NavigationPortal } from 'mastodon/components/navigation_portal'; import { NavigationPortal } from 'mastodon/components/navigation_portal';
import { timelinePreview, trendsEnabled } from 'mastodon/initial_state'; import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
@ -94,7 +94,7 @@ class NavigationPanel extends Component {
)} )}
{trendsEnabled ? ( {trendsEnabled ? (
<ColumnLink transparent to='/explore' icon='hashtag' iconComponent={TagIcon} text={intl.formatMessage(messages.explore)} /> <ColumnLink transparent to='/explore' icon='explore' iconComponent={ExploreIcon} text={intl.formatMessage(messages.explore)} />
) : ( ) : (
<ColumnLink transparent to='/search' icon='search' iconComponent={SearchIcon} text={intl.formatMessage(messages.search)} /> <ColumnLink transparent to='/search' icon='search' iconComponent={SearchIcon} text={intl.formatMessage(messages.search)} />
)} )}

View File

@ -33,6 +33,7 @@
"account.follows.empty": "Die gebruiker volg nog niemand.", "account.follows.empty": "Die gebruiker volg nog niemand.",
"account.go_to_profile": "Gaan na profiel", "account.go_to_profile": "Gaan na profiel",
"account.hide_reblogs": "Versteek plasings wat deur @{name} aangestuur is", "account.hide_reblogs": "Versteek plasings wat deur @{name} aangestuur is",
"account.in_memoriam": "Ter nagedagtenis.",
"account.joined_short": "Aangesluit", "account.joined_short": "Aangesluit",
"account.link_verified_on": "Eienaarskap van hierdie skakel is nagegaan op {date}", "account.link_verified_on": "Eienaarskap van hierdie skakel is nagegaan op {date}",
"account.locked_info": "Die rekening se privaatheidstatus is gesluit. Die eienaar hersien handmatig wie hom/haar kan volg.", "account.locked_info": "Die rekening se privaatheidstatus is gesluit. Die eienaar hersien handmatig wie hom/haar kan volg.",
@ -71,6 +72,7 @@
"bundle_column_error.network.title": "Netwerkfout", "bundle_column_error.network.title": "Netwerkfout",
"bundle_column_error.retry": "Probeer weer", "bundle_column_error.retry": "Probeer weer",
"bundle_column_error.return": "Keer terug na die tuisblad", "bundle_column_error.return": "Keer terug na die tuisblad",
"bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Sluit", "bundle_modal_error.close": "Sluit",
"bundle_modal_error.message": "Die laai van die komponent het iewers skeefgeloop.", "bundle_modal_error.message": "Die laai van die komponent het iewers skeefgeloop.",
"bundle_modal_error.retry": "Probeer weer", "bundle_modal_error.retry": "Probeer weer",
@ -149,6 +151,8 @@
"emoji_button.food": "Eet- en drinkgoed", "emoji_button.food": "Eet- en drinkgoed",
"emoji_button.nature": "Natuur", "emoji_button.nature": "Natuur",
"emoji_button.not_found": "Geen passende emoji gevind nie", "emoji_button.not_found": "Geen passende emoji gevind nie",
"emoji_button.objects": "Voorwerpe",
"emoji_button.people": "Mense",
"emoji_button.search": "Soek...", "emoji_button.search": "Soek...",
"emoji_button.search_results": "Soekresultate", "emoji_button.search_results": "Soekresultate",
"empty_column.account_timeline": "Geen plasings hier nie!", "empty_column.account_timeline": "Geen plasings hier nie!",
@ -161,7 +165,12 @@
"empty_column.lists": "Jy het nog geen lyste nie. Wanneer jy een skep, sal dit hier vertoon.", "empty_column.lists": "Jy het nog geen lyste nie. Wanneer jy een skep, sal dit hier vertoon.",
"empty_column.notifications": "Jy het nog geen kennisgewings nie. Interaksie van ander mense met jou, sal hier vertoon.", "empty_column.notifications": "Jy het nog geen kennisgewings nie. Interaksie van ander mense met jou, sal hier vertoon.",
"explore.search_results": "Soekresultate", "explore.search_results": "Soekresultate",
"explore.suggested_follows": "Mense",
"explore.trending_links": "Nuus",
"filter_modal.added.settings_link": "instellings bladsy",
"filter_modal.select_filter.search": "Soek of skep", "filter_modal.select_filter.search": "Soek of skep",
"firehose.local": "Hierdie bediener",
"firehose.remote": "Ander bedieners",
"footer.about": "Oor", "footer.about": "Oor",
"footer.directory": "Profielgids", "footer.directory": "Profielgids",
"footer.get_app": "Kry die app", "footer.get_app": "Kry die app",
@ -170,14 +179,21 @@
"footer.privacy_policy": "Privaatheidsbeleid", "footer.privacy_policy": "Privaatheidsbeleid",
"footer.source_code": "Wys bronkode", "footer.source_code": "Wys bronkode",
"getting_started.heading": "Kom aan die gang", "getting_started.heading": "Kom aan die gang",
"hashtag.column_header.tag_mode.all": "en {additional}",
"hashtag.column_header.tag_mode.any": "of {additional}",
"hashtag.column_header.tag_mode.none": "sonder {additional}",
"hashtag.column_settings.select.placeholder": "Voer hutsetikette in…", "hashtag.column_settings.select.placeholder": "Voer hutsetikette in…",
"hashtag.column_settings.tag_toggle": "Voeg meer etikette by hierdie kolom", "hashtag.column_settings.tag_toggle": "Voeg meer etikette by hierdie kolom",
"hashtag.follow": "Volg hutsetiket", "hashtag.follow": "Volg hutsetiket",
"home.column_settings.show_reblogs": "Wys aangestuurde plasings", "home.column_settings.show_reblogs": "Wys aangestuurde plasings",
"interaction_modal.description.reblog": "Met 'n rekening op Mastodon kan jy hierdie plasing aanstuur om dit met jou volgers te deel.", "interaction_modal.description.reblog": "Met 'n rekening op Mastodon kan jy hierdie plasing aanstuur om dit met jou volgers te deel.",
"interaction_modal.description.reply": "Met 'n rekening op Mastodon kan jy op hierdie plasing reageer.", "interaction_modal.description.reply": "Met 'n rekening op Mastodon kan jy op hierdie plasing reageer.",
"interaction_modal.title.follow": "Volg {name}",
"interaction_modal.title.reblog": "Stuur {name} se plasing aan", "interaction_modal.title.reblog": "Stuur {name} se plasing aan",
"interaction_modal.title.reply": "Reageer op {name} se plasing", "interaction_modal.title.reply": "Reageer op {name} se plasing",
"intervals.full.days": "{number, plural, one {# dag} other {# dae}}",
"intervals.full.hours": "{number, plural, one {# uur} other {# uur}}",
"intervals.full.minutes": "{number, plural, one {# minuut} other {# minute}}",
"keyboard_shortcuts.back": "Navigeer terug", "keyboard_shortcuts.back": "Navigeer terug",
"keyboard_shortcuts.blocked": "Vertoon lys van geblokkeerde gebruikers", "keyboard_shortcuts.blocked": "Vertoon lys van geblokkeerde gebruikers",
"keyboard_shortcuts.boost": "Stuur aan", "keyboard_shortcuts.boost": "Stuur aan",
@ -209,8 +225,11 @@
"keyboard_shortcuts.toot": "Begin n nuwe plasing", "keyboard_shortcuts.toot": "Begin n nuwe plasing",
"keyboard_shortcuts.unfocus": "Fokus uit van teksveld/soekveld", "keyboard_shortcuts.unfocus": "Fokus uit van teksveld/soekveld",
"keyboard_shortcuts.up": "Beweeg opwaarts in die lys", "keyboard_shortcuts.up": "Beweeg opwaarts in die lys",
"lightbox.next": "Volgende",
"lightbox.previous": "Vorige",
"limited_account_hint.action": "Vertoon profiel in elk geval", "limited_account_hint.action": "Vertoon profiel in elk geval",
"limited_account_hint.title": "Hierdie profiel is deur moderators van {domain} versteek.", "limited_account_hint.title": "Hierdie profiel is deur moderators van {domain} versteek.",
"link_preview.author": "Deur {name}",
"lists.account.add": "Voeg by lys", "lists.account.add": "Voeg by lys",
"lists.account.remove": "Verwyder vanaf lys", "lists.account.remove": "Verwyder vanaf lys",
"lists.delete": "Verwyder lys", "lists.delete": "Verwyder lys",
@ -237,6 +256,7 @@
"notification.reblog": "{name} het jou plasing aangestuur", "notification.reblog": "{name} het jou plasing aangestuur",
"notifications.column_settings.push": "Stootkennisgewings", "notifications.column_settings.push": "Stootkennisgewings",
"notifications.column_settings.reblog": "Aangestuurde plasings:", "notifications.column_settings.reblog": "Aangestuurde plasings:",
"notifications.column_settings.sound": "Speel klank",
"notifications.column_settings.status": "Nuwe plasings:", "notifications.column_settings.status": "Nuwe plasings:",
"notifications.column_settings.unread_notifications.highlight": "Lig ongelese kennisgewings uit", "notifications.column_settings.unread_notifications.highlight": "Lig ongelese kennisgewings uit",
"notifications.filter.boosts": "Aangestuurde plasings", "notifications.filter.boosts": "Aangestuurde plasings",
@ -300,5 +320,8 @@
"upload_form.audio_description": "Describe for people with hearing loss", "upload_form.audio_description": "Describe for people with hearing loss",
"upload_form.description": "Describe for the visually impaired", "upload_form.description": "Describe for the visually impaired",
"upload_form.video_description": "Describe for people with hearing loss or visual impairment", "upload_form.video_description": "Describe for people with hearing loss or visual impairment",
"upload_progress.label": "Uploading…" "upload_progress.label": "Uploading…",
"video.fullscreen": "Volskerm",
"video.mute": "Klank afskakel",
"video.unmute": "Klank aanskakel"
} }

View File

@ -21,6 +21,7 @@
"account.blocked": "محظور", "account.blocked": "محظور",
"account.browse_more_on_origin_server": "تصفح المزيد في الملف الشخصي الأصلي", "account.browse_more_on_origin_server": "تصفح المزيد في الملف الشخصي الأصلي",
"account.cancel_follow_request": "إلغاء طلب المتابعة", "account.cancel_follow_request": "إلغاء طلب المتابعة",
"account.copy": "نسخ الرابط إلى الملف الشخصي",
"account.direct": "إشارة خاصة لـ @{name}", "account.direct": "إشارة خاصة لـ @{name}",
"account.disable_notifications": "توقف عن إشعاري عندما ينشر @{name}", "account.disable_notifications": "توقف عن إشعاري عندما ينشر @{name}",
"account.domain_blocked": "اسم النِّطاق محظور", "account.domain_blocked": "اسم النِّطاق محظور",
@ -31,6 +32,7 @@
"account.featured_tags.last_status_never": "لا توجد رسائل", "account.featured_tags.last_status_never": "لا توجد رسائل",
"account.featured_tags.title": "وسوم {name} المميَّزة", "account.featured_tags.title": "وسوم {name} المميَّزة",
"account.follow": "متابعة", "account.follow": "متابعة",
"account.follow_back": "تابعه بدورك",
"account.followers": "مُتابِعون", "account.followers": "مُتابِعون",
"account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.", "account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.",
"account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two {مُتابعانِ اِثنان} few {{counter} مُتابِعين} many {{counter} مُتابِعًا} other {{counter} مُتابع}}", "account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two {مُتابعانِ اِثنان} few {{counter} مُتابِعين} many {{counter} مُتابِعًا} other {{counter} مُتابع}}",
@ -51,6 +53,7 @@
"account.mute_notifications_short": "كتم الإشعارات", "account.mute_notifications_short": "كتم الإشعارات",
"account.mute_short": "اكتم", "account.mute_short": "اكتم",
"account.muted": "مَكتوم", "account.muted": "مَكتوم",
"account.mutual": "متبادل",
"account.no_bio": "لم يتم تقديم وصف.", "account.no_bio": "لم يتم تقديم وصف.",
"account.open_original_page": "افتح الصفحة الأصلية", "account.open_original_page": "افتح الصفحة الأصلية",
"account.posts": "منشورات", "account.posts": "منشورات",
@ -143,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "مُقفَل", "compose_form.lock_disclaimer.lock": "مُقفَل",
"compose_form.placeholder": "فِيمَ تُفكِّر؟", "compose_form.placeholder": "فِيمَ تُفكِّر؟",
"compose_form.poll.duration": "مُدَّة اِستطلاع الرأي", "compose_form.poll.duration": "مُدَّة اِستطلاع الرأي",
"compose_form.poll.multiple": "متعدد الخيارات",
"compose_form.poll.option_placeholder": "الخيار {number}",
"compose_form.poll.single": "اختر واحدا",
"compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة", "compose_form.poll.switch_to_multiple": "تغيِير الاستطلاع للسماح باِخيارات مُتعدِّدة",
"compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط", "compose_form.poll.switch_to_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط",
"compose_form.poll.type": "الأسلوب",
"compose_form.publish": "نشر",
"compose_form.publish_form": "منشور جديد", "compose_form.publish_form": "منشور جديد",
"compose_form.reply": "ردّ",
"compose_form.save_changes": "تحديث",
"compose_form.spoiler.marked": "إزالة تحذير المحتوى", "compose_form.spoiler.marked": "إزالة تحذير المحتوى",
"compose_form.spoiler.unmarked": "إضافة تحذير للمحتوى", "compose_form.spoiler.unmarked": "إضافة تحذير للمحتوى",
"compose_form.spoiler_placeholder": "تحذير المحتوى (اختياري)",
"confirmation_modal.cancel": "إلغاء", "confirmation_modal.cancel": "إلغاء",
"confirmations.block.block_and_report": "حظره والإبلاغ عنه", "confirmations.block.block_and_report": "حظره والإبلاغ عنه",
"confirmations.block.confirm": "حظر", "confirmations.block.confirm": "حظر",
@ -179,6 +190,7 @@
"conversation.mark_as_read": "اعتبرها كمقروءة", "conversation.mark_as_read": "اعتبرها كمقروءة",
"conversation.open": "اعرض المحادثة", "conversation.open": "اعرض المحادثة",
"conversation.with": "مع {names}", "conversation.with": "مع {names}",
"copy_icon_button.copied": "نُسِخ إلى الحافظة",
"copypaste.copied": "تم نسخه", "copypaste.copied": "تم نسخه",
"copypaste.copy_to_clipboard": "نسخ إلى الحافظة", "copypaste.copy_to_clipboard": "نسخ إلى الحافظة",
"directory.federated": "مِن الفديفرس المعروف", "directory.federated": "مِن الفديفرس المعروف",
@ -210,6 +222,7 @@
"emoji_button.search_results": "نتائج البحث", "emoji_button.search_results": "نتائج البحث",
"emoji_button.symbols": "رموز", "emoji_button.symbols": "رموز",
"emoji_button.travel": "الأماكن والسفر", "emoji_button.travel": "الأماكن والسفر",
"empty_column.account_hides_collections": "اختار هذا المستخدم عدم إتاحة هذه المعلومات للعامة",
"empty_column.account_suspended": "حساب معلق", "empty_column.account_suspended": "حساب معلق",
"empty_column.account_timeline": "لا توجد منشورات هنا!", "empty_column.account_timeline": "لا توجد منشورات هنا!",
"empty_column.account_unavailable": "الملف التعريفي غير متوفر", "empty_column.account_unavailable": "الملف التعريفي غير متوفر",
@ -264,6 +277,11 @@
"follow_request.authorize": "ترخيص", "follow_request.authorize": "ترخيص",
"follow_request.reject": "رفض", "follow_request.reject": "رفض",
"follow_requests.unlocked_explanation": "حتى وإن كان حسابك غير مقفل، يعتقد فريق {domain} أنك قد ترغب في مراجعة طلبات المتابعة من هذه الحسابات يدوياً.", "follow_requests.unlocked_explanation": "حتى وإن كان حسابك غير مقفل، يعتقد فريق {domain} أنك قد ترغب في مراجعة طلبات المتابعة من هذه الحسابات يدوياً.",
"follow_suggestions.dismiss": "لا تُظهرها مجدّدًا",
"follow_suggestions.personalized_suggestion": "توصية مخصصة",
"follow_suggestions.popular_suggestion": "توصية رائجة",
"follow_suggestions.view_all": "عرض الكل",
"follow_suggestions.who_to_follow": "حسابات للمُتابَعة",
"followed_tags": "الوسوم المتابَعة", "followed_tags": "الوسوم المتابَعة",
"footer.about": "عن", "footer.about": "عن",
"footer.directory": "دليل الصفحات التعريفية", "footer.directory": "دليل الصفحات التعريفية",
@ -290,13 +308,9 @@
"hashtag.follow": "اتبع الوسم", "hashtag.follow": "اتبع الوسم",
"hashtag.unfollow": "ألغِ متابعة الوسم", "hashtag.unfollow": "ألغِ متابعة الوسم",
"hashtags.and_other": "…و {count, plural, zero {} one {# واحد آخر} two {# اثنان آخران} few {# آخرون} many {# آخَرًا}other {# آخرون}}", "hashtags.and_other": "…و {count, plural, zero {} one {# واحد آخر} two {# اثنان آخران} few {# آخرون} many {# آخَرًا}other {# آخرون}}",
"home.actions.go_to_explore": "اطّلع على ما هو رائج حاليا",
"home.actions.go_to_suggestions": "ابحث عن أشخاص لِمُتابعتهم",
"home.column_settings.basic": "الأساسية", "home.column_settings.basic": "الأساسية",
"home.column_settings.show_reblogs": "اعرض المعاد نشرها", "home.column_settings.show_reblogs": "اعرض المعاد نشرها",
"home.column_settings.show_replies": "اعرض الردود", "home.column_settings.show_replies": "اعرض الردود",
"home.explore_prompt.body": "سوف يحتوي خيط أخبارك الرئيسي على مزيج من المنشورات مِنها التي تحتوي على وسوم اخترتَ متابعتها، وأشخاص اخترتَ متابعتهم والمنشورات التي أعادوا نشرها. ومع ذلك، إن لا زال خيط أخبارك يبدو هادئا جدا، ماذا لو:",
"home.explore_prompt.title": "هذه هي صفحتك الرئيسة في ماستدون.",
"home.hide_announcements": "إخفاء الإعلانات", "home.hide_announcements": "إخفاء الإعلانات",
"home.pending_critical_update.body": "يرجى تحديث خادم ماستدون في أقرب وقت ممكن!", "home.pending_critical_update.body": "يرجى تحديث خادم ماستدون في أقرب وقت ممكن!",
"home.pending_critical_update.link": "اطّلع على التحديثات", "home.pending_critical_update.link": "اطّلع على التحديثات",
@ -377,6 +391,7 @@
"lists.search": "إبحث في قائمة الحسابات التي تُتابِعها", "lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
"lists.subheading": "قوائمك", "lists.subheading": "قوائمك",
"load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}", "load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}",
"loading_indicator.label": "جاري التحميل…",
"media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}", "media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}",
"moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.", "moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.",
"mute_modal.duration": "المدة", "mute_modal.duration": "المدة",
@ -464,6 +479,17 @@
"onboarding.follows.empty": "نأسف، لا يمكن عرض نتائج في الوقت الحالي. جرب البحث أو انتقل لصفحة الاستكشاف لإيجاد أشخاص للمتابعة، أو حاول مرة أخرى.", "onboarding.follows.empty": "نأسف، لا يمكن عرض نتائج في الوقت الحالي. جرب البحث أو انتقل لصفحة الاستكشاف لإيجاد أشخاص للمتابعة، أو حاول مرة أخرى.",
"onboarding.follows.lead": "مقتطفات خيطك الرئيس هي الطريقة الأساسية لتجربة ماستدون. كلما زاد عدد الأشخاص الذين تتبعهم، كلما زاد خيط أخبارك نشاطا وإثارة للاهتمام. بداية، إليك بعض الاقتراحات:", "onboarding.follows.lead": "مقتطفات خيطك الرئيس هي الطريقة الأساسية لتجربة ماستدون. كلما زاد عدد الأشخاص الذين تتبعهم، كلما زاد خيط أخبارك نشاطا وإثارة للاهتمام. بداية، إليك بعض الاقتراحات:",
"onboarding.follows.title": "أضفِ طابعا شخصيا على موجزات خيطك الرئيس", "onboarding.follows.title": "أضفِ طابعا شخصيا على موجزات خيطك الرئيس",
"onboarding.profile.discoverable": "اجعل ملفي الشخصي قابلاً للاكتشاف",
"onboarding.profile.discoverable_hint": "عندما تختار تفعيل إمكانية الاكتشاف على ماستدون، قد تظهر منشوراتك في نتائج البحث والمواضيع الرائجة، وقد يتم اقتراح ملفك الشخصي لأشخاص ذوي اهتمامات مماثلة معك.",
"onboarding.profile.display_name": "الاسم العلني",
"onboarding.profile.display_name_hint": "اسمك الكامل أو اسمك المرح…",
"onboarding.profile.lead": "يمكنك دائمًا إكمال ذلك لاحقًا في الإعدادات، حيث يتوفر المزيد من خيارات التخصيص.",
"onboarding.profile.note": "نبذة عنك",
"onboarding.profile.note_hint": "يمكنك @ذِكر أشخاص آخرين أو استعمال #الوسوم…",
"onboarding.profile.save_and_continue": "حفظ و إستمرار",
"onboarding.profile.title": "إعداد الملف الشخصي",
"onboarding.profile.upload_avatar": "تحميل صورة الملف الشخصي",
"onboarding.profile.upload_header": "تحميل رأسية الملف الشخصي",
"onboarding.share.lead": "اسمح للأشخاص بمعرفة إمكانية الوصول إليك على ماستدون!", "onboarding.share.lead": "اسمح للأشخاص بمعرفة إمكانية الوصول إليك على ماستدون!",
"onboarding.share.message": "أنا {username} في #Mastodon! تعال لمتابعتي على {url}", "onboarding.share.message": "أنا {username} في #Mastodon! تعال لمتابعتي على {url}",
"onboarding.share.next_steps": "الخطوات المحتملة التالية:", "onboarding.share.next_steps": "الخطوات المحتملة التالية:",
@ -497,9 +523,18 @@
"poll_button.add_poll": "إضافة استطلاع للرأي", "poll_button.add_poll": "إضافة استطلاع للرأي",
"poll_button.remove_poll": "إزالة استطلاع الرأي", "poll_button.remove_poll": "إزالة استطلاع الرأي",
"privacy.change": "اضبط خصوصية المنشور", "privacy.change": "اضبط خصوصية المنشور",
"privacy.direct.long": "كل من ذُكر في المنشور",
"privacy.direct.short": "أشخاص محددون",
"privacy.private.long": "متابعيك فقط",
"privacy.private.short": "للمتابِعين",
"privacy.public.long": "أي شخص على أو خارج ماستدون",
"privacy.public.short": "للعامة", "privacy.public.short": "للعامة",
"privacy.unlisted.additional": "هذا يتصرف بالضبط مثل النشر للعامة، باستثناء أن المنشور لن يظهر في الموجزات الحية أو في الوسوم أو في الإستكشاف، أو في نتائج بحث ماستدون، حتى وإن قمت بتفعيله على مستوى الحساب.",
"privacy.unlisted.long": "خوارزميات أقل",
"privacy.unlisted.short": "للعامة دون صخب",
"privacy_policy.last_updated": "آخر تحديث {date}", "privacy_policy.last_updated": "آخر تحديث {date}",
"privacy_policy.title": "سياسة الخصوصية", "privacy_policy.title": "سياسة الخصوصية",
"recommended": "موصى به",
"refresh": "أنعِش", "refresh": "أنعِش",
"regeneration_indicator.label": "جارٍ التحميل…", "regeneration_indicator.label": "جارٍ التحميل…",
"regeneration_indicator.sublabel": "جارٍ تجهيز موجزات خيطك الرئيس!", "regeneration_indicator.sublabel": "جارٍ تجهيز موجزات خيطك الرئيس!",
@ -514,7 +549,9 @@
"relative_time.minutes": "{number}د", "relative_time.minutes": "{number}د",
"relative_time.seconds": "{number}ثا", "relative_time.seconds": "{number}ثا",
"relative_time.today": "اليوم", "relative_time.today": "اليوم",
"reply_indicator.attachments": "{count, plural, zero {}one {# مرفق} two {# المرفقات} few {# مرفقات} many {# مرفقات} other {# مرفقًا}}",
"reply_indicator.cancel": "إلغاء", "reply_indicator.cancel": "إلغاء",
"reply_indicator.poll": "استطلاع رأي",
"report.block": "حظر", "report.block": "حظر",
"report.block_explanation": "لن ترى منشوراته ولن يمكنه متابعتك أو رؤية منشوراتك، سيكون بديهيا له أنه مكتوم.", "report.block_explanation": "لن ترى منشوراته ولن يمكنه متابعتك أو رؤية منشوراتك، سيكون بديهيا له أنه مكتوم.",
"report.categories.legal": "إشعارات قانونية", "report.categories.legal": "إشعارات قانونية",
@ -570,6 +607,7 @@
"search.quick_action.status_search": "المنشورات المطابقة لـ {x}", "search.quick_action.status_search": "المنشورات المطابقة لـ {x}",
"search.search_or_paste": "ابحث أو أدخل رابطا تشعبيا URL", "search.search_or_paste": "ابحث أو أدخل رابطا تشعبيا URL",
"search_popout.full_text_search_disabled_message": "غير متوفر على {domain}.", "search_popout.full_text_search_disabled_message": "غير متوفر على {domain}.",
"search_popout.full_text_search_logged_out_message": "متاح فقط عند تسجيل الدخول.",
"search_popout.language_code": "رمز لغة ISO", "search_popout.language_code": "رمز لغة ISO",
"search_popout.options": "خيارات البحث", "search_popout.options": "خيارات البحث",
"search_popout.quick_actions": "الإجراءات السريعة", "search_popout.quick_actions": "الإجراءات السريعة",

View File

@ -199,6 +199,11 @@
"follow_request.authorize": "Autorizar", "follow_request.authorize": "Autorizar",
"follow_request.reject": "Refugar", "follow_request.reject": "Refugar",
"follow_requests.unlocked_explanation": "Magar que la to cuenta nun seya privada, el personal del dominiu «{domain}» pensó qu'a lo meyor quies revisar manualmente les solicitúes de siguimientu d'estes cuentes.", "follow_requests.unlocked_explanation": "Magar que la to cuenta nun seya privada, el personal del dominiu «{domain}» pensó qu'a lo meyor quies revisar manualmente les solicitúes de siguimientu d'estes cuentes.",
"follow_suggestions.dismiss": "Nun volver amosar",
"follow_suggestions.personalized_suggestion": "Suxerencia personalizada",
"follow_suggestions.popular_suggestion": "Suxerencia popular",
"follow_suggestions.view_all": "Ver too",
"follow_suggestions.who_to_follow": "A quién siguir",
"footer.about": "Tocante a", "footer.about": "Tocante a",
"footer.directory": "Direutoriu de perfiles", "footer.directory": "Direutoriu de perfiles",
"footer.get_app": "Consiguir l'aplicación", "footer.get_app": "Consiguir l'aplicación",

View File

@ -146,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "закрыты", "compose_form.lock_disclaimer.lock": "закрыты",
"compose_form.placeholder": "Што здарылася?", "compose_form.placeholder": "Што здарылася?",
"compose_form.poll.duration": "Працягласць апытання", "compose_form.poll.duration": "Працягласць апытання",
"compose_form.poll.multiple": "Множны выбар",
"compose_form.poll.option_placeholder": "Варыянт {number}",
"compose_form.poll.single": "Адзін варыянт",
"compose_form.poll.switch_to_multiple": "Змяніце апытанне, каб дазволіць некалькі варыянтаў адказу", "compose_form.poll.switch_to_multiple": "Змяніце апытанне, каб дазволіць некалькі варыянтаў адказу",
"compose_form.poll.switch_to_single": "Змяніце апытанне, каб дазволіць адзіны варыянт адказу", "compose_form.poll.switch_to_single": "Змяніце апытанне, каб дазволіць адзіны варыянт адказу",
"compose_form.publish_form": "Апублікаваць", "compose_form.poll.type": "Стыль",
"compose_form.publish": "Даслаць",
"compose_form.publish_form": "Новы допіс",
"compose_form.reply": "Адказаць",
"compose_form.save_changes": "Абнавіць",
"compose_form.spoiler.marked": "Выдаліць папярэджанне аб змесціве", "compose_form.spoiler.marked": "Выдаліць папярэджанне аб змесціве",
"compose_form.spoiler.unmarked": "Дадаць папярэджанне аб змесціве", "compose_form.spoiler.unmarked": "Дадаць папярэджанне аб змесціве",
"compose_form.spoiler_placeholder": "Папярэджанне аб змесціве (неабавязкова)",
"confirmation_modal.cancel": "Скасаваць", "confirmation_modal.cancel": "Скасаваць",
"confirmations.block.block_and_report": "Заблакіраваць і паскардзіцца", "confirmations.block.block_and_report": "Заблакіраваць і паскардзіцца",
"confirmations.block.confirm": "Заблакіраваць", "confirmations.block.confirm": "Заблакіраваць",
@ -269,6 +277,17 @@
"follow_request.authorize": "Аўтарызацыя", "follow_request.authorize": "Аўтарызацыя",
"follow_request.reject": "Адхіліць", "follow_request.reject": "Адхіліць",
"follow_requests.unlocked_explanation": "Ваш акаўнт не схаваны, аднак прадстаўнікі {domain} палічылі, што вы можаце захацець праглядзець запыты на падпіску з гэтых профіляў уручную.", "follow_requests.unlocked_explanation": "Ваш акаўнт не схаваны, аднак прадстаўнікі {domain} палічылі, што вы можаце захацець праглядзець запыты на падпіску з гэтых профіляў уручную.",
"follow_suggestions.curated_suggestion": "Выбар адміністрацыі",
"follow_suggestions.dismiss": "Не паказваць зноў",
"follow_suggestions.hints.featured": "Гэты профіль быў выбраны ўручную камандай {domain}.",
"follow_suggestions.hints.friends_of_friends": "Гэты профіль папулярны сярод людзей, на якіх вы падпісаліся.",
"follow_suggestions.hints.most_followed": "Гэты профіль - адзін з профіляў з самай вялікай колькасцю падпісак на {domain}.",
"follow_suggestions.hints.most_interactions": "У апошні час гэты профіль прыцягвае шмат увагі на {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Гэты профіль падобны на профілі, на якія вы нядаўна падпісаліся.",
"follow_suggestions.personalized_suggestion": "Персаналізаваная прапанова",
"follow_suggestions.popular_suggestion": "Папулярная прапанова",
"follow_suggestions.view_all": "Праглядзець усё",
"follow_suggestions.who_to_follow": "На каго падпісацца",
"followed_tags": "Падпіскі", "followed_tags": "Падпіскі",
"footer.about": "Пра нас", "footer.about": "Пра нас",
"footer.directory": "Дырэкторыя профіляў", "footer.directory": "Дырэкторыя профіляў",
@ -295,13 +314,9 @@
"hashtag.follow": "Падпісацца на хэштэг", "hashtag.follow": "Падпісацца на хэштэг",
"hashtag.unfollow": "Адпісацца ад хэштэга", "hashtag.unfollow": "Адпісацца ад хэштэга",
"hashtags.and_other": "…і яшчэ {count, plural, other {#}}", "hashtags.and_other": "…і яшчэ {count, plural, other {#}}",
"home.actions.go_to_explore": "Паглядзіце, што ў трэндзе",
"home.actions.go_to_suggestions": "Знайсці людзей, каб падпісацца",
"home.column_settings.basic": "Асноўныя", "home.column_settings.basic": "Асноўныя",
"home.column_settings.show_reblogs": "Паказаць пашырэнні", "home.column_settings.show_reblogs": "Паказаць пашырэнні",
"home.column_settings.show_replies": "Паказваць адказы", "home.column_settings.show_replies": "Паказваць адказы",
"home.explore_prompt.body": "Ваша галоўная стужка змяшчае сумесь допісаў з хэштэгамі, за якімі вы вырашылі сачыць, допісаў ад людзей, за якімі вы вырашылі сачыць, і допісаў, якія яны пашыраюць. Зараз усё выглядае даволі ціха, так што як наконт:",
"home.explore_prompt.title": "Гэта ваша апорная кропка ў Mastodon.",
"home.hide_announcements": "Схаваць аб'явы", "home.hide_announcements": "Схаваць аб'явы",
"home.pending_critical_update.body": "Калі ласка, абнавіце свой сервер Mastodon як мага хутчэй!", "home.pending_critical_update.body": "Калі ласка, абнавіце свой сервер Mastodon як мага хутчэй!",
"home.pending_critical_update.link": "Прагледзець абнаўленні", "home.pending_critical_update.link": "Прагледзець абнаўленні",
@ -514,7 +529,15 @@
"poll_button.add_poll": "Дадаць апытанне", "poll_button.add_poll": "Дадаць апытанне",
"poll_button.remove_poll": "Выдаліць апытанне", "poll_button.remove_poll": "Выдаліць апытанне",
"privacy.change": "Змяніць прыватнасць допісу", "privacy.change": "Змяніць прыватнасць допісу",
"privacy.direct.long": "Усе згаданыя ў допісе",
"privacy.direct.short": "Канкрэтныя людзі",
"privacy.private.long": "Толькі вашыя падпісчыкі",
"privacy.private.short": "Падпісчыкі",
"privacy.public.long": "Усе, хто ёсць і каго няма ў Mastodon",
"privacy.public.short": "Публічны", "privacy.public.short": "Публічны",
"privacy.unlisted.additional": "Паводзіць сябе гэтак жа, як і публічны, за выключэннем таго, што пост не будзе адлюстроўвацца ў жывой стужцы, хэштэгах, аглядзе або ў пошуку Mastodon, нават калі вы ўключылі бачнасць у пошуку ў наладах.",
"privacy.unlisted.long": "Менш фанфар ад алгарытмаў",
"privacy.unlisted.short": "Ціхі публічны",
"privacy_policy.last_updated": "Адноўлена {date}", "privacy_policy.last_updated": "Адноўлена {date}",
"privacy_policy.title": "Палітыка канфідэнцыйнасці", "privacy_policy.title": "Палітыка канфідэнцыйнасці",
"recommended": "Рэкамендуем", "recommended": "Рэкамендуем",
@ -532,7 +555,9 @@
"relative_time.minutes": "{number} хв", "relative_time.minutes": "{number} хв",
"relative_time.seconds": "{number} с", "relative_time.seconds": "{number} с",
"relative_time.today": "сёння", "relative_time.today": "сёння",
"reply_indicator.attachments": "{count, plural, one {# далучэнне} few {# далучэнні} many {# далучэнняў} other {# далучэння}}",
"reply_indicator.cancel": "Скасаваць", "reply_indicator.cancel": "Скасаваць",
"reply_indicator.poll": "Апытанне",
"report.block": "Заблакіраваць", "report.block": "Заблакіраваць",
"report.block_explanation": "Вы перастанеце бачыць допісы гэтага карыстальніка. Ён не зможа сачыць за вамі і бачыць вашы допісы. Ён зможа зразумець, што яго заблакіравалі.", "report.block_explanation": "Вы перастанеце бачыць допісы гэтага карыстальніка. Ён не зможа сачыць за вамі і бачыць вашы допісы. Ён зможа зразумець, што яго заблакіравалі.",
"report.categories.legal": "Права", "report.categories.legal": "Права",
@ -664,7 +689,7 @@
"status.show_more": "Паказаць болей", "status.show_more": "Паказаць болей",
"status.show_more_all": "Разгарнуць усё", "status.show_more_all": "Разгарнуць усё",
"status.show_original": "Паказаць арыгінал", "status.show_original": "Паказаць арыгінал",
"status.title.with_attachments": "{user} апублікаваў {attachmentCount, plural, one {укладанне} other {{attachmentCount} укладанні}}", "status.title.with_attachments": "{user} апублікаваў {attachmentCount, plural, one {далучэнне} few {{attachmentCount} далучэнні} many {{attachmentCount} далучэнняў} other {{attachmentCount} далучэння}}",
"status.translate": "Перакласці", "status.translate": "Перакласці",
"status.translated_from_with": "Перакладзена з {lang} з дапамогай {provider}", "status.translated_from_with": "Перакладзена з {lang} з дапамогай {provider}",
"status.uncached_media_warning": "Перадпрагляд недаступны", "status.uncached_media_warning": "Перадпрагляд недаступны",

View File

@ -3,12 +3,12 @@
"about.contact": "За контакти:", "about.contact": "За контакти:",
"about.disclaimer": "Mastodon е безплатен софтуер с отворен изходен код и търговска марка на Mastodon gGmbH.", "about.disclaimer": "Mastodon е безплатен софтуер с отворен изходен код и търговска марка на Mastodon gGmbH.",
"about.domain_blocks.no_reason_available": "Няма налична причина", "about.domain_blocks.no_reason_available": "Няма налична причина",
"about.domain_blocks.preamble": "Mastodon обикновено позволява да разглеждате съдържание и да взаимодействате с други потребители от всякакви сървъри във Федивърс. Има изключения, направени конкретно за този сървър.", "about.domain_blocks.preamble": "Mastodon обикновено позволява да разглеждате съдържание и да взаимодействате с други потребители от всякакви сървъри във Федивселената. Има изключения, направени конкретно за този сървър.",
"about.domain_blocks.silenced.explanation": "Обикновено няма да виждате профили и съдържание, освен ако изрично не го потърсите или се включете в него, следвайки го.", "about.domain_blocks.silenced.explanation": "Обикновено няма да виждате профили и съдържание, освен ако изрично не го потърсите или се включете в него, следвайки го.",
"about.domain_blocks.silenced.title": "Ограничено", "about.domain_blocks.silenced.title": "Ограничено",
"about.domain_blocks.suspended.explanation": "Никакви данни от този сървър няма да се обработват, съхраняват или обменят, правещи невъзможно всяко взаимодействие или комуникация с потребители от тези сървъри.", "about.domain_blocks.suspended.explanation": "Никакви данни от този сървър няма да се обработват, съхраняват или обменят, правещи невъзможно всяко взаимодействие или комуникация с потребители от тези сървъри.",
"about.domain_blocks.suspended.title": "Спряно", "about.domain_blocks.suspended.title": "Спряно",
"about.not_available": "Тази информация не е била направена налична на този сървър.", "about.not_available": "Тази информация не е публична на този сървър.",
"about.powered_by": "Децентрализирана социална мрежа, захранвана от {mastodon}", "about.powered_by": "Децентрализирана социална мрежа, захранвана от {mastodon}",
"about.rules": "Правила на сървъра", "about.rules": "Правила на сървъра",
"account.account_note_header": "Бележка", "account.account_note_header": "Бележка",
@ -110,7 +110,7 @@
"column.about": "Относно", "column.about": "Относно",
"column.blocks": "Блокирани потребители", "column.blocks": "Блокирани потребители",
"column.bookmarks": "Отметки", "column.bookmarks": "Отметки",
"column.community": "Локална часова ос", "column.community": "Локален инфопоток",
"column.direct": "Частни споменавания", "column.direct": "Частни споменавания",
"column.directory": "Разглеждане на профили", "column.directory": "Разглеждане на профили",
"column.domain_blocks": "Блокирани домейни", "column.domain_blocks": "Блокирани домейни",
@ -145,11 +145,9 @@
"compose_form.lock_disclaimer": "Вашият акаунт не е в положение {locked}. Всеки може да ви последва, за да разглежда публикациите ви само за последователи.", "compose_form.lock_disclaimer": "Вашият акаунт не е в положение {locked}. Всеки може да ви последва, за да разглежда публикациите ви само за последователи.",
"compose_form.lock_disclaimer.lock": "заключено", "compose_form.lock_disclaimer.lock": "заключено",
"compose_form.placeholder": "Какво мислите?", "compose_form.placeholder": "Какво мислите?",
"compose_form.poll.add_option": "Добавяне на избор",
"compose_form.poll.duration": "Времетраене на анкетата", "compose_form.poll.duration": "Времетраене на анкетата",
"compose_form.poll.multiple": "Множествен избор", "compose_form.poll.multiple": "Множествен избор",
"compose_form.poll.option_placeholder": "Избор {number}", "compose_form.poll.option_placeholder": "Избор {number}",
"compose_form.poll.remove_option": "Премахване на тази възможност",
"compose_form.poll.single": "Подберете нещо", "compose_form.poll.single": "Подберете нещо",
"compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора", "compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора",
"compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор", "compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор",
@ -203,7 +201,7 @@
"disabled_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен.", "disabled_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен.",
"dismissable_banner.community_timeline": "Ето най-скорошните публични публикации от хора, чиито акаунти са разположени в {domain}.", "dismissable_banner.community_timeline": "Ето най-скорошните публични публикации от хора, чиито акаунти са разположени в {domain}.",
"dismissable_banner.dismiss": "Отхвърляне", "dismissable_banner.dismiss": "Отхвърляне",
"dismissable_banner.explore_links": "Тези новини се разказват от хората в този и други сървъри на децентрализираната мрежа точно сега.", "dismissable_banner.explore_links": "Това са най-споделяните новини в социалната мрежа днес. По-нови истории, споделени от повече хора се показват по-напред.",
"dismissable_banner.explore_statuses": "Има публикации през социалната мрежа, които днес набират популярност. По-новите публикации с повече подсилвания и любими са класирани по-високо.", "dismissable_banner.explore_statuses": "Има публикации през социалната мрежа, които днес набират популярност. По-новите публикации с повече подсилвания и любими са класирани по-високо.",
"dismissable_banner.explore_tags": "Тези хаштагове сега набират популярност сред хората в този и други сървъри на децентрализирата мрежа.", "dismissable_banner.explore_tags": "Тези хаштагове сега набират популярност сред хората в този и други сървъри на децентрализирата мрежа.",
"dismissable_banner.public_timeline": "Ето най-новите обществени публикации от хора в социална мрежа, която хората в {domain} следват.", "dismissable_banner.public_timeline": "Ето най-новите обществени публикации от хора в социална мрежа, която хората в {domain} следват.",
@ -224,16 +222,16 @@
"emoji_button.search_results": "Резултати от търсене", "emoji_button.search_results": "Резултати от търсене",
"emoji_button.symbols": "Символи", "emoji_button.symbols": "Символи",
"emoji_button.travel": "Пътуване и места", "emoji_button.travel": "Пътуване и места",
"empty_column.account_hides_collections": "Този потребител е избрал да не прави това сведение достъпно", "empty_column.account_hides_collections": "Този потребител е избрал да не дава тази информация",
"empty_column.account_suspended": "Спрян акаунт", "empty_column.account_suspended": "Спрян акаунт",
"empty_column.account_timeline": "Тук няма публикации!", "empty_column.account_timeline": "Тук няма публикации!",
"empty_column.account_unavailable": "Профилът не е наличен", "empty_column.account_unavailable": "Профилът не е наличен",
"empty_column.blocks": "Още не сте блокирали никакви потребители.", "empty_column.blocks": "Още не сте блокирали никакви потребители.",
"empty_column.bookmarked_statuses": "Още не сте отметнали публикации. Отметвайки някоя, то тя ще се покаже тук.", "empty_column.bookmarked_statuses": "Още не сте отметнали публикации. Отметвайки някоя, то тя ще се покаже тук.",
"empty_column.community": "Местната часова ос е празна. Напишете нещо обществено, за да завъртите нещата!", "empty_column.community": "Локалният инфопоток е празен. Публикувайте нещо, за да започнете!",
"empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.", "empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.",
"empty_column.domain_blocks": "Още няма блокирани домейни.", "empty_column.domain_blocks": "Още няма блокирани домейни.",
"empty_column.explore_statuses": "Няма нищо налагащо се в момента. Проверете пак по-късно!", "empty_column.explore_statuses": "Няма тенденции в момента. Проверете пак по-късно!",
"empty_column.favourited_statuses": "Още нямате никакви любими публикации. Правейки любима, то тя ще се покаже тук.", "empty_column.favourited_statuses": "Още нямате никакви любими публикации. Правейки любима, то тя ще се покаже тук.",
"empty_column.favourites": "Още никого не е слагал публикацията в любими. Когато някой го направи, този човек ще се покаже тук.", "empty_column.favourites": "Още никого не е слагал публикацията в любими. Когато някой го направи, този човек ще се покаже тук.",
"empty_column.follow_requests": "Още нямате заявки за последване. Получавайки такава, то тя ще се покаже тук.", "empty_column.follow_requests": "Още нямате заявки за последване. Получавайки такава, то тя ще се покаже тук.",
@ -279,6 +277,17 @@
"follow_request.authorize": "Упълномощаване", "follow_request.authorize": "Упълномощаване",
"follow_request.reject": "Отхвърляне", "follow_request.reject": "Отхвърляне",
"follow_requests.unlocked_explanation": "Въпреки че акаунтът ви не е заключен, служителите на {domain} помислиха, че може да искате да преглеждате ръчно заявките за последване на тези профили.", "follow_requests.unlocked_explanation": "Въпреки че акаунтът ви не е заключен, служителите на {domain} помислиха, че може да искате да преглеждате ръчно заявките за последване на тези профили.",
"follow_suggestions.curated_suggestion": "Избор на персонал",
"follow_suggestions.dismiss": "Без ново показване",
"follow_suggestions.hints.featured": "Този профил е ръчно подбран от отбора на {domain}.",
"follow_suggestions.hints.friends_of_friends": "Този профил е популярен измежду хората, които следвате.",
"follow_suggestions.hints.most_followed": "Този профил е един от най-следваните при {domain}.",
"follow_suggestions.hints.most_interactions": "Този профил наскоро получи много внимание при {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Този профил е подобен на профилите, които сте последвали наскоро.",
"follow_suggestions.personalized_suggestion": "Персонализирано предложение",
"follow_suggestions.popular_suggestion": "Популярно предложение",
"follow_suggestions.view_all": "Преглед на всички",
"follow_suggestions.who_to_follow": "Кого да се следва",
"followed_tags": "Последвани хаштагове", "followed_tags": "Последвани хаштагове",
"footer.about": "Относно", "footer.about": "Относно",
"footer.directory": "Директория на профилите", "footer.directory": "Директория на профилите",
@ -305,13 +314,9 @@
"hashtag.follow": "Следване на хаштаг", "hashtag.follow": "Следване на хаштаг",
"hashtag.unfollow": "Спиране на следване на хаштаг", "hashtag.unfollow": "Спиране на следване на хаштаг",
"hashtags.and_other": "…и {count, plural, other {# още}}", "hashtags.and_other": "…и {count, plural, other {# още}}",
"home.actions.go_to_explore": "Вижте какво изгрява",
"home.actions.go_to_suggestions": "Намиране на хора за следване",
"home.column_settings.basic": "Основно", "home.column_settings.basic": "Основно",
"home.column_settings.show_reblogs": "Показване на подсилванията", "home.column_settings.show_reblogs": "Показване на подсилванията",
"home.column_settings.show_replies": "Показване на отговорите", "home.column_settings.show_replies": "Показване на отговорите",
"home.explore_prompt.body": "Вашият начален инфоканал ще е смес на публикации от хаштаговете, които сте избрали да следвате, избраните хора да следвате, а и публикациите, които са подсилили. Ако изглежда твърде тихо в момента, то може да искате да:",
"home.explore_prompt.title": "Това е началната ви база с Mastodon.",
"home.hide_announcements": "Скриване на оповестяванията", "home.hide_announcements": "Скриване на оповестяванията",
"home.pending_critical_update.body": "Обновете сървъра си в Mastodon възможно най-скоро!", "home.pending_critical_update.body": "Обновете сървъра си в Mastodon възможно най-скоро!",
"home.pending_critical_update.link": "Преглед на обновяванията", "home.pending_critical_update.link": "Преглед на обновяванията",
@ -348,10 +353,10 @@
"keyboard_shortcuts.favourites": "Отваряне на списъка с любими", "keyboard_shortcuts.favourites": "Отваряне на списъка с любими",
"keyboard_shortcuts.federated": "Отваряне на федерирания инфопоток", "keyboard_shortcuts.federated": "Отваряне на федерирания инфопоток",
"keyboard_shortcuts.heading": "Клавишни съчетания", "keyboard_shortcuts.heading": "Клавишни съчетания",
"keyboard_shortcuts.home": "Отваряне на началната часова ос", "keyboard_shortcuts.home": "Отваряне на личния инфопоток",
"keyboard_shortcuts.hotkey": "Бърз клавиш", "keyboard_shortcuts.hotkey": "Бърз клавиш",
"keyboard_shortcuts.legend": "Показване на тази легенда", "keyboard_shortcuts.legend": "Показване на тази легенда",
"keyboard_shortcuts.local": "Отваряне на местна часова ос", "keyboard_shortcuts.local": "Отваряне на локалния инфопоток",
"keyboard_shortcuts.mention": "Споменаване на автора", "keyboard_shortcuts.mention": "Споменаване на автора",
"keyboard_shortcuts.muted": "Отваряне на списъка със заглушени потребители", "keyboard_shortcuts.muted": "Отваряне на списъка със заглушени потребители",
"keyboard_shortcuts.my_profile": "Отваряне на профила ви", "keyboard_shortcuts.my_profile": "Отваряне на профила ви",
@ -402,12 +407,12 @@
"navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс", "navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс",
"navigation_bar.blocks": "Блокирани потребители", "navigation_bar.blocks": "Блокирани потребители",
"navigation_bar.bookmarks": "Отметки", "navigation_bar.bookmarks": "Отметки",
"navigation_bar.community_timeline": "Локална часова ос", "navigation_bar.community_timeline": "Локален инфопоток",
"navigation_bar.compose": "Съставяне на нова публикация", "navigation_bar.compose": "Съставяне на нова публикация",
"navigation_bar.direct": "Частни споменавания", "navigation_bar.direct": "Частни споменавания",
"navigation_bar.discover": "Откриване", "navigation_bar.discover": "Откриване",
"navigation_bar.domain_blocks": "Блокирани домейни", "navigation_bar.domain_blocks": "Блокирани домейни",
"navigation_bar.explore": "Изследване", "navigation_bar.explore": "Разглеждане",
"navigation_bar.favourites": "Любими", "navigation_bar.favourites": "Любими",
"navigation_bar.filters": "Заглушени думи", "navigation_bar.filters": "Заглушени думи",
"navigation_bar.follow_requests": "Заявки за последване", "navigation_bar.follow_requests": "Заявки за последване",
@ -471,13 +476,13 @@
"notifications.permission_required": "Известията на работния плот ги няма, щото няма дадено нужното позволение.", "notifications.permission_required": "Известията на работния плот ги няма, щото няма дадено нужното позволение.",
"notifications_permission_banner.enable": "Включване на известията на работния плот", "notifications_permission_banner.enable": "Включване на известията на работния плот",
"notifications_permission_banner.how_to_control": "За да получавате известия, когато Mastodon не е отворен, включете известията на работния плот. Може да управлявате точно кои видове взаимодействия пораждат известия на работния плот чрез бутона {icon} по-горе, след като бъдат включени.", "notifications_permission_banner.how_to_control": "За да получавате известия, когато Mastodon не е отворен, включете известията на работния плот. Може да управлявате точно кои видове взаимодействия пораждат известия на работния плот чрез бутона {icon} по-горе, след като бъдат включени.",
"notifications_permission_banner.title": "Никога не пропускате нещо", "notifications_permission_banner.title": "Никога не пропускайте нищо",
"onboarding.action.back": "Върнете ме обратно", "onboarding.action.back": "Върнете ме обратно",
"onboarding.actions.back": "Върнете ме обратно", "onboarding.actions.back": "Върнете ме обратно",
"onboarding.actions.go_to_explore": "Вижте какво изгрява", "onboarding.actions.go_to_explore": "Виж тенденции",
"onboarding.actions.go_to_home": "Към началния ви инфоканал", "onboarding.actions.go_to_home": "Към началния ви инфоканал",
"onboarding.compose.template": "Здравейте, #Mastodon!", "onboarding.compose.template": "Здравейте, #Mastodon!",
"onboarding.follows.empty": "За съжаление, в момента не могат да се показват резултати. Може да опитате да употребявате търсене или да прегледате страницата за изследване, за да намерите страница за последване, или да опитате пак по-късно.", "onboarding.follows.empty": "За съжаление, в момента не могат да бъдат показани резултати. Може да опитате да търсите или да разгледате, за да намерите кого да последвате, или опитайте отново по-късно.",
"onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!", "onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!",
"onboarding.follows.title": "Популярно в Mastodon", "onboarding.follows.title": "Популярно в Mastodon",
"onboarding.profile.discoverable": "Правене на моя профил откриваем", "onboarding.profile.discoverable": "Правене на моя профил откриваем",
@ -524,12 +529,13 @@
"poll_button.add_poll": "Анкетиране", "poll_button.add_poll": "Анкетиране",
"poll_button.remove_poll": "Премахване на анкета", "poll_button.remove_poll": "Премахване на анкета",
"privacy.change": "Промяна на поверителността на публикация", "privacy.change": "Промяна на поверителността на публикация",
"privacy.direct.long": "Всеки споменат в публикацията", "privacy.direct.long": "Споменатите в публикацията",
"privacy.direct.short": "Определени хора", "privacy.direct.short": "Определени хора",
"privacy.private.long": "Само последователите ви", "privacy.private.long": "Само последователите ви",
"privacy.private.short": "Последователи", "privacy.private.short": "Последователи",
"privacy.public.long": "Всеки във и извън Mastodon", "privacy.public.long": "Всеки във и извън Mastodon",
"privacy.public.short": "Публично", "privacy.public.short": "Публично",
"privacy.unlisted.additional": "Това действие е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, разглеждането или търсенето в Mastodon, дори ако сте избрали да се публично видими на ниво акаунт.",
"privacy.unlisted.long": "По-малко алгоритмични фанфари", "privacy.unlisted.long": "По-малко алгоритмични фанфари",
"privacy.unlisted.short": "Тиха публика", "privacy.unlisted.short": "Тиха публика",
"privacy_policy.last_updated": "Последно осъвременяване на {date}", "privacy_policy.last_updated": "Последно осъвременяване на {date}",

View File

@ -29,7 +29,7 @@
"account.enable_notifications": "Ma c'hemenn pa vez embannet traoù gant @{name}", "account.enable_notifications": "Ma c'hemenn pa vez embannet traoù gant @{name}",
"account.endorse": "Lakaat war-wel war ar profil", "account.endorse": "Lakaat war-wel war ar profil",
"account.featured_tags.last_status_at": "Toud diwezhañ : {date}", "account.featured_tags.last_status_at": "Toud diwezhañ : {date}",
"account.featured_tags.last_status_never": "Toud ebet", "account.featured_tags.last_status_never": "Embannadur ebet",
"account.featured_tags.title": "Hashtagoù pennañ {name}", "account.featured_tags.title": "Hashtagoù pennañ {name}",
"account.follow": "Heuliañ", "account.follow": "Heuliañ",
"account.follow_back": "Heuliañ d'ho tro", "account.follow_back": "Heuliañ d'ho tro",
@ -62,7 +62,7 @@
"account.requested_follow": "Gant {name} eo bet goulennet ho heuliañ", "account.requested_follow": "Gant {name} eo bet goulennet ho heuliañ",
"account.share": "Skignañ profil @{name}", "account.share": "Skignañ profil @{name}",
"account.show_reblogs": "Diskouez skignadennoù @{name}", "account.show_reblogs": "Diskouez skignadennoù @{name}",
"account.statuses_counter": "{count, plural, one {{counter} Toud} two {{counter} Doud} other {{counter} a Doudoù}}", "account.statuses_counter": "{count, plural, one {{counter} C'hannad} two {{counter} Gannad} other {{counter} a Gannadoù}}",
"account.unblock": "Diverzañ @{name}", "account.unblock": "Diverzañ @{name}",
"account.unblock_domain": "Diverzañ an domani {domain}", "account.unblock_domain": "Diverzañ an domani {domain}",
"account.unblock_short": "Distankañ", "account.unblock_short": "Distankañ",
@ -118,9 +118,9 @@
"column.lists": "Listennoù", "column.lists": "Listennoù",
"column.mutes": "Implijer·ion·ezed kuzhet", "column.mutes": "Implijer·ion·ezed kuzhet",
"column.notifications": "Kemennoù", "column.notifications": "Kemennoù",
"column.pins": "Toudoù spilhennet", "column.pins": "Embannadurioù spilhennet",
"column.public": "Red-amzer kevredet", "column.public": "Red-amzer kevredet",
"column_back_button.label": "Distro", "column_back_button.label": "Distreiñ",
"column_header.hide_settings": "Kuzhat an arventennoù", "column_header.hide_settings": "Kuzhat an arventennoù",
"column_header.moveLeft_settings": "Dilec'hiañ ar bannad a-gleiz", "column_header.moveLeft_settings": "Dilec'hiañ ar bannad a-gleiz",
"column_header.moveRight_settings": "Dilec'hiañ ar bannad a-zehou", "column_header.moveRight_settings": "Dilec'hiañ ar bannad a-zehou",
@ -143,9 +143,14 @@
"compose_form.lock_disclaimer.lock": "prennet", "compose_form.lock_disclaimer.lock": "prennet",
"compose_form.placeholder": "Petra emaoc'h o soñjal e-barzh ?", "compose_form.placeholder": "Petra emaoc'h o soñjal e-barzh ?",
"compose_form.poll.duration": "Pad ar sontadeg", "compose_form.poll.duration": "Pad ar sontadeg",
"compose_form.poll.single": "Dibabit unan",
"compose_form.poll.switch_to_multiple": "Kemmañ ar sontadeg evit aotren meur a zibab", "compose_form.poll.switch_to_multiple": "Kemmañ ar sontadeg evit aotren meur a zibab",
"compose_form.poll.switch_to_single": "Kemmañ ar sontadeg evit aotren un dibab hepken", "compose_form.poll.switch_to_single": "Kemmañ ar sontadeg evit aotren un dibab hepken",
"compose_form.poll.type": "Neuz",
"compose_form.publish": "Embann",
"compose_form.publish_form": "Embann", "compose_form.publish_form": "Embann",
"compose_form.reply": "Respont",
"compose_form.save_changes": "Hizivadur",
"compose_form.spoiler.marked": "Kuzhet eo an destenn a-dreñv ur c'hemenn", "compose_form.spoiler.marked": "Kuzhet eo an destenn a-dreñv ur c'hemenn",
"compose_form.spoiler.unmarked": "N'eo ket kuzhet an destenn", "compose_form.spoiler.unmarked": "N'eo ket kuzhet an destenn",
"confirmation_modal.cancel": "Nullañ", "confirmation_modal.cancel": "Nullañ",
@ -194,9 +199,9 @@
"embed.preview": "Setu penaos e teuio war wel :", "embed.preview": "Setu penaos e teuio war wel :",
"emoji_button.activity": "Obererezh", "emoji_button.activity": "Obererezh",
"emoji_button.clear": "Diverkañ", "emoji_button.clear": "Diverkañ",
"emoji_button.custom": "Kempennet", "emoji_button.custom": "Personelaet",
"emoji_button.flags": "Bannieloù", "emoji_button.flags": "Bannieloù",
"emoji_button.food": "Boued hag Evaj", "emoji_button.food": "Boued & Evajoù",
"emoji_button.label": "Enlakaat un emoji", "emoji_button.label": "Enlakaat un emoji",
"emoji_button.nature": "Natur", "emoji_button.nature": "Natur",
"emoji_button.not_found": "Emoji ebet !! (╯°□°)╯︵ ┻━┻", "emoji_button.not_found": "Emoji ebet !! (╯°□°)╯︵ ┻━┻",
@ -206,12 +211,12 @@
"emoji_button.search": "O klask...", "emoji_button.search": "O klask...",
"emoji_button.search_results": "Disoc'hoù an enklask", "emoji_button.search_results": "Disoc'hoù an enklask",
"emoji_button.symbols": "Arouezioù", "emoji_button.symbols": "Arouezioù",
"emoji_button.travel": "Lec'hioù ha Beajoù", "emoji_button.travel": "Beajiñ & Lec'hioù",
"empty_column.account_suspended": "Kont ehanet", "empty_column.account_suspended": "Kont ehanet",
"empty_column.account_timeline": "Toud ebet amañ !", "empty_column.account_timeline": "Toud ebet amañ !",
"empty_column.account_unavailable": "Profil dihegerz", "empty_column.account_unavailable": "Profil dihegerz",
"empty_column.blocks": "N'eus ket bet berzet implijer·ez ganeoc'h c'hoazh.", "empty_column.blocks": "N'eus ket bet berzet implijer·ez ganeoc'h c'hoazh.",
"empty_column.bookmarked_statuses": "N'ho peus toud ebet enrollet en ho sinedoù c'hoazh. Pa vo ouzhpennet unan e teuio war wel amañ.", "empty_column.bookmarked_statuses": "N'ho peus embannadur ebet enrollet en ho sinedoù c'hoazh. Pa vo ouzhpennet unan e teuio war wel amañ.",
"empty_column.community": "Goulo eo ar red-amzer lec'hel. Skrivit'ta un dra evit lakaat tan dezhi !", "empty_column.community": "Goulo eo ar red-amzer lec'hel. Skrivit'ta un dra evit lakaat tan dezhi !",
"empty_column.domain_blocks": "N'eus domani kuzh ebet c'hoazh.", "empty_column.domain_blocks": "N'eus domani kuzh ebet c'hoazh.",
"empty_column.explore_statuses": "N'eus tuadur ebet evit c'hoazh. Distroit diwezhatoc'h !", "empty_column.explore_statuses": "N'eus tuadur ebet evit c'hoazh. Distroit diwezhatoc'h !",
@ -255,6 +260,7 @@
"follow_request.authorize": "Aotren", "follow_request.authorize": "Aotren",
"follow_request.reject": "Nac'hañ", "follow_request.reject": "Nac'hañ",
"follow_requests.unlocked_explanation": "Daoust ma n'eo ket ho kont prennet, skipailh {domain} a soñj e fellfe deoc'h gwiriekaat pedadennoù heuliañ deus ar c'hontoù-se diwar-zorn.", "follow_requests.unlocked_explanation": "Daoust ma n'eo ket ho kont prennet, skipailh {domain} a soñj e fellfe deoc'h gwiriekaat pedadennoù heuliañ deus ar c'hontoù-se diwar-zorn.",
"follow_suggestions.view_all": "Gwelet pep tra",
"followed_tags": "Hashtagoù o heuliañ", "followed_tags": "Hashtagoù o heuliañ",
"footer.about": "Diwar-benn", "footer.about": "Diwar-benn",
"footer.directory": "Kavlec'h ar profiloù", "footer.directory": "Kavlec'h ar profiloù",
@ -262,7 +268,7 @@
"footer.invite": "Pediñ tud", "footer.invite": "Pediñ tud",
"footer.keyboard_shortcuts": "Berradennoù klavier", "footer.keyboard_shortcuts": "Berradennoù klavier",
"footer.privacy_policy": "Reolennoù prevezded", "footer.privacy_policy": "Reolennoù prevezded",
"footer.source_code": "Gwelet kod mammenn", "footer.source_code": "Gwelet ar c'hod mammenn",
"footer.status": "Statud", "footer.status": "Statud",
"generic.saved": "Enrollet", "generic.saved": "Enrollet",
"getting_started.heading": "Loc'hañ", "getting_started.heading": "Loc'hañ",
@ -280,12 +286,9 @@
"hashtag.follow": "Heuliañ ar ger-klik", "hashtag.follow": "Heuliañ ar ger-klik",
"hashtag.unfollow": "Paouez heuliañ an hashtag", "hashtag.unfollow": "Paouez heuliañ an hashtag",
"hashtags.and_other": "…{count, plural, one {hag # all} other {ha # all}}", "hashtags.and_other": "…{count, plural, one {hag # all} other {ha # all}}",
"home.actions.go_to_explore": "Gwelet petra zo diouzh ar c'hiz",
"home.actions.go_to_suggestions": "Kavout tud da heuliañ",
"home.column_settings.basic": "Diazez", "home.column_settings.basic": "Diazez",
"home.column_settings.show_reblogs": "Diskouez ar skignadennoù", "home.column_settings.show_reblogs": "Diskouez ar skignadennoù",
"home.column_settings.show_replies": "Diskouez ar respontoù", "home.column_settings.show_replies": "Diskouez ar respontoù",
"home.explore_prompt.title": "Homañ eo ho pajenn degemer e-barzh Mastodon.",
"home.hide_announcements": "Kuzhat ar c'hemennoù", "home.hide_announcements": "Kuzhat ar c'hemennoù",
"home.pending_critical_update.body": "Hizivait ho servijer Mastodon kerkent ha ma c'hallit mar plij!", "home.pending_critical_update.body": "Hizivait ho servijer Mastodon kerkent ha ma c'hallit mar plij!",
"home.pending_critical_update.link": "Gwelet an hizivadennoù", "home.pending_critical_update.link": "Gwelet an hizivadennoù",
@ -293,7 +296,7 @@
"interaction_modal.description.follow": "Gant ur gont Mastodon e c'hellit heuliañ {name} evit resev an toudoù a embann war ho red degemer.", "interaction_modal.description.follow": "Gant ur gont Mastodon e c'hellit heuliañ {name} evit resev an toudoù a embann war ho red degemer.",
"interaction_modal.description.reblog": "Gant ur gont Mastodon e c'hellit skignañ an toud-mañ evit rannañ anezhañ gant ho heulierien·ezed.", "interaction_modal.description.reblog": "Gant ur gont Mastodon e c'hellit skignañ an toud-mañ evit rannañ anezhañ gant ho heulierien·ezed.",
"interaction_modal.description.reply": "Gant ur gont Mastodon e c'hellit respont d'an toud-mañ.", "interaction_modal.description.reply": "Gant ur gont Mastodon e c'hellit respont d'an toud-mañ.",
"interaction_modal.no_account_yet": "N'eo ket war vMastodon?", "interaction_modal.no_account_yet": "N'emañ ket war vMastodon?",
"interaction_modal.on_another_server": "War ur servijer all", "interaction_modal.on_another_server": "War ur servijer all",
"interaction_modal.on_this_server": "War ar servijer-mañ", "interaction_modal.on_this_server": "War ar servijer-mañ",
"interaction_modal.title.favourite": "Ouzhpennañ embannadur {name} d'ar re vuiañ-karet", "interaction_modal.title.favourite": "Ouzhpennañ embannadur {name} d'ar re vuiañ-karet",
@ -461,7 +464,7 @@
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.setup_profile.title": "Customize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
"onboarding.steps.share_profile.title": "Share your profile", "onboarding.steps.share_profile.title": "Rannit ho kont Mastodon",
"password_confirmation.mismatching": "Disheñvel eo an daou c'her-termen-se", "password_confirmation.mismatching": "Disheñvel eo an daou c'her-termen-se",
"picture_in_picture.restore": "Adlakaat", "picture_in_picture.restore": "Adlakaat",
"poll.closed": "Serret", "poll.closed": "Serret",
@ -474,7 +477,9 @@
"poll.votes": "{votes, plural,one {#votadenn} other {# votadenn}}", "poll.votes": "{votes, plural,one {#votadenn} other {# votadenn}}",
"poll_button.add_poll": "Ouzhpennañ ur sontadeg", "poll_button.add_poll": "Ouzhpennañ ur sontadeg",
"poll_button.remove_poll": "Dilemel ar sontadeg", "poll_button.remove_poll": "Dilemel ar sontadeg",
"privacy.change": "Cheñch prevezded an toud", "privacy.change": "Cheñch prevezded an embannadur",
"privacy.direct.short": "Tud resis",
"privacy.private.short": "Heulierien",
"privacy.public.short": "Publik", "privacy.public.short": "Publik",
"privacy_policy.last_updated": "Hizivadenn ziwezhañ {date}", "privacy_policy.last_updated": "Hizivadenn ziwezhañ {date}",
"privacy_policy.title": "Reolennoù Prevezded", "privacy_policy.title": "Reolennoù Prevezded",
@ -494,6 +499,7 @@
"relative_time.seconds": "{number}eil", "relative_time.seconds": "{number}eil",
"relative_time.today": "hiziv", "relative_time.today": "hiziv",
"reply_indicator.cancel": "Nullañ", "reply_indicator.cancel": "Nullañ",
"reply_indicator.poll": "Sontadeg",
"report.block": "Stankañ", "report.block": "Stankañ",
"report.block_explanation": "Ne vo ket gwelet toudoù ar gont-se ken. Ne welo ket ho toudoù ha ne c'hello ket ho heuliañ ken. Gouzout a raio eo bet stanket ganeoc'h.", "report.block_explanation": "Ne vo ket gwelet toudoù ar gont-se ken. Ne welo ket ho toudoù ha ne c'hello ket ho heuliañ ken. Gouzout a raio eo bet stanket ganeoc'h.",
"report.categories.legal": "Lezennel", "report.categories.legal": "Lezennel",

View File

@ -145,18 +145,16 @@
"compose_form.lock_disclaimer": "El teu compte no està {locked}. Tothom pot seguir-te i veure els tuts de només per a seguidors.", "compose_form.lock_disclaimer": "El teu compte no està {locked}. Tothom pot seguir-te i veure els tuts de només per a seguidors.",
"compose_form.lock_disclaimer.lock": "blocat", "compose_form.lock_disclaimer.lock": "blocat",
"compose_form.placeholder": "Què tens al cap?", "compose_form.placeholder": "Què tens al cap?",
"compose_form.poll.add_option": "Afegiu una opció",
"compose_form.poll.duration": "Durada de l'enquesta", "compose_form.poll.duration": "Durada de l'enquesta",
"compose_form.poll.multiple": "Opcions múltiples", "compose_form.poll.multiple": "Opcions múltiples",
"compose_form.poll.option_placeholder": "Opció {number}", "compose_form.poll.option_placeholder": "Opció {number}",
"compose_form.poll.remove_option": "Treu aquesta opció",
"compose_form.poll.single": "Trieu-ne una", "compose_form.poll.single": "Trieu-ne una",
"compose_form.poll.switch_to_multiple": "Canvia lenquesta per a permetre múltiples opcions", "compose_form.poll.switch_to_multiple": "Canvia lenquesta per a permetre múltiples opcions",
"compose_form.poll.switch_to_single": "Canvia lenquesta per a permetre una única opció", "compose_form.poll.switch_to_single": "Canvia lenquesta per a permetre una única opció",
"compose_form.poll.type": "Estil", "compose_form.poll.type": "Estil",
"compose_form.publish": "Publica", "compose_form.publish": "Publica",
"compose_form.publish_form": "Nou tut", "compose_form.publish_form": "Nou tut",
"compose_form.reply": "Responeu", "compose_form.reply": "Respon",
"compose_form.save_changes": "Actualitza", "compose_form.save_changes": "Actualitza",
"compose_form.spoiler.marked": "Elimina l'avís de contingut", "compose_form.spoiler.marked": "Elimina l'avís de contingut",
"compose_form.spoiler.unmarked": "Afegeix avís de contingut", "compose_form.spoiler.unmarked": "Afegeix avís de contingut",
@ -279,6 +277,17 @@
"follow_request.authorize": "Autoritza", "follow_request.authorize": "Autoritza",
"follow_request.reject": "Rebutja", "follow_request.reject": "Rebutja",
"follow_requests.unlocked_explanation": "Tot i que el teu compte no està blocat, el personal de {domain} ha pensat que és possible que vulguis revisar manualment les sol·licituds de seguiment daquests comptes.", "follow_requests.unlocked_explanation": "Tot i que el teu compte no està blocat, el personal de {domain} ha pensat que és possible que vulguis revisar manualment les sol·licituds de seguiment daquests comptes.",
"follow_suggestions.curated_suggestion": "Tria de l'equip",
"follow_suggestions.dismiss": "No ho tornis a mostrar",
"follow_suggestions.hints.featured": "L'equip de {domain} ha seleccionat aquest perfil.",
"follow_suggestions.hints.friends_of_friends": "Aquest perfil és popular entre la gent que seguiu.",
"follow_suggestions.hints.most_followed": "Aquest perfil és un dels més seguits a {domain}.",
"follow_suggestions.hints.most_interactions": "Aquest perfil ha estat rebent un munt d'atenció recentment a {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Aquest perfil és similar a d'altres que heu seguit recentment.",
"follow_suggestions.personalized_suggestion": "Suggeriment personalitzat",
"follow_suggestions.popular_suggestion": "Suggeriment popular",
"follow_suggestions.view_all": "Mostra-ho tot",
"follow_suggestions.who_to_follow": "A qui seguir",
"followed_tags": "Etiquetes seguides", "followed_tags": "Etiquetes seguides",
"footer.about": "Quant a", "footer.about": "Quant a",
"footer.directory": "Directori de perfils", "footer.directory": "Directori de perfils",
@ -305,13 +314,9 @@
"hashtag.follow": "Segueix l'etiqueta", "hashtag.follow": "Segueix l'etiqueta",
"hashtag.unfollow": "Deixa de seguir l'etiqueta", "hashtag.unfollow": "Deixa de seguir l'etiqueta",
"hashtags.and_other": "…i {count, plural, other {# més}}", "hashtags.and_other": "…i {count, plural, other {# més}}",
"home.actions.go_to_explore": "Mira què és tendència",
"home.actions.go_to_suggestions": "Troba persones a seguir",
"home.column_settings.basic": "Bàsic", "home.column_settings.basic": "Bàsic",
"home.column_settings.show_reblogs": "Mostra els impulsos", "home.column_settings.show_reblogs": "Mostra els impulsos",
"home.column_settings.show_replies": "Mostra les respostes", "home.column_settings.show_replies": "Mostra les respostes",
"home.explore_prompt.body": "La teva línia de temps Inici tindrà una barreja dels tuts de les etiquetes que has triat seguir, de les persones que has triat seguir i dels tuts que s'impulsen. Ara mateix es veu força tranquil·la, què et sembla si:",
"home.explore_prompt.title": "Aquesta és la teva base inicial a Mastodon.",
"home.hide_announcements": "Amaga els anuncis", "home.hide_announcements": "Amaga els anuncis",
"home.pending_critical_update.body": "Si us plau actualitza el teu servidor Mastodon tant aviat com sigui possible!", "home.pending_critical_update.body": "Si us plau actualitza el teu servidor Mastodon tant aviat com sigui possible!",
"home.pending_critical_update.link": "Veure actualitzacions", "home.pending_critical_update.link": "Veure actualitzacions",
@ -524,12 +529,15 @@
"poll_button.add_poll": "Afegeix una enquesta", "poll_button.add_poll": "Afegeix una enquesta",
"poll_button.remove_poll": "Elimina l'enquesta", "poll_button.remove_poll": "Elimina l'enquesta",
"privacy.change": "Canvia la privacitat del tut", "privacy.change": "Canvia la privacitat del tut",
"privacy.direct.long": "Tothom mencionat en aquesta publicació", "privacy.direct.long": "Tothom mencionat a la publicació",
"privacy.direct.short": "Persones concretes", "privacy.direct.short": "Persones concretes",
"privacy.private.long": "Només els vostres seguidors", "privacy.private.long": "Només els vostres seguidors",
"privacy.private.short": "Seguidors", "privacy.private.short": "Seguidors",
"privacy.public.long": "Tothom dins o fora Mastodon", "privacy.public.long": "Tothom dins o fora Mastodon",
"privacy.public.short": "Públic", "privacy.public.short": "Públic",
"privacy.unlisted.additional": "Es comporta igual que públic, excepte que la publicació no apareixerà als canals en directe o etiquetes, l'explora o a la cerca de Mastodon, fins i tot si ho heu activat a nivell de compte.",
"privacy.unlisted.long": "Menys fanfàrries algorísmiques",
"privacy.unlisted.short": "Públic silenciós",
"privacy_policy.last_updated": "Darrera actualització {date}", "privacy_policy.last_updated": "Darrera actualització {date}",
"privacy_policy.title": "Política de Privacitat", "privacy_policy.title": "Política de Privacitat",
"recommended": "Recomanat", "recommended": "Recomanat",
@ -547,7 +555,9 @@
"relative_time.minutes": "{number}min", "relative_time.minutes": "{number}min",
"relative_time.seconds": "{number}s", "relative_time.seconds": "{number}s",
"relative_time.today": "avui", "relative_time.today": "avui",
"reply_indicator.attachments": "{count, plural, one {# adjunt} other {# adjunts}}",
"reply_indicator.cancel": "Cancel·la", "reply_indicator.cancel": "Cancel·la",
"reply_indicator.poll": "Enquesta",
"report.block": "Bloca", "report.block": "Bloca",
"report.block_explanation": "No veuràs els seus tuts. Ells no podran veure els teus tuts ni et podran seguir. Podran saber que estan blocats.", "report.block_explanation": "No veuràs els seus tuts. Ells no podran veure els teus tuts ni et podran seguir. Podran saber que estan blocats.",
"report.categories.legal": "Legal", "report.categories.legal": "Legal",

View File

@ -17,9 +17,11 @@
"account.badges.group": "گرووپ", "account.badges.group": "گرووپ",
"account.block": "بلۆکی @{name}", "account.block": "بلۆکی @{name}",
"account.block_domain": "بلۆکی هەموو شتێک لە {domain}", "account.block_domain": "بلۆکی هەموو شتێک لە {domain}",
"account.block_short": "بلۆک",
"account.blocked": "بلۆککرا", "account.blocked": "بلۆککرا",
"account.browse_more_on_origin_server": "گەڕانی فرەتر لە سەر پرۆفایلی سەرەکی", "account.browse_more_on_origin_server": "گەڕانی فرەتر لە سەر پرۆفایلی سەرەکی",
"account.cancel_follow_request": "داواکاری فۆڵۆو بکشێنەوە", "account.cancel_follow_request": "داواکاری فۆڵۆو بکشێنەوە",
"account.copy": "ڕوونووسی بەستەر بۆ توت",
"account.direct": "بە شێوەیەکی تایبەت باسی @{name} بکە", "account.direct": "بە شێوەیەکی تایبەت باسی @{name} بکە",
"account.disable_notifications": "ئاگانامە مەنێرە بۆم کاتێک @{name} پۆست دەکرێت", "account.disable_notifications": "ئاگانامە مەنێرە بۆم کاتێک @{name} پۆست دەکرێت",
"account.domain_blocked": "دۆمەین قەپاتکرا", "account.domain_blocked": "دۆمەین قەپاتکرا",
@ -30,6 +32,7 @@
"account.featured_tags.last_status_never": "هیچ پۆستێک نییە", "account.featured_tags.last_status_never": "هیچ پۆستێک نییە",
"account.featured_tags.title": "هاشتاگە تایبەتەکانی {name}", "account.featured_tags.title": "هاشتاگە تایبەتەکانی {name}",
"account.follow": "بەدواداچوون", "account.follow": "بەدواداچوون",
"account.follow_back": "فۆڵۆو بکەنەوە",
"account.followers": "شوێنکەوتووان", "account.followers": "شوێنکەوتووان",
"account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە", "account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە",
"account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}", "account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}",
@ -38,6 +41,7 @@
"account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.", "account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.",
"account.go_to_profile": "بڕۆ بۆ پڕۆفایلی", "account.go_to_profile": "بڕۆ بۆ پڕۆفایلی",
"account.hide_reblogs": "داشاردنی بووستەکان لە @{name}", "account.hide_reblogs": "داشاردنی بووستەکان لە @{name}",
"account.in_memoriam": "لە یادەوەریدا.",
"account.joined_short": "بەشداری کردووە", "account.joined_short": "بەشداری کردووە",
"account.languages": "گۆڕینی زمانە بەشداربووەکان", "account.languages": "گۆڕینی زمانە بەشداربووەکان",
"account.link_verified_on": "خاوەنداریەتی ئەم لینکە لە {date} چێک کراوە", "account.link_verified_on": "خاوەنداریەتی ئەم لینکە لە {date} چێک کراوە",
@ -46,7 +50,11 @@
"account.mention": "ئاماژە @{name}", "account.mention": "ئاماژە @{name}",
"account.moved_to": "{name} ئاماژەی بەوە کردووە کە ئەکاونتە نوێیەکەیان ئێستا:", "account.moved_to": "{name} ئاماژەی بەوە کردووە کە ئەکاونتە نوێیەکەیان ئێستا:",
"account.mute": "بێدەنگکردن @{name}", "account.mute": "بێدەنگکردن @{name}",
"account.mute_notifications_short": "پاڵ بە ئاگادارکردنەوەکانەوە بنێ",
"account.mute_short": "بێدەنگ",
"account.muted": "بێ دەنگ", "account.muted": "بێ دەنگ",
"account.mutual": "دوولایەنە",
"account.no_bio": "هیچ وەسفێک نەخراوەتەڕوو.",
"account.open_original_page": "لاپەڕەی ئەسڵی بکەرەوە", "account.open_original_page": "لاپەڕەی ئەسڵی بکەرەوە",
"account.posts": "نووسراوەکان", "account.posts": "نووسراوەکان",
"account.posts_with_replies": "توتس و وەڵامەکان", "account.posts_with_replies": "توتس و وەڵامەکان",
@ -62,6 +70,7 @@
"account.unendorse": "تایبەتمەندی لەسەر پرۆفایلەکە نیە", "account.unendorse": "تایبەتمەندی لەسەر پرۆفایلەکە نیە",
"account.unfollow": "بەدوادانەچو", "account.unfollow": "بەدوادانەچو",
"account.unmute": "بێدەنگکردنی @{name}", "account.unmute": "بێدەنگکردنی @{name}",
"account.unmute_notifications_short": "ئاگادارکردنەوەکان بێدەنگ بکەرەوە",
"account.unmute_short": "بێدەنگی مەکە", "account.unmute_short": "بێدەنگی مەکە",
"account_note.placeholder": "کرتەبکە بۆ زیادکردنی تێبینی", "account_note.placeholder": "کرتەبکە بۆ زیادکردنی تێبینی",
"admin.dashboard.daily_retention": "ڕێژەی مانەوەی بەکارهێنەر بەپێی ڕۆژ دوای ناو تۆمارکردن", "admin.dashboard.daily_retention": "ڕێژەی مانەوەی بەکارهێنەر بەپێی ڕۆژ دوای ناو تۆمارکردن",
@ -69,6 +78,10 @@
"admin.dashboard.retention.average": "ڕێژە", "admin.dashboard.retention.average": "ڕێژە",
"admin.dashboard.retention.cohort": "چوونەژوورەوەی مانگانە", "admin.dashboard.retention.cohort": "چوونەژوورەوەی مانگانە",
"admin.dashboard.retention.cohort_size": "ئەندامی نوێ", "admin.dashboard.retention.cohort_size": "ئەندامی نوێ",
"admin.impact_report.instance_accounts": "پڕۆفایلی هەژمارەکان ئەمە دەسڕێتەوە",
"admin.impact_report.instance_followers": "فۆڵۆوەرەکان بەکارهێنەران لەدەست دەدەن",
"admin.impact_report.instance_follows": "فۆڵۆوەرەکان ئەمبەکارهێنەرە لەدەست دەدەن",
"admin.impact_report.title": "پوختەی کاریگەرییەکان",
"alert.rate_limited.message": "تکایە هەوڵبدەرەوە دوای {retry_time, time, medium}.", "alert.rate_limited.message": "تکایە هەوڵبدەرەوە دوای {retry_time, time, medium}.",
"alert.rate_limited.title": "ڕێژەی سنووردار", "alert.rate_limited.title": "ڕێژەی سنووردار",
"alert.unexpected.message": "هەڵەیەکی چاوەڕوان نەکراو ڕوویدا.", "alert.unexpected.message": "هەڵەیەکی چاوەڕوان نەکراو ڕوویدا.",
@ -101,6 +114,8 @@
"column.direct": "ئاماژەی تایبەت", "column.direct": "ئاماژەی تایبەت",
"column.directory": "گەڕان لە پرۆفایلەکان", "column.directory": "گەڕان لە پرۆفایلەکان",
"column.domain_blocks": "دۆمەینە داخراوەکان", "column.domain_blocks": "دۆمەینە داخراوەکان",
"column.favourites": "دڵخوازەکان",
"column.firehose": "فیدی ڕاستەوخۆ",
"column.follow_requests": "بەدواداچوی داواکاریەکان بکە", "column.follow_requests": "بەدواداچوی داواکاریەکان بکە",
"column.home": "سەرەتا", "column.home": "سەرەتا",
"column.lists": "پێرست", "column.lists": "پێرست",
@ -121,6 +136,9 @@
"community.column_settings.remote_only": "تەنها بۆ دوور", "community.column_settings.remote_only": "تەنها بۆ دوور",
"compose.language.change": "گۆڕینی زمان", "compose.language.change": "گۆڕینی زمان",
"compose.language.search": "گەڕان بە زمانەکان...", "compose.language.search": "گەڕان بە زمانەکان...",
"compose.published.body": "پۆست بڵاوکراوەتەوە.",
"compose.published.open": "بیکەوە",
"compose.saved.body": "پۆستەکە سەیڤ کراوە.",
"compose_form.direct_message_warning_learn_more": "زیاتر فێربه", "compose_form.direct_message_warning_learn_more": "زیاتر فێربه",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.", "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.hashtag_warning": "ئەم بڵاوکراوەیە لە ژێر هیچ هاشتاگێکدا دا نانرێت وەک ئەوەیە، کە گشتی نەبێت. تەنها بڵاوکراوە گشتیەکان دەتوانرێ بە هاشتاگ گەڕانی بۆ بکرێت.", "compose_form.hashtag_warning": "ئەم بڵاوکراوەیە لە ژێر هیچ هاشتاگێکدا دا نانرێت وەک ئەوەیە، کە گشتی نەبێت. تەنها بڵاوکراوە گشتیەکان دەتوانرێ بە هاشتاگ گەڕانی بۆ بکرێت.",
@ -128,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "قفڵ دراوە", "compose_form.lock_disclaimer.lock": "قفڵ دراوە",
"compose_form.placeholder": "چی لە مێشکتدایە?", "compose_form.placeholder": "چی لە مێشکتدایە?",
"compose_form.poll.duration": "ماوەی ڕاپرسی", "compose_form.poll.duration": "ماوەی ڕاپرسی",
"compose_form.poll.multiple": "فرە هەڵبژاردە",
"compose_form.poll.option_placeholder": "بژاردەی {number}",
"compose_form.poll.single": "یەکێك هەلبژێرە",
"compose_form.poll.switch_to_multiple": "ڕاپرسی بگۆڕە بۆ ڕێگەدان بە چەند هەڵبژاردنێک", "compose_form.poll.switch_to_multiple": "ڕاپرسی بگۆڕە بۆ ڕێگەدان بە چەند هەڵبژاردنێک",
"compose_form.poll.switch_to_single": "گۆڕینی ڕاپرسی بۆ ڕێگەدان بە تاکە هەڵبژاردنێک", "compose_form.poll.switch_to_single": "گۆڕینی ڕاپرسی بۆ ڕێگەدان بە تاکە هەڵبژاردنێک",
"compose_form.poll.type": "ستایڵ",
"compose_form.publish": "پۆست",
"compose_form.publish_form": "بڵاوی بکەوە", "compose_form.publish_form": "بڵاوی بکەوە",
"compose_form.reply": "وەڵام",
"compose_form.save_changes": "نوێکردنەوە",
"compose_form.spoiler.marked": "دەق لە پشت ئاگاداریدا شاراوەتەوە", "compose_form.spoiler.marked": "دەق لە پشت ئاگاداریدا شاراوەتەوە",
"compose_form.spoiler.unmarked": "دەق شاراوە نییە", "compose_form.spoiler.unmarked": "دەق شاراوە نییە",
"compose_form.spoiler_placeholder": "ئاگادارکردنەوەی ناوەڕۆک (ئیختیاری)",
"confirmation_modal.cancel": "هەڵوەشاندنەوه", "confirmation_modal.cancel": "هەڵوەشاندنەوه",
"confirmations.block.block_and_report": "بلۆک & گوزارشت", "confirmations.block.block_and_report": "بلۆک & گوزارشت",
"confirmations.block.confirm": "بلۆک", "confirmations.block.confirm": "بلۆک",
@ -155,6 +181,7 @@
"confirmations.mute.explanation": "ئەمەش دەبێتە هۆی شاردنەوەی پۆستەکان یان ئەو بابەتانەی کە ئاماژەیان پێ دەکات ، بەڵام هێشتا ڕێگەیان پێ دەدات کە پۆستەکانتان ببینن و شوێنتان بکەون.", "confirmations.mute.explanation": "ئەمەش دەبێتە هۆی شاردنەوەی پۆستەکان یان ئەو بابەتانەی کە ئاماژەیان پێ دەکات ، بەڵام هێشتا ڕێگەیان پێ دەدات کە پۆستەکانتان ببینن و شوێنتان بکەون.",
"confirmations.mute.message": "ئایا دڵنیایت لەوەی دەتەوێت بیلێیت {name}?", "confirmations.mute.message": "ئایا دڵنیایت لەوەی دەتەوێت بیلێیت {name}?",
"confirmations.redraft.confirm": "سڕینەوە & دووبارە ڕەشکردنەوە", "confirmations.redraft.confirm": "سڕینەوە & دووبارە ڕەشکردنەوە",
"confirmations.redraft.message": "دڵنیای دەتەوێت ئەم پۆستە بسڕیتەوە و دووبارە دایبڕێژیتەوە؟ فەڤۆریت و بووستەکان لەدەست دەچن، وەڵامەکانی پۆستە ئەسڵیەکەش هەتیو دەبن.",
"confirmations.reply.confirm": "وەڵام", "confirmations.reply.confirm": "وەڵام",
"confirmations.reply.message": "وەڵامدانەوە ئێستا ئەو نامەیە ی کە تۆ ئێستا دایڕشتووە، دەنووسێتەوە. ئایا دڵنیایت کە دەتەوێت بەردەوام بیت?", "confirmations.reply.message": "وەڵامدانەوە ئێستا ئەو نامەیە ی کە تۆ ئێستا دایڕشتووە، دەنووسێتەوە. ئایا دڵنیایت کە دەتەوێت بەردەوام بیت?",
"confirmations.unfollow.confirm": "بەدوادانەچو", "confirmations.unfollow.confirm": "بەدوادانەچو",
@ -163,7 +190,9 @@
"conversation.mark_as_read": "نیشانەکردن وەک خوێندراوە", "conversation.mark_as_read": "نیشانەکردن وەک خوێندراوە",
"conversation.open": "نیشاندان گفتوگۆ", "conversation.open": "نیشاندان گفتوگۆ",
"conversation.with": "لەگەڵ{names}", "conversation.with": "لەگەڵ{names}",
"copy_icon_button.copied": "کۆپی کراوە بۆ کلیپبۆرد",
"copypaste.copied": "کۆپی کراوە", "copypaste.copied": "کۆپی کراوە",
"copypaste.copy_to_clipboard": "کۆپی کراوە بۆ کلیپبۆرد",
"directory.federated": "لە ڕاژەکانی ناسراو", "directory.federated": "لە ڕاژەکانی ناسراو",
"directory.local": "تەنها لە {domain}", "directory.local": "تەنها لە {domain}",
"directory.new_arrivals": "تازە گەیشتنەکان", "directory.new_arrivals": "تازە گەیشتنەکان",
@ -173,6 +202,7 @@
"dismissable_banner.community_timeline": "ئەمانە دوایین پۆستی گشتی ئەو کەسانەن کە ئەکاونتەکانیان لەلایەن {domain}ەوە هۆست کراوە.", "dismissable_banner.community_timeline": "ئەمانە دوایین پۆستی گشتی ئەو کەسانەن کە ئەکاونتەکانیان لەلایەن {domain}ەوە هۆست کراوە.",
"dismissable_banner.dismiss": "بەلاوە نان", "dismissable_banner.dismiss": "بەلاوە نان",
"dismissable_banner.explore_links": "ئەم هەواڵانە لە ئێستادا لەلایەن کەسانێکەوە لەسەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزی باس دەکرێن.", "dismissable_banner.explore_links": "ئەم هەواڵانە لە ئێستادا لەلایەن کەسانێکەوە لەسەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزی باس دەکرێن.",
"dismissable_banner.explore_statuses": "ئەمانە پۆستەکانن لە سەرانسەری وێبی کۆمەڵایەتی کە ئەمڕۆ کێشکردنیان بەدەستهێناوە. پۆستە نوێیەکان کە بووست و فەڤریتی زیاتریان هەیە ڕیزبەندی بەرزتریان هەیە.",
"dismissable_banner.explore_tags": "ئەم هاشتاگانە لە ئێستادا لە نێو خەڵکی سەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزیدا جێگەی خۆیان دەگرن.", "dismissable_banner.explore_tags": "ئەم هاشتاگانە لە ئێستادا لە نێو خەڵکی سەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزیدا جێگەی خۆیان دەگرن.",
"embed.instructions": "ئەم توتە بنچین بکە لەسەر وێب سایتەکەت بە کۆپیکردنی کۆدەکەی خوارەوە.", "embed.instructions": "ئەم توتە بنچین بکە لەسەر وێب سایتەکەت بە کۆپیکردنی کۆدەکەی خوارەوە.",
"embed.preview": "ئەمە ئەو شتەیە کە لە شێوەی خۆی دەچێت:", "embed.preview": "ئەمە ئەو شتەیە کە لە شێوەی خۆی دەچێت:",
@ -216,6 +246,7 @@
"errors.unexpected_crash.copy_stacktrace": "کۆپیکردنی ستێکتراسی بۆ کلیپ بۆرد", "errors.unexpected_crash.copy_stacktrace": "کۆپیکردنی ستێکتراسی بۆ کلیپ بۆرد",
"errors.unexpected_crash.report_issue": "کێشەی گوزارشت", "errors.unexpected_crash.report_issue": "کێشەی گوزارشت",
"explore.search_results": "ئەنجامەکانی گەڕان", "explore.search_results": "ئەنجامەکانی گەڕان",
"explore.suggested_follows": "خەڵک",
"explore.title": "گەڕان", "explore.title": "گەڕان",
"explore.trending_links": "هەواڵەکان", "explore.trending_links": "هەواڵەکان",
"explore.trending_statuses": "بڵاوکراوەکان", "explore.trending_statuses": "بڵاوکراوەکان",
@ -236,9 +267,16 @@
"filter_modal.select_filter.subtitle": "بەکارهێنانی پۆلێنی بەردەست یان دروستکردنی پۆلێنێکی نوێ", "filter_modal.select_filter.subtitle": "بەکارهێنانی پۆلێنی بەردەست یان دروستکردنی پۆلێنێکی نوێ",
"filter_modal.select_filter.title": "ئەم بڵاوکراوەیە بپاڵێوە", "filter_modal.select_filter.title": "ئەم بڵاوکراوەیە بپاڵێوە",
"filter_modal.title.status": "بڵاوکراوەیەک بپاڵێوە", "filter_modal.title.status": "بڵاوکراوەیەک بپاڵێوە",
"firehose.all": "هەموو",
"firehose.local": "لەسەر ئەم ڕاژەیە",
"firehose.remote": "ڕاژەکانی دی",
"follow_request.authorize": "ده‌سه‌ڵاتپێدراو", "follow_request.authorize": "ده‌سه‌ڵاتپێدراو",
"follow_request.reject": "ڕەتکردنەوە", "follow_request.reject": "ڕەتکردنەوە",
"follow_requests.unlocked_explanation": "هەرچەندە هەژمارەکەت داخراو نییە، ستافی {domain} وا بیریان کردەوە کە لەوانەیە بتانەوێت پێداچوونەوە بە داواکاریەکانی ئەم هەژمارەدا بکەن بە دەستی.", "follow_requests.unlocked_explanation": "هەرچەندە هەژمارەکەت داخراو نییە، ستافی {domain} وا بیریان کردەوە کە لەوانەیە بتانەوێت پێداچوونەوە بە داواکاریەکانی ئەم هەژمارەدا بکەن بە دەستی.",
"follow_suggestions.curated_suggestion": "ستاف هەڵبژاردنی",
"follow_suggestions.dismiss": "دوبارە پشانی مەدە",
"follow_suggestions.view_all": "بینینی هەموو",
"follow_suggestions.who_to_follow": "دواکەوتنی کێ",
"followed_tags": "هاشتاگە شوێنکەوتووەکان", "followed_tags": "هاشتاگە شوێنکەوتووەکان",
"footer.about": "دەربارە", "footer.about": "دەربارە",
"footer.directory": "ڕابەری پەڕەی ناساندن", "footer.directory": "ڕابەری پەڕەی ناساندن",
@ -259,6 +297,7 @@
"hashtag.column_settings.tag_mode.any": "هەر کام لەمانە", "hashtag.column_settings.tag_mode.any": "هەر کام لەمانە",
"hashtag.column_settings.tag_mode.none": "هیچ کام لەمانە", "hashtag.column_settings.tag_mode.none": "هیچ کام لەمانە",
"hashtag.column_settings.tag_toggle": "تاگی زیادە ی ئەم ستوونە لەخۆ بنووسە", "hashtag.column_settings.tag_toggle": "تاگی زیادە ی ئەم ستوونە لەخۆ بنووسە",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participant} other {{counter} participants}}",
"hashtag.follow": "شوێنکەوتنی هاشتاگ", "hashtag.follow": "شوێنکەوتنی هاشتاگ",
"hashtag.unfollow": "شوێن نەکەوتنی هاشتاگ", "hashtag.unfollow": "شوێن نەکەوتنی هاشتاگ",
"home.column_settings.basic": "بنەڕەتی", "home.column_settings.basic": "بنەڕەتی",

View File

@ -32,6 +32,7 @@
"account.featured_tags.last_status_never": "Žádné příspěvky", "account.featured_tags.last_status_never": "Žádné příspěvky",
"account.featured_tags.title": "Hlavní hashtagy uživatele {name}", "account.featured_tags.title": "Hlavní hashtagy uživatele {name}",
"account.follow": "Sledovat", "account.follow": "Sledovat",
"account.follow_back": "Také sledovat",
"account.followers": "Sledující", "account.followers": "Sledující",
"account.followers.empty": "Tohoto uživatele zatím nikdo nesleduje.", "account.followers.empty": "Tohoto uživatele zatím nikdo nesleduje.",
"account.followers_counter": "{count, plural, one {{counter} Sledující} few {{counter} Sledující} many {{counter} Sledujících} other {{counter} Sledujících}}", "account.followers_counter": "{count, plural, one {{counter} Sledující} few {{counter} Sledující} many {{counter} Sledujících} other {{counter} Sledujících}}",
@ -52,6 +53,7 @@
"account.mute_notifications_short": "Ztlumit upozornění", "account.mute_notifications_short": "Ztlumit upozornění",
"account.mute_short": "Ztlumit", "account.mute_short": "Ztlumit",
"account.muted": "Skrytý", "account.muted": "Skrytý",
"account.mutual": "Vzájemné",
"account.no_bio": "Nebyl poskytnut žádný popis.", "account.no_bio": "Nebyl poskytnut žádný popis.",
"account.open_original_page": "Otevřít původní stránku", "account.open_original_page": "Otevřít původní stránku",
"account.posts": "Příspěvky", "account.posts": "Příspěvky",
@ -144,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "zamčený", "compose_form.lock_disclaimer.lock": "zamčený",
"compose_form.placeholder": "Co se vám honí hlavou?", "compose_form.placeholder": "Co se vám honí hlavou?",
"compose_form.poll.duration": "Doba trvání ankety", "compose_form.poll.duration": "Doba trvání ankety",
"compose_form.poll.multiple": "Výběr z více možností",
"compose_form.poll.option_placeholder": "Volba {number}",
"compose_form.poll.single": "Vyber jednu",
"compose_form.poll.switch_to_multiple": "Povolit u ankety výběr více voleb", "compose_form.poll.switch_to_multiple": "Povolit u ankety výběr více voleb",
"compose_form.poll.switch_to_single": "Povolit u ankety výběr pouze jedné volby", "compose_form.poll.switch_to_single": "Povolit u ankety výběr pouze jedné volby",
"compose_form.poll.type": "Styl",
"compose_form.publish": "Odeslat",
"compose_form.publish_form": "Zveřejnit", "compose_form.publish_form": "Zveřejnit",
"compose_form.reply": "Odpovědět",
"compose_form.save_changes": "Aktualizovat",
"compose_form.spoiler.marked": "Odebrat varování o obsahu", "compose_form.spoiler.marked": "Odebrat varování o obsahu",
"compose_form.spoiler.unmarked": "Přidat varování o obsahu", "compose_form.spoiler.unmarked": "Přidat varování o obsahu",
"compose_form.spoiler_placeholder": "Upozornění na obsah (nepovinné)",
"confirmation_modal.cancel": "Zrušit", "confirmation_modal.cancel": "Zrušit",
"confirmations.block.block_and_report": "Blokovat a nahlásit", "confirmations.block.block_and_report": "Blokovat a nahlásit",
"confirmations.block.confirm": "Blokovat", "confirmations.block.confirm": "Blokovat",
@ -227,7 +237,7 @@
"empty_column.follow_requests": "Zatím nemáte žádné žádosti o sledování. Až nějakou obdržíte, zobrazí se zde.", "empty_column.follow_requests": "Zatím nemáte žádné žádosti o sledování. Až nějakou obdržíte, zobrazí se zde.",
"empty_column.followed_tags": "Zatím jste nesledovali žádné hashtagy. Až to uděláte, objeví se zde.", "empty_column.followed_tags": "Zatím jste nesledovali žádné hashtagy. Až to uděláte, objeví se zde.",
"empty_column.hashtag": "Pod tímto hashtagem zde zatím nic není.", "empty_column.hashtag": "Pod tímto hashtagem zde zatím nic není.",
"empty_column.home": "Vaše domovská časová osa je prázdná! Naplňte ji sledováním dalších lidí. {suggestions}", "empty_column.home": "Vaše domovská časová osa je prázdná! Naplňte ji sledováním dalších lidí.",
"empty_column.list": "V tomto seznamu zatím nic není. Až nějaký člen z tohoto seznamu zveřejní nový příspěvek, objeví se zde.", "empty_column.list": "V tomto seznamu zatím nic není. Až nějaký člen z tohoto seznamu zveřejní nový příspěvek, objeví se zde.",
"empty_column.lists": "Zatím nemáte žádné seznamy. Až nějaký vytvoříte, zobrazí se zde.", "empty_column.lists": "Zatím nemáte žádné seznamy. Až nějaký vytvoříte, zobrazí se zde.",
"empty_column.mutes": "Zatím jste neskryli žádného uživatele.", "empty_column.mutes": "Zatím jste neskryli žádného uživatele.",
@ -266,7 +276,18 @@
"firehose.remote": "Ostatní servery", "firehose.remote": "Ostatní servery",
"follow_request.authorize": "Autorizovat", "follow_request.authorize": "Autorizovat",
"follow_request.reject": "Zamítnout", "follow_request.reject": "Zamítnout",
"follow_requests.unlocked_explanation": "Přestože váš účet není zamčený, administrátor {domain} usoudil, že byste mohli chtít tyto žádosti o sledování zkontrolovat ručně.", "follow_requests.unlocked_explanation": "Přestože váš účet není uzamčen, personál {domain} usoudil, že byste mohli chtít tyto požadavky na sledování zkontrolovat ručně.",
"follow_suggestions.curated_suggestion": "Výběr personálů",
"follow_suggestions.dismiss": "Znovu nezobrazovat",
"follow_suggestions.hints.featured": "Tento profil byl ručně vybrán týmem {domain}.",
"follow_suggestions.hints.friends_of_friends": "Tento profil je populární mezi lidmi, které sledujete.",
"follow_suggestions.hints.most_followed": "Tento profil je jedním z nejvíce sledovaných na {domain}.",
"follow_suggestions.hints.most_interactions": "Tento profil nedávno dostalo velkou pozornost na {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Tento profil je podobný profilům, které jste nedávno sledovali.",
"follow_suggestions.personalized_suggestion": "Přizpůsobený návrh",
"follow_suggestions.popular_suggestion": "Populární návrh",
"follow_suggestions.view_all": "Zobrazit vše",
"follow_suggestions.who_to_follow": "Koho sledovat",
"followed_tags": "Sledované hashtagy", "followed_tags": "Sledované hashtagy",
"footer.about": "O aplikaci", "footer.about": "O aplikaci",
"footer.directory": "Adresář profilů", "footer.directory": "Adresář profilů",
@ -287,15 +308,15 @@
"hashtag.column_settings.tag_mode.any": "Jakýkoliv z těchto", "hashtag.column_settings.tag_mode.any": "Jakýkoliv z těchto",
"hashtag.column_settings.tag_mode.none": "Žádný z těchto", "hashtag.column_settings.tag_mode.none": "Žádný z těchto",
"hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci další štítky", "hashtag.column_settings.tag_toggle": "Zahrnout v tomto sloupci další štítky",
"hashtag.counter_by_accounts": "{count, plural, one {{counter} účastník} few {{counter} účastníci} other {{counter} účastníků}}",
"hashtag.counter_by_uses": "{count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}",
"hashtag.counter_by_uses_today": "Dnes {count, plural, one {{counter} příspěvek} few {{counter} příspěvky} other {{counter} příspěvků}}",
"hashtag.follow": "Sledovat hashtag", "hashtag.follow": "Sledovat hashtag",
"hashtag.unfollow": "Přestat sledovat hashtag", "hashtag.unfollow": "Přestat sledovat hashtag",
"home.actions.go_to_explore": "Podívejte se, co frčí", "hashtags.and_other": "…a {count, plural, one {# další} few {# další} other {# dalších}}",
"home.actions.go_to_suggestions": "Najít lidi ke sledování",
"home.column_settings.basic": "Základní", "home.column_settings.basic": "Základní",
"home.column_settings.show_reblogs": "Zobrazit boosty", "home.column_settings.show_reblogs": "Zobrazit boosty",
"home.column_settings.show_replies": "Zobrazit odpovědi", "home.column_settings.show_replies": "Zobrazit odpovědi",
"home.explore_prompt.body": "Váš domovský kanál bude obsahovat směs příspěvků z hashtagů, které jste se rozhodli sledovat, lidí, které jste se rozhodli sledovat, a příspěvků, které boostují. Pokud vám to připadá příliš klidné, možná budete chtít:",
"home.explore_prompt.title": "Toto je vaše domovská základna uvnitř Mastodonu.",
"home.hide_announcements": "Skrýt oznámení", "home.hide_announcements": "Skrýt oznámení",
"home.pending_critical_update.body": "Aktualizujte, prosím, svůj Mastodon server co nejdříve!", "home.pending_critical_update.body": "Aktualizujte, prosím, svůj Mastodon server co nejdříve!",
"home.pending_critical_update.link": "Zobrazit aktualizace", "home.pending_critical_update.link": "Zobrazit aktualizace",
@ -376,6 +397,7 @@
"lists.search": "Hledejte mezi lidmi, které sledujete", "lists.search": "Hledejte mezi lidmi, které sledujete",
"lists.subheading": "Vaše seznamy", "lists.subheading": "Vaše seznamy",
"load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}",
"loading_indicator.label": "Načítání…",
"media_gallery.toggle_visible": "{number, plural, one {Skrýt obrázek} few {Skrýt obrázky} many {Skrýt obrázky} other {Skrýt obrázky}}", "media_gallery.toggle_visible": "{number, plural, one {Skrýt obrázek} few {Skrýt obrázky} many {Skrýt obrázky} other {Skrýt obrázky}}",
"moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.", "moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.",
"mute_modal.duration": "Trvání", "mute_modal.duration": "Trvání",
@ -461,8 +483,19 @@
"onboarding.actions.go_to_home": "Přejít na svůj domovský feed", "onboarding.actions.go_to_home": "Přejít na svůj domovský feed",
"onboarding.compose.template": "Ahoj #Mastodon!", "onboarding.compose.template": "Ahoj #Mastodon!",
"onboarding.follows.empty": "Bohužel, žádné výsledky nelze momentálně zobrazit. Můžete zkusit vyhledat nebo procházet stránku s průzkumem a najít lidi, kteří budou sledovat, nebo to zkuste znovu později.", "onboarding.follows.empty": "Bohužel, žádné výsledky nelze momentálně zobrazit. Můžete zkusit vyhledat nebo procházet stránku s průzkumem a najít lidi, kteří budou sledovat, nebo to zkuste znovu později.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "Domovský kanál je hlavní metodou zažívání Mastodonu. Čím více lidí sledujete, tím aktivnější a zajímavější bude. Pro začnutí, zde máte několik návrhů:",
"onboarding.follows.title": "Populární na Mastodonu", "onboarding.follows.title": "Přispůsobit vlastní domovský kanál",
"onboarding.profile.discoverable": "Udělat svůj profil vyhledatelným",
"onboarding.profile.discoverable_hint": "Když se rozhodnete být vyhledatelný na Mastodonu, vaše příspěvky se mohou objevit ve výsledcích vyhledávání a v populárních, a váš profil může být navrhován lidem s podobnými zájmy.",
"onboarding.profile.display_name": "Zobrazované jméno",
"onboarding.profile.display_name_hint": "Vaše celé jméno nebo přezdívka…",
"onboarding.profile.lead": "Toto můžete vždy dokončit později v nastavení, kde je k dispozici ještě více možností přizpůsobení.",
"onboarding.profile.note": "O vás",
"onboarding.profile.note_hint": "Můžete @zmínit jiné osoby nebo #hashtagy…",
"onboarding.profile.save_and_continue": "Uložit a pokračovat",
"onboarding.profile.title": "Nastavení profilu",
"onboarding.profile.upload_avatar": "Nahrát profilový obrázek",
"onboarding.profile.upload_header": "Nahrát hlavičku profilu",
"onboarding.share.lead": "Dejte lidem vědět, jak vás mohou najít na Mastodonu!", "onboarding.share.lead": "Dejte lidem vědět, jak vás mohou najít na Mastodonu!",
"onboarding.share.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}", "onboarding.share.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}",
"onboarding.share.next_steps": "Možné další kroky:", "onboarding.share.next_steps": "Možné další kroky:",
@ -470,13 +503,13 @@
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
"onboarding.start.skip": "Want to skip right ahead?", "onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Dokázali jste to!", "onboarding.start.title": "Dokázali jste to!",
"onboarding.steps.follow_people.body": "You curate your own feed. Lets fill it with interesting people.", "onboarding.steps.follow_people.body": "Mastodon je o sledování zajimavých lidí.",
"onboarding.steps.follow_people.title": "Follow {count, plural, one {one person} other {# people}}", "onboarding.steps.follow_people.title": "Přispůsobit vlastní domovský kanál",
"onboarding.steps.publish_status.body": "Řekněte světu Ahoj.", "onboarding.steps.publish_status.body": "Řekněte světu ahoj s pomocí textem, fotografiemi, videami nebo anketami {emoji}",
"onboarding.steps.publish_status.title": "Vytvořte svůj první příspěvek", "onboarding.steps.publish_status.title": "Vytvořte svůj první příspěvek",
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Přizpůsobit svůj profil", "onboarding.steps.setup_profile.title": "Přizpůsobit svůj profil",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.body": "Dejte blízkým lidem vědět, jak vás mohou najít na Mastodonu",
"onboarding.steps.share_profile.title": "Sdílejte svůj profil", "onboarding.steps.share_profile.title": "Sdílejte svůj profil",
"onboarding.tips.2fa": "<strong>Víte, že?</strong> Svůj účet můžete zabezpečit nastavením dvoufaktorového ověřování v nastavení účtu. Funguje s jakoukoli TOTP aplikací podle vašeho výběru, telefonní číslo není nutné!", "onboarding.tips.2fa": "<strong>Víte, že?</strong> Svůj účet můžete zabezpečit nastavením dvoufaktorového ověřování v nastavení účtu. Funguje s jakoukoli TOTP aplikací podle vašeho výběru, telefonní číslo není nutné!",
"onboarding.tips.accounts_from_other_servers": "<strong>Víte, že?</strong> Protože je Mastodon decentralizovaný, některé profily, na které narazíte, budou hostovány na jiných serverech, než je ten váš. A přesto s nimi můžete bezproblémově komunikovat! Jejich server se nachází v druhé polovině uživatelského jména!", "onboarding.tips.accounts_from_other_servers": "<strong>Víte, že?</strong> Protože je Mastodon decentralizovaný, některé profily, na které narazíte, budou hostovány na jiných serverech, než je ten váš. A přesto s nimi můžete bezproblémově komunikovat! Jejich server se nachází v druhé polovině uživatelského jména!",
@ -496,9 +529,18 @@
"poll_button.add_poll": "Přidat anketu", "poll_button.add_poll": "Přidat anketu",
"poll_button.remove_poll": "Odebrat anketu", "poll_button.remove_poll": "Odebrat anketu",
"privacy.change": "Změnit soukromí příspěvku", "privacy.change": "Změnit soukromí příspěvku",
"privacy.direct.long": "Všichni zmínění v příspěvku",
"privacy.direct.short": "Vybraní lidé",
"privacy.private.long": "Jen vaši sledující",
"privacy.private.short": "Sledující",
"privacy.public.long": "Kdokoliv na Mastodonu i mimo něj",
"privacy.public.short": "Veřejné", "privacy.public.short": "Veřejné",
"privacy.unlisted.additional": "Chová se stejně jako veřejný, až na to, že se příspěvek neobjeví v živých kanálech nebo hashtazích, v objevování nebo vyhledávání na Mastodonu, a to i když je účet nastaven tak, aby se zde všude tyto příspěvky zobrazovaly.",
"privacy.unlisted.long": "Méně algoritmických fanfár",
"privacy.unlisted.short": "Ztišené veřejné",
"privacy_policy.last_updated": "Naposledy aktualizováno {date}", "privacy_policy.last_updated": "Naposledy aktualizováno {date}",
"privacy_policy.title": "Zásady ochrany osobních údajů", "privacy_policy.title": "Zásady ochrany osobních údajů",
"recommended": "Doporučeno",
"refresh": "Obnovit", "refresh": "Obnovit",
"regeneration_indicator.label": "Načítání…", "regeneration_indicator.label": "Načítání…",
"regeneration_indicator.sublabel": "Váš domovský kanál se připravuje!", "regeneration_indicator.sublabel": "Váš domovský kanál se připravuje!",
@ -513,7 +555,9 @@
"relative_time.minutes": "{number} m", "relative_time.minutes": "{number} m",
"relative_time.seconds": "{number} s", "relative_time.seconds": "{number} s",
"relative_time.today": "dnes", "relative_time.today": "dnes",
"reply_indicator.attachments": "{count, plural, one {{counter} příloha} few {{counter} přílohy} other {{counter} přilohů}}",
"reply_indicator.cancel": "Zrušit", "reply_indicator.cancel": "Zrušit",
"reply_indicator.poll": "Anketa",
"report.block": "Blokovat", "report.block": "Blokovat",
"report.block_explanation": "Neuvidíte příspěvky tohoto uživatele. On neuvidí vaše příspěvky, ani vás nebude moci sledovat. Pozná, že je blokován.", "report.block_explanation": "Neuvidíte příspěvky tohoto uživatele. On neuvidí vaše příspěvky, ani vás nebude moci sledovat. Pozná, že je blokován.",
"report.categories.legal": "Právní ustanovení", "report.categories.legal": "Právní ustanovení",
@ -569,6 +613,7 @@
"search.quick_action.status_search": "Příspěvky odpovídající {x}", "search.quick_action.status_search": "Příspěvky odpovídající {x}",
"search.search_or_paste": "Hledat nebo vložit URL", "search.search_or_paste": "Hledat nebo vložit URL",
"search_popout.full_text_search_disabled_message": "Nedostupné na {domain}.", "search_popout.full_text_search_disabled_message": "Nedostupné na {domain}.",
"search_popout.full_text_search_logged_out_message": "Dostupné pouze po přihlášení.",
"search_popout.language_code": "Kód jazyka podle ISO", "search_popout.language_code": "Kód jazyka podle ISO",
"search_popout.options": "Možnosti hledání", "search_popout.options": "Možnosti hledání",
"search_popout.quick_actions": "Rychlé akce", "search_popout.quick_actions": "Rychlé akce",

View File

@ -146,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "wedi ei gloi", "compose_form.lock_disclaimer.lock": "wedi ei gloi",
"compose_form.placeholder": "Beth sydd ar eich meddwl?", "compose_form.placeholder": "Beth sydd ar eich meddwl?",
"compose_form.poll.duration": "Cyfnod pleidlais", "compose_form.poll.duration": "Cyfnod pleidlais",
"compose_form.poll.multiple": "Dewis lluosog",
"compose_form.poll.option_placeholder": "Dewis {number}",
"compose_form.poll.single": "Ddewis un",
"compose_form.poll.switch_to_multiple": "Newid pleidlais i adael mwy nag un dewis", "compose_form.poll.switch_to_multiple": "Newid pleidlais i adael mwy nag un dewis",
"compose_form.poll.switch_to_single": "Newid pleidlais i gyfyngu i un dewis", "compose_form.poll.switch_to_single": "Newid pleidlais i gyfyngu i un dewis",
"compose_form.poll.type": "Arddull",
"compose_form.publish": "Postiad",
"compose_form.publish_form": "Cyhoeddi", "compose_form.publish_form": "Cyhoeddi",
"compose_form.reply": "Ateb",
"compose_form.save_changes": "Diweddariad",
"compose_form.spoiler.marked": "Dileu rhybudd cynnwys", "compose_form.spoiler.marked": "Dileu rhybudd cynnwys",
"compose_form.spoiler.unmarked": "Ychwanegu rhybudd cynnwys", "compose_form.spoiler.unmarked": "Ychwanegu rhybudd cynnwys",
"compose_form.spoiler_placeholder": "Rhybudd cynnwys (dewisol)",
"confirmation_modal.cancel": "Diddymu", "confirmation_modal.cancel": "Diddymu",
"confirmations.block.block_and_report": "Rhwystro ac Adrodd", "confirmations.block.block_and_report": "Rhwystro ac Adrodd",
"confirmations.block.confirm": "Blocio", "confirmations.block.confirm": "Blocio",
@ -269,6 +277,17 @@
"follow_request.authorize": "Awdurdodi", "follow_request.authorize": "Awdurdodi",
"follow_request.reject": "Gwrthod", "follow_request.reject": "Gwrthod",
"follow_requests.unlocked_explanation": "Er nid yw eich cyfrif wedi'i gloi, roedd y staff {domain} yn meddwl efallai hoffech adolygu ceisiadau dilyn o'r cyfrifau rhain wrth law.", "follow_requests.unlocked_explanation": "Er nid yw eich cyfrif wedi'i gloi, roedd y staff {domain} yn meddwl efallai hoffech adolygu ceisiadau dilyn o'r cyfrifau rhain wrth law.",
"follow_suggestions.curated_suggestion": "Dewis staff",
"follow_suggestions.dismiss": "Peidio â dangos hwn eto",
"follow_suggestions.hints.featured": "Mae'r proffil hwn wedi'i ddewis yn arbennig gan dîm {domain}.",
"follow_suggestions.hints.friends_of_friends": "Mae'r proffil hwn yn boblogaidd ymhlith y bobl rydych chi'n eu dilyn.",
"follow_suggestions.hints.most_followed": "Mae'r proffil hwn yn un o'r rhai sy'n cael ei ddilyn fwyaf ar {domain}.",
"follow_suggestions.hints.most_interactions": "Mae'r proffil hwn wedi bod yn cael llawer o sylw yn ddiweddar ar {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Mae'r proffil hwn yn debyg i'r proffiliau rydych chi wedi'u dilyn yn fwyaf diweddar.",
"follow_suggestions.personalized_suggestion": "Awgrym personol",
"follow_suggestions.popular_suggestion": "Awgrym poblogaidd",
"follow_suggestions.view_all": "Gweld y cyfan",
"follow_suggestions.who_to_follow": "Pwy i ddilyn",
"followed_tags": "Hashnodau rydych yn eu dilyn", "followed_tags": "Hashnodau rydych yn eu dilyn",
"footer.about": "Ynghylch", "footer.about": "Ynghylch",
"footer.directory": "Cyfeiriadur proffiliau", "footer.directory": "Cyfeiriadur proffiliau",
@ -295,13 +314,9 @@
"hashtag.follow": "Dilyn hashnod", "hashtag.follow": "Dilyn hashnod",
"hashtag.unfollow": "Dad-ddilyn hashnod", "hashtag.unfollow": "Dad-ddilyn hashnod",
"hashtags.and_other": "…a {count, plural, other {# more}}", "hashtags.and_other": "…a {count, plural, other {# more}}",
"home.actions.go_to_explore": "Gweld beth yw'r tuedd",
"home.actions.go_to_suggestions": "Ffeindio pobl i'w dilyn",
"home.column_settings.basic": "Syml", "home.column_settings.basic": "Syml",
"home.column_settings.show_reblogs": "Dangos hybiau", "home.column_settings.show_reblogs": "Dangos hybiau",
"home.column_settings.show_replies": "Dangos atebion", "home.column_settings.show_replies": "Dangos atebion",
"home.explore_prompt.body": "Bydd eich llif cartref yn cynnwys cymysgedd o bostiadau o'r hashnodau rydych chi wedi dewis eu dilyn, y bobl rydych chi wedi dewis eu dilyn, a'r postiadau maen nhw'n rhoi hwb iddyn nhw. Os yw hynny'n teimlo'n rhy dawel, efallai y byddwch eisiau:",
"home.explore_prompt.title": "Dyma'ch cartref o fewn Mastodon.",
"home.hide_announcements": "Cuddio cyhoeddiadau", "home.hide_announcements": "Cuddio cyhoeddiadau",
"home.pending_critical_update.body": "Diweddarwch eich gweinydd Mastodon cyn gynted â phosibl!", "home.pending_critical_update.body": "Diweddarwch eich gweinydd Mastodon cyn gynted â phosibl!",
"home.pending_critical_update.link": "Gweld y diweddariadau", "home.pending_critical_update.link": "Gweld y diweddariadau",
@ -514,7 +529,15 @@
"poll_button.add_poll": "Ychwanegu pleidlais", "poll_button.add_poll": "Ychwanegu pleidlais",
"poll_button.remove_poll": "Tynnu pleidlais", "poll_button.remove_poll": "Tynnu pleidlais",
"privacy.change": "Addasu preifatrwdd y post", "privacy.change": "Addasu preifatrwdd y post",
"privacy.direct.long": "Pawb sydd â son amdanyn nhw yn y postiad",
"privacy.direct.short": "Pobl benodol",
"privacy.private.long": "Eich dilynwyr yn unig",
"privacy.private.short": "Dilynwyr",
"privacy.public.long": "Unrhyw ar ac oddi ar Mastodon",
"privacy.public.short": "Cyhoeddus", "privacy.public.short": "Cyhoeddus",
"privacy.unlisted.additional": "Mae hwn yn ymddwyn yn union fel y cyhoeddus, ac eithrio na fydd y postiad yn ymddangos mewn ffrydiau byw neu hashnodau, archwilio, neu chwiliad Mastodon, hyd yn oed os ydych wedi eich cynnwys ar draws y cyfrif.",
"privacy.unlisted.long": "Llai o ddathliadau algorithmig",
"privacy.unlisted.short": "Tewi'r cyhoeddus",
"privacy_policy.last_updated": "Diweddarwyd ddiwethaf ar {date}", "privacy_policy.last_updated": "Diweddarwyd ddiwethaf ar {date}",
"privacy_policy.title": "Polisi Preifatrwydd", "privacy_policy.title": "Polisi Preifatrwydd",
"recommended": "Argymhellwyd", "recommended": "Argymhellwyd",
@ -532,7 +555,9 @@
"relative_time.minutes": "{number} munud", "relative_time.minutes": "{number} munud",
"relative_time.seconds": "{number} eiliad", "relative_time.seconds": "{number} eiliad",
"relative_time.today": "heddiw", "relative_time.today": "heddiw",
"reply_indicator.attachments": "{count, plural, one {# attachment} arall {# attachments}}",
"reply_indicator.cancel": "Canslo", "reply_indicator.cancel": "Canslo",
"reply_indicator.poll": "Arolwg",
"report.block": "Blocio", "report.block": "Blocio",
"report.block_explanation": "Ni welwch chi eu postiadau. Ni allan nhw weld eich postiadau na'ch dilyn. Byddan nhw'n gallu gweld eu bod nhw wedi'u rhwystro.", "report.block_explanation": "Ni welwch chi eu postiadau. Ni allan nhw weld eich postiadau na'ch dilyn. Byddan nhw'n gallu gweld eu bod nhw wedi'u rhwystro.",
"report.categories.legal": "Cyfreithiol", "report.categories.legal": "Cyfreithiol",

View File

@ -145,11 +145,9 @@
"compose_form.lock_disclaimer": "Din konto er ikke {locked}. Enhver kan følge dig og se indlæg kun beregnet for følgere.", "compose_form.lock_disclaimer": "Din konto er ikke {locked}. Enhver kan følge dig og se indlæg kun beregnet for følgere.",
"compose_form.lock_disclaimer.lock": "låst", "compose_form.lock_disclaimer.lock": "låst",
"compose_form.placeholder": "Hvad tænker du på?", "compose_form.placeholder": "Hvad tænker du på?",
"compose_form.poll.add_option": "Tilføj mulighed",
"compose_form.poll.duration": "Afstemningens varighed", "compose_form.poll.duration": "Afstemningens varighed",
"compose_form.poll.multiple": "Multivalg", "compose_form.poll.multiple": "Multivalg",
"compose_form.poll.option_placeholder": "Valgmulighed {number}", "compose_form.poll.option_placeholder": "Valgmulighed {number}",
"compose_form.poll.remove_option": "Fjern denne valgmulighed",
"compose_form.poll.single": "Vælg én", "compose_form.poll.single": "Vælg én",
"compose_form.poll.switch_to_multiple": "Ændr afstemning til flervalgstype", "compose_form.poll.switch_to_multiple": "Ændr afstemning til flervalgstype",
"compose_form.poll.switch_to_single": "Ændr afstemning til enkeltvalgstype", "compose_form.poll.switch_to_single": "Ændr afstemning til enkeltvalgstype",
@ -279,6 +277,17 @@
"follow_request.authorize": "Godkend", "follow_request.authorize": "Godkend",
"follow_request.reject": "Afvis", "follow_request.reject": "Afvis",
"follow_requests.unlocked_explanation": "Selvom din konto ikke er låst, synes {domain}-personalet, du måske bør gennemgå disse anmodninger manuelt.", "follow_requests.unlocked_explanation": "Selvom din konto ikke er låst, synes {domain}-personalet, du måske bør gennemgå disse anmodninger manuelt.",
"follow_suggestions.curated_suggestion": "Personaleudvalgt",
"follow_suggestions.dismiss": "Vis ikke igen",
"follow_suggestions.hints.featured": "Denne profil er håndplukket af {domain}-teamet.",
"follow_suggestions.hints.friends_of_friends": "Denne profil er populær blandt de personer, som følges.",
"follow_suggestions.hints.most_followed": "Denne profil er en af de mest fulgte på {domain}.",
"follow_suggestions.hints.most_interactions": "Denne profil har for nylig fået stor opmærksomhed på {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "Denne profil svarer til de profiler, som senest er blevet fulgt.",
"follow_suggestions.personalized_suggestion": "Personligt forslag",
"follow_suggestions.popular_suggestion": "Populært forslag",
"follow_suggestions.view_all": "Vis alle",
"follow_suggestions.who_to_follow": "Hvem, som skal følges",
"followed_tags": "Hashtag, som følges", "followed_tags": "Hashtag, som følges",
"footer.about": "Om", "footer.about": "Om",
"footer.directory": "Profiloversigt", "footer.directory": "Profiloversigt",
@ -305,13 +314,9 @@
"hashtag.follow": "Følg hashtag", "hashtag.follow": "Følg hashtag",
"hashtag.unfollow": "Stop med at følge hashtag", "hashtag.unfollow": "Stop med at følge hashtag",
"hashtags.and_other": "…og {count, plural, one {}other {# flere}}", "hashtags.and_other": "…og {count, plural, one {}other {# flere}}",
"home.actions.go_to_explore": "Se, hvad som trender",
"home.actions.go_to_suggestions": "Find nogle personer at følge",
"home.column_settings.basic": "Grundlæggende", "home.column_settings.basic": "Grundlæggende",
"home.column_settings.show_reblogs": "Vis boosts", "home.column_settings.show_reblogs": "Vis boosts",
"home.column_settings.show_replies": "Vis svar", "home.column_settings.show_replies": "Vis svar",
"home.explore_prompt.body": "Dit hjemmefeed vil have en blanding af indlæg fra de hashtags, du har valgt at følge, de personer, du har valgt at følge, og de indlæg, de booster. Hvis her virker for stille, kan du prøve:",
"home.explore_prompt.title": "Dette er din hjemmebase i Mastodon.",
"home.hide_announcements": "Skjul bekendtgørelser", "home.hide_announcements": "Skjul bekendtgørelser",
"home.pending_critical_update.body": "Opdater din Mastodon-server snarest muligt!", "home.pending_critical_update.body": "Opdater din Mastodon-server snarest muligt!",
"home.pending_critical_update.link": "Se opdateringer", "home.pending_critical_update.link": "Se opdateringer",

View File

@ -145,15 +145,13 @@
"compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Andere können dir folgen und deine Beiträge sehen, die nur für Follower bestimmt sind.", "compose_form.lock_disclaimer": "Dein Profil ist nicht {locked}. Andere können dir folgen und deine Beiträge sehen, die nur für Follower bestimmt sind.",
"compose_form.lock_disclaimer.lock": "geschützt", "compose_form.lock_disclaimer.lock": "geschützt",
"compose_form.placeholder": "Was gibts Neues?", "compose_form.placeholder": "Was gibts Neues?",
"compose_form.poll.add_option": "Auswahl hinzufügen",
"compose_form.poll.duration": "Umfragedauer", "compose_form.poll.duration": "Umfragedauer",
"compose_form.poll.multiple": "Mehrfachauswahl", "compose_form.poll.multiple": "Mul­ti­ple-Choice",
"compose_form.poll.option_placeholder": "{number}. Auswahlmöglichkeit", "compose_form.poll.option_placeholder": "Option {number}",
"compose_form.poll.remove_option": "Dieses Auswahlfeld entfernen",
"compose_form.poll.single": "Einfachauswahl", "compose_form.poll.single": "Einfachauswahl",
"compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben", "compose_form.poll.switch_to_multiple": "Mehrfachauswahl erlauben",
"compose_form.poll.switch_to_single": "Nur Einfachauswahl erlauben", "compose_form.poll.switch_to_single": "Nur Einfachauswahl erlauben",
"compose_form.poll.type": "Art", "compose_form.poll.type": "Stil",
"compose_form.publish": "Veröffentlichen", "compose_form.publish": "Veröffentlichen",
"compose_form.publish_form": "Neuer Beitrag", "compose_form.publish_form": "Neuer Beitrag",
"compose_form.reply": "Antworten", "compose_form.reply": "Antworten",
@ -279,6 +277,17 @@
"follow_request.authorize": "Genehmigen", "follow_request.authorize": "Genehmigen",
"follow_request.reject": "Ablehnen", "follow_request.reject": "Ablehnen",
"follow_requests.unlocked_explanation": "Auch wenn dein Konto öffentlich bzw. nicht geschützt ist, haben die Moderator*innen von {domain} gedacht, dass du diesen Follower lieber manuell bestätigen solltest.", "follow_requests.unlocked_explanation": "Auch wenn dein Konto öffentlich bzw. nicht geschützt ist, haben die Moderator*innen von {domain} gedacht, dass du diesen Follower lieber manuell bestätigen solltest.",
"follow_suggestions.curated_suggestion": "Vom Server empfohlen",
"follow_suggestions.dismiss": "Nicht mehr anzeigen",
"follow_suggestions.hints.featured": "Dieses Profil wurde vom {domain}-Team ausgewählt.",
"follow_suggestions.hints.friends_of_friends": "Dieses Profil ist bei deinen Followern beliebt.",
"follow_suggestions.hints.most_followed": "Dieses Profil wird von den meisten auf {domain} gefolgt.",
"follow_suggestions.hints.most_interactions": "Dieses Profil erhielt auf {domain} in letzter Zeit viel Aufmerksamkeit.",
"follow_suggestions.hints.similar_to_recently_followed": "Dieses Profil ähnelt den Profilen, denen du in letzter Zeit gefolgt hast.",
"follow_suggestions.personalized_suggestion": "Persönliche Empfehlung",
"follow_suggestions.popular_suggestion": "Beliebte Empfehlung",
"follow_suggestions.view_all": "Alle anzeigen",
"follow_suggestions.who_to_follow": "Empfohlene Profile",
"followed_tags": "Gefolgte Hashtags", "followed_tags": "Gefolgte Hashtags",
"footer.about": "Über", "footer.about": "Über",
"footer.directory": "Profilverzeichnis", "footer.directory": "Profilverzeichnis",
@ -305,13 +314,9 @@
"hashtag.follow": "Hashtag folgen", "hashtag.follow": "Hashtag folgen",
"hashtag.unfollow": "Hashtag entfolgen", "hashtag.unfollow": "Hashtag entfolgen",
"hashtags.and_other": "… und {count, plural, one{# weiterer} other {# weitere}}", "hashtags.and_other": "… und {count, plural, one{# weiterer} other {# weitere}}",
"home.actions.go_to_explore": "Trends ansehen",
"home.actions.go_to_suggestions": "Profile zum Folgen finden",
"home.column_settings.basic": "Allgemein", "home.column_settings.basic": "Allgemein",
"home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen", "home.column_settings.show_reblogs": "Geteilte Beiträge anzeigen",
"home.column_settings.show_replies": "Antworten anzeigen", "home.column_settings.show_replies": "Antworten anzeigen",
"home.explore_prompt.body": "Deine Startseite wird eine Mischung aus Beiträgen mit Hashtags und den Profilen, denen du folgst sowie den Beiträgen, die sie teilen, enthalten. Sollte es sich zu still anfühlen:",
"home.explore_prompt.title": "Das ist dein Zuhause bei Mastodon.",
"home.hide_announcements": "Ankündigungen ausblenden", "home.hide_announcements": "Ankündigungen ausblenden",
"home.pending_critical_update.body": "Bitte aktualisiere deinen Mastodon-Server so schnell wie möglich!", "home.pending_critical_update.body": "Bitte aktualisiere deinen Mastodon-Server so schnell wie möglich!",
"home.pending_critical_update.link": "Updates ansehen", "home.pending_critical_update.link": "Updates ansehen",
@ -528,7 +533,7 @@
"privacy.direct.short": "Bestimmte Profile", "privacy.direct.short": "Bestimmte Profile",
"privacy.private.long": "Nur deine Follower", "privacy.private.long": "Nur deine Follower",
"privacy.private.short": "Follower", "privacy.private.short": "Follower",
"privacy.public.long": "Alle auf und außerhalb von Mastodon", "privacy.public.long": "Alle in und außerhalb von Mastodon",
"privacy.public.short": "Öffentlich", "privacy.public.short": "Öffentlich",
"privacy.unlisted.additional": "Das Verhalten ist wie bei „Öffentlich“, jedoch erscheint dieser Beitrag nicht in „Live-Feeds“, „Erkunden“, Hashtags oder über die Mastodon-Suchfunktion selbst wenn du das in den Einstellungen aktiviert hast.", "privacy.unlisted.additional": "Das Verhalten ist wie bei „Öffentlich“, jedoch erscheint dieser Beitrag nicht in „Live-Feeds“, „Erkunden“, Hashtags oder über die Mastodon-Suchfunktion selbst wenn du das in den Einstellungen aktiviert hast.",
"privacy.unlisted.long": "Weniger im Algorithmus berücksichtigt", "privacy.unlisted.long": "Weniger im Algorithmus berücksichtigt",

View File

@ -140,11 +140,9 @@
"compose_form.lock_disclaimer": "Ο λογαριασμός σου δεν είναι {locked}. Οποιοσδήποτε μπορεί να σε ακολουθήσει για να δει τις δημοσιεύσεις σου προς τους ακολούθους σου.", "compose_form.lock_disclaimer": "Ο λογαριασμός σου δεν είναι {locked}. Οποιοσδήποτε μπορεί να σε ακολουθήσει για να δει τις δημοσιεύσεις σου προς τους ακολούθους σου.",
"compose_form.lock_disclaimer.lock": "κλειδωμένο", "compose_form.lock_disclaimer.lock": "κλειδωμένο",
"compose_form.placeholder": "Τι σκέφτεσαι;", "compose_form.placeholder": "Τι σκέφτεσαι;",
"compose_form.poll.add_option": "Προσθήκη επιλογής",
"compose_form.poll.duration": "Διάρκεια δημοσκόπησης", "compose_form.poll.duration": "Διάρκεια δημοσκόπησης",
"compose_form.poll.multiple": "Πολλαπλή επιλογή", "compose_form.poll.multiple": "Πολλαπλή επιλογή",
"compose_form.poll.option_placeholder": "Επιλογή {number}", "compose_form.poll.option_placeholder": "Επιλογή {number}",
"compose_form.poll.remove_option": "Αφαίρεση επιλογής",
"compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές", "compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές",
"compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή", "compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή",
"compose_form.poll.type": "Στυλ", "compose_form.poll.type": "Στυλ",
@ -291,12 +289,9 @@
"hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα", "hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα",
"hashtag.follow": "Παρακολούθηση ετικέτας", "hashtag.follow": "Παρακολούθηση ετικέτας",
"hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας", "hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας",
"home.actions.go_to_suggestions": "Βρείτε άτομα για να ακολουθήσετε",
"home.column_settings.basic": "Βασικές ρυθμίσεις", "home.column_settings.basic": "Βασικές ρυθμίσεις",
"home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων", "home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων",
"home.column_settings.show_replies": "Εμφάνιση απαντήσεων", "home.column_settings.show_replies": "Εμφάνιση απαντήσεων",
"home.explore_prompt.body": "Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. If that feels too quiet, you may want to:\nΗ τροφοδοσία της αρχικής σελίδας σας είναι ένα μίγμα από αναρτήσεις με τις ετικέτες και τα άτομα που επιλέξατε να ακολουθείτε, και τις αναρτήσεις που προωθούν. Εάν αυτό σας φαίνεται πολύ ήσυχο, μπορεί να θέλετε:",
"home.explore_prompt.title": "Αυτό είναι το σπίτι σας στο Mastodon.",
"home.hide_announcements": "Απόκρυψη ανακοινώσεων", "home.hide_announcements": "Απόκρυψη ανακοινώσεων",
"home.pending_critical_update.link": "Δείτε ενημερώσεις", "home.pending_critical_update.link": "Δείτε ενημερώσεις",
"home.pending_critical_update.title": "Κρίσιμη ενημέρωση ασφαλείας διαθέσιμη!", "home.pending_critical_update.title": "Κρίσιμη ενημέρωση ασφαλείας διαθέσιμη!",

View File

@ -32,6 +32,7 @@
"account.featured_tags.last_status_never": "No posts", "account.featured_tags.last_status_never": "No posts",
"account.featured_tags.title": "{name}'s featured hashtags", "account.featured_tags.title": "{name}'s featured hashtags",
"account.follow": "Follow", "account.follow": "Follow",
"account.follow_back": "Follow back",
"account.followers": "Followers", "account.followers": "Followers",
"account.followers.empty": "No one follows this user yet.", "account.followers.empty": "No one follows this user yet.",
"account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}", "account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
@ -52,6 +53,7 @@
"account.mute_notifications_short": "Mute notifications", "account.mute_notifications_short": "Mute notifications",
"account.mute_short": "Mute", "account.mute_short": "Mute",
"account.muted": "Muted", "account.muted": "Muted",
"account.mutual": "Mutual",
"account.no_bio": "No description provided.", "account.no_bio": "No description provided.",
"account.open_original_page": "Open original page", "account.open_original_page": "Open original page",
"account.posts": "Posts", "account.posts": "Posts",
@ -144,11 +146,19 @@
"compose_form.lock_disclaimer.lock": "locked", "compose_form.lock_disclaimer.lock": "locked",
"compose_form.placeholder": "What's on your mind?", "compose_form.placeholder": "What's on your mind?",
"compose_form.poll.duration": "Poll duration", "compose_form.poll.duration": "Poll duration",
"compose_form.poll.multiple": "Multiple choice",
"compose_form.poll.option_placeholder": "Option {number}",
"compose_form.poll.single": "Pick one",
"compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices",
"compose_form.poll.switch_to_single": "Change poll to allow for a single choice", "compose_form.poll.switch_to_single": "Change poll to allow for a single choice",
"compose_form.poll.type": "Style",
"compose_form.publish": "Post",
"compose_form.publish_form": "New post", "compose_form.publish_form": "New post",
"compose_form.reply": "Reply",
"compose_form.save_changes": "Update",
"compose_form.spoiler.marked": "Remove content warning", "compose_form.spoiler.marked": "Remove content warning",
"compose_form.spoiler.unmarked": "Add content warning", "compose_form.spoiler.unmarked": "Add content warning",
"compose_form.spoiler_placeholder": "Content warning (optional)",
"confirmation_modal.cancel": "Cancel", "confirmation_modal.cancel": "Cancel",
"confirmations.block.block_and_report": "Block & Report", "confirmations.block.block_and_report": "Block & Report",
"confirmations.block.confirm": "Block", "confirmations.block.confirm": "Block",
@ -267,6 +277,11 @@
"follow_request.authorize": "Authorise", "follow_request.authorize": "Authorise",
"follow_request.reject": "Reject", "follow_request.reject": "Reject",
"follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.",
"follow_suggestions.dismiss": "Don't show again",
"follow_suggestions.personalized_suggestion": "Personalised suggestion",
"follow_suggestions.popular_suggestion": "Popular suggestion",
"follow_suggestions.view_all": "View all",
"follow_suggestions.who_to_follow": "Who to follow",
"followed_tags": "Followed hashtags", "followed_tags": "Followed hashtags",
"footer.about": "About", "footer.about": "About",
"footer.directory": "Profiles directory", "footer.directory": "Profiles directory",
@ -292,14 +307,10 @@
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} post} other {{counter} posts}} today", "hashtag.counter_by_uses_today": "{count, plural, one {{counter} post} other {{counter} posts}} today",
"hashtag.follow": "Follow hashtag", "hashtag.follow": "Follow hashtag",
"hashtag.unfollow": "Unfollow hashtag", "hashtag.unfollow": "Unfollow hashtag",
"hashtags.and_other": "…and {count, plural, one {}other {# more}}", "hashtags.and_other": "…and {count, plural, one {one more} other {# more}}",
"home.actions.go_to_explore": "See what's trending",
"home.actions.go_to_suggestions": "Find people to follow",
"home.column_settings.basic": "Basic", "home.column_settings.basic": "Basic",
"home.column_settings.show_reblogs": "Show boosts", "home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies", "home.column_settings.show_replies": "Show replies",
"home.explore_prompt.body": "Your home feed will have a mix of posts from the hashtags you've chosen to follow, the people you've chosen to follow, and the posts they boost. If that feels too quiet, you may want to:",
"home.explore_prompt.title": "This is your home base within Mastodon.",
"home.hide_announcements": "Hide announcements", "home.hide_announcements": "Hide announcements",
"home.pending_critical_update.body": "Please update your Mastodon server as soon as possible!", "home.pending_critical_update.body": "Please update your Mastodon server as soon as possible!",
"home.pending_critical_update.link": "See updates", "home.pending_critical_update.link": "See updates",
@ -512,7 +523,15 @@
"poll_button.add_poll": "Add a poll", "poll_button.add_poll": "Add a poll",
"poll_button.remove_poll": "Remove poll", "poll_button.remove_poll": "Remove poll",
"privacy.change": "Change post privacy", "privacy.change": "Change post privacy",
"privacy.direct.long": "Everyone mentioned in the post",
"privacy.direct.short": "Specific people",
"privacy.private.long": "Only your followers",
"privacy.private.short": "Followers",
"privacy.public.long": "Anyone on and off Mastodon",
"privacy.public.short": "Public", "privacy.public.short": "Public",
"privacy.unlisted.additional": "This behaves exactly like public, except the post will not appear in live feeds or hashtags, explore, or Mastodon search, even if you are opted-in account-wide.",
"privacy.unlisted.long": "Fewer algorithmic fanfares",
"privacy.unlisted.short": "Quiet public",
"privacy_policy.last_updated": "Last updated {date}", "privacy_policy.last_updated": "Last updated {date}",
"privacy_policy.title": "Privacy Policy", "privacy_policy.title": "Privacy Policy",
"recommended": "Recommended", "recommended": "Recommended",
@ -530,7 +549,9 @@
"relative_time.minutes": "{number}m", "relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s", "relative_time.seconds": "{number}s",
"relative_time.today": "today", "relative_time.today": "today",
"reply_indicator.attachments": "{count, plural, one {# attachment} other {# attachments}}",
"reply_indicator.cancel": "Cancel", "reply_indicator.cancel": "Cancel",
"reply_indicator.poll": "Poll",
"report.block": "Block", "report.block": "Block",
"report.block_explanation": "You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.", "report.block_explanation": "You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.",
"report.categories.legal": "Legal", "report.categories.legal": "Legal",

View File

@ -277,8 +277,13 @@
"follow_request.authorize": "Authorize", "follow_request.authorize": "Authorize",
"follow_request.reject": "Reject", "follow_request.reject": "Reject",
"follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.", "follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.",
"follow_suggestions.curated_suggestion": "Editors' Choice", "follow_suggestions.curated_suggestion": "Staff pick",
"follow_suggestions.dismiss": "Don't show again", "follow_suggestions.dismiss": "Don't show again",
"follow_suggestions.hints.featured": "This profile has been hand-picked by the {domain} team.",
"follow_suggestions.hints.friends_of_friends": "This profile is popular among the people you follow.",
"follow_suggestions.hints.most_followed": "This profile is one of the most followed on {domain}.",
"follow_suggestions.hints.most_interactions": "This profile has been recently getting a lot of attention on {domain}.",
"follow_suggestions.hints.similar_to_recently_followed": "This profile is similar to the profiles you have most recently followed.",
"follow_suggestions.personalized_suggestion": "Personalized suggestion", "follow_suggestions.personalized_suggestion": "Personalized suggestion",
"follow_suggestions.popular_suggestion": "Popular suggestion", "follow_suggestions.popular_suggestion": "Popular suggestion",
"follow_suggestions.view_all": "View all", "follow_suggestions.view_all": "View all",

View File

@ -115,7 +115,7 @@
"column.directory": "Foliumi la profilojn", "column.directory": "Foliumi la profilojn",
"column.domain_blocks": "Blokitaj domajnoj", "column.domain_blocks": "Blokitaj domajnoj",
"column.favourites": "Stelumoj", "column.favourites": "Stelumoj",
"column.firehose": "Vivantaj fluoj", "column.firehose": "Rektaj fluoj",
"column.follow_requests": "Petoj de sekvado", "column.follow_requests": "Petoj de sekvado",
"column.home": "Hejmo", "column.home": "Hejmo",
"column.lists": "Listoj", "column.lists": "Listoj",
@ -295,13 +295,9 @@
"hashtag.follow": "Sekvi la kradvorton", "hashtag.follow": "Sekvi la kradvorton",
"hashtag.unfollow": "Ne plu sekvi la kradvorton", "hashtag.unfollow": "Ne plu sekvi la kradvorton",
"hashtags.and_other": "…kaj {count, plural,other {# pli}}", "hashtags.and_other": "…kaj {count, plural,other {# pli}}",
"home.actions.go_to_explore": "Vidi kio populariĝas",
"home.actions.go_to_suggestions": "Trovi homojn por sekvi",
"home.column_settings.basic": "Bazaj agordoj", "home.column_settings.basic": "Bazaj agordoj",
"home.column_settings.show_reblogs": "Montri diskonigojn", "home.column_settings.show_reblogs": "Montri diskonigojn",
"home.column_settings.show_replies": "Montri respondojn", "home.column_settings.show_replies": "Montri respondojn",
"home.explore_prompt.body": "Via hejmafiŝaro havos miksitajn afiŝojn de kradvortoj kiujn vi elektis sekvi, personoj kiujn vi elektis sekvi, kaj afiŝoj kiujn ili suprenigis.",
"home.explore_prompt.title": "Ĉi tio estas via hejma paĝo en Mastodon.",
"home.hide_announcements": "Kaŝi la anoncojn", "home.hide_announcements": "Kaŝi la anoncojn",
"home.pending_critical_update.body": "Ĝisdatigu vian servilon de Mastodon kiel eble plej baldau!", "home.pending_critical_update.body": "Ĝisdatigu vian servilon de Mastodon kiel eble plej baldau!",
"home.pending_critical_update.link": "Vidi ĝisdatigojn", "home.pending_critical_update.link": "Vidi ĝisdatigojn",

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