Compare commits
210 Commits
features/4
...
features/m
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f92b6e931 | |||
| 2aa30a875e | |||
| 5b1eb8f8d7 | |||
| 1cd3856fb8 | |||
| 59e77b2e80 | |||
| f2161a6340 | |||
|
|
1cb74eeec0 | ||
|
|
bbf6cb66f6 | ||
|
|
aca691726b | ||
|
|
cfa71a4d16 | ||
|
|
25ffe0af45 | ||
|
|
bba4118ddd | ||
|
|
b0064ddda7 | ||
|
|
baa23738a8 | ||
|
|
45f71e3954 | ||
|
|
82e2370f5f | ||
|
|
a6ed148769 | ||
|
|
9d8dfeb5fb | ||
|
|
5152dd869e | ||
|
|
a9496882fc | ||
|
|
b71904816a | ||
|
|
491dd97642 | ||
|
|
ebe2086087 | ||
|
|
e9b0f0c314 | ||
|
|
7c7dfe7de3 | ||
|
|
6342ddd698 | ||
|
|
f70905f127 | ||
|
|
a69fe534e3 | ||
|
|
d1602c017d | ||
|
|
ab2ef63a03 | ||
|
|
fa1c3a0915 | ||
|
|
96d5c44db2 | ||
|
|
449fcf1ae7 | ||
|
|
53a4648db1 | ||
|
|
006aa4e35a | ||
|
|
c63567a214 | ||
|
|
638861b2a3 | ||
|
|
aed60df80e | ||
|
|
bcc0860100 | ||
|
|
df4ed60331 | ||
|
|
38d0292281 | ||
|
|
d48d824d9a | ||
|
|
581f14e56f | ||
|
|
2751acb6cd | ||
|
|
08342ad40c | ||
|
|
8f61e32569 | ||
|
|
b73932461f | ||
|
|
5f19e7e799 | ||
|
|
1f648fdf1a | ||
|
|
fd2b6c29c6 | ||
|
|
36fd47ac57 | ||
|
|
937dad1ee6 | ||
|
|
9a2b9d1484 | ||
|
|
0ef44ee720 | ||
|
|
e1cee84e58 | ||
|
|
bde4df6be6 | ||
|
|
785e2f9399 | ||
|
|
5d9d0d174a | ||
|
|
6e4c1e172b | ||
|
|
b8b2f20b16 | ||
|
|
64f9939e39 | ||
|
|
86627ea2e4 | ||
|
|
72b0c9e20b | ||
|
|
c645490d55 | ||
|
|
ad16362efe | ||
|
|
fe6c055f35 | ||
|
|
63f4ea055a | ||
|
|
245064bb98 | ||
|
|
96ddf1d482 | ||
|
|
cfadb87077 | ||
|
|
1d9d14b8de | ||
|
|
1946e171e6 | ||
|
|
3454fcbd71 | ||
|
|
a316c0e38d | ||
|
|
117b507df5 | ||
|
|
1690fb39e6 | ||
|
|
bba488c189 | ||
|
|
e140d05a6a | ||
|
|
5f21a1f5a3 | ||
|
|
9fee5e8526 | ||
|
|
a8ee6fdd62 | ||
|
|
a9f9b0097b | ||
|
|
4b7f04e3ea | ||
|
|
1c93d625c6 | ||
|
|
ed4939296a | ||
|
|
1df2ffc3ee | ||
|
|
fc4f823464 | ||
|
|
d4d0565b0f | ||
|
|
844aa59bdf | ||
|
|
bbbbf00084 | ||
|
|
8e8e0f104f | ||
|
|
b31af34c97 | ||
|
|
68eaa804c9 | ||
|
|
554e2a019e | ||
|
|
46142cdbdd | ||
|
|
e8b66a0525 | ||
|
|
476a043fc5 | ||
|
|
5de1ce23c3 | ||
|
|
e25d9dfb25 | ||
|
|
b244e5cb81 | ||
|
|
819ede190e | ||
|
|
cf0d6bef8b | ||
|
|
58918844a9 | ||
|
|
6482948547 | ||
|
|
8125dae5a8 | ||
|
|
c07028b2fa | ||
|
|
ca8fbda5d0 | ||
|
|
a9e91eb955 | ||
|
|
67ec192d7d | ||
|
|
d4db1c497b | ||
|
|
13840d685c | ||
|
|
15437e4ad9 | ||
|
|
5271131658 | ||
|
|
52986f35b8 | ||
|
|
2a362d62a8 | ||
|
|
eff447a455 | ||
|
|
79b4b94f3a | ||
|
|
95da28d201 | ||
|
|
dbafec88e5 | ||
|
|
b2133fee5f | ||
|
|
7efc33b909 | ||
|
|
17052714a2 | ||
|
|
2912829411 | ||
|
|
eeabf9af72 | ||
|
|
da50217b88 | ||
|
|
492e25da06 | ||
|
|
aaa58d4807 | ||
|
|
90ccf7beb2 | ||
|
|
7ee93b7431 | ||
|
|
1e0b0a3486 | ||
|
|
64300e0fe3 | ||
|
|
2f19ddd1fa | ||
|
|
0df86d77fd | ||
|
|
93a5b3f9df | ||
|
|
cf42eba0f9 | ||
|
|
69e61fff38 | ||
|
|
2d6ab44556 | ||
|
|
978fdc71ca | ||
|
|
0877f6fda4 | ||
|
|
e8cc98977d | ||
|
|
577520b637 | ||
|
|
df7acdcee5 | ||
|
|
4fb7f611de | ||
|
|
dedefdc303 | ||
|
|
4cf07ed78c | ||
|
|
a31427a629 | ||
|
|
0bec5c0755 | ||
|
|
62028b1b1b | ||
|
|
90f4b8d53a | ||
|
|
9ce914cc89 | ||
|
|
66dda7c762 | ||
|
|
779d987fbc | ||
|
|
a2d8aa1583 | ||
|
|
5ca45403e2 | ||
|
|
586b4faf61 | ||
|
|
916aeb574d | ||
|
|
f00ba02653 | ||
|
|
86500e3312 | ||
| 14625836de | |||
| 850d9bf253 | |||
| fdf24bd1ce | |||
| ee4b5c279a | |||
| f2f39eebdf | |||
| 8e8d121659 | |||
| c4712ed22c | |||
| f16b068156 | |||
|
|
1666b19559 | ||
| a0474b9a53 | |||
|
|
4b2272c34e | ||
|
|
d1369ca959 | ||
| 03e6239278 | |||
| 2b2851b05b | |||
| 05611d249b | |||
| 0bf9f469c5 | |||
|
|
c81b901f08 | ||
|
|
7cf177d11e | ||
|
|
96220dc2f4 | ||
|
|
bcb6f80ac3 | ||
|
|
5c786b4868 | ||
|
|
93e61bf392 | ||
|
|
3f5142c2f8 | ||
| 1f82788629 | |||
| 3ad062a886 | |||
| 57eed5696e | |||
|
|
0190688af0 | ||
|
|
b9f8e7731b | ||
|
|
fed10012e4 | ||
|
|
f8ca193b89 | ||
|
|
d61e7dbdc1 | ||
|
|
fb1c2abc7e | ||
|
|
5fc29d03dd | ||
|
|
2a912a0698 | ||
|
|
5baee4e1ca | ||
|
|
3b5d2b3b35 | ||
|
|
837c572d8b | ||
|
|
d7ce457a3f | ||
|
|
0ea43929b7 | ||
|
|
90b9b5d893 | ||
|
|
546c2417e9 | ||
|
|
68c7def8d3 | ||
|
|
432b68c5d1 | ||
|
|
5b9031f36e | ||
|
|
88e9b8d4fa | ||
|
|
3747409526 | ||
|
|
ba989d9db6 | ||
|
|
53e4c6adff | ||
|
|
471540d9aa | ||
|
|
dca26cc504 | ||
|
|
b88e3942cc | ||
|
|
e443f3c90a |
@@ -70,7 +70,7 @@ services:
|
||||
hard: -1
|
||||
|
||||
libretranslate:
|
||||
image: libretranslate/libretranslate:v1.5.4
|
||||
image: libretranslate/libretranslate:v1.5.5
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- lt-data:/home/libretranslate/.local
|
||||
|
||||
4
.github/workflows/build-security.yml
vendored
4
.github/workflows/build-security.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
tags: |
|
||||
type=raw,value=edge
|
||||
type=raw,value=nightly
|
||||
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
||||
type=raw,value=${{ needs.compute-suffix.outputs.prerelease }}
|
||||
secrets: inherit
|
||||
|
||||
build-image-streaming:
|
||||
@@ -60,5 +60,5 @@ jobs:
|
||||
tags: |
|
||||
type=raw,value=edge
|
||||
type=raw,value=nightly
|
||||
type=schedule,pattern=${{ needs.compute-suffix.outputs.prerelease }}
|
||||
type=raw,value=${{ needs.compute-suffix.outputs.prerelease }}
|
||||
secrets: inherit
|
||||
|
||||
2
.github/workflows/crowdin-download.yml
vendored
2
.github/workflows/crowdin-download.yml
vendored
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
# Create or update the pull request
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5.0.2
|
||||
uses: peter-evans/create-pull-request@v6.0.0
|
||||
with:
|
||||
commit-message: 'New Crowdin translations'
|
||||
title: 'New Crowdin Translations (automated)'
|
||||
|
||||
6
.github/workflows/test-ruby.yml
vendored
6
.github/workflows/test-ruby.yml
vendored
@@ -139,7 +139,7 @@ jobs:
|
||||
|
||||
- name: Upload coverage reports to Codecov
|
||||
if: matrix.ruby-version == '.ruby-version'
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
files: coverage/lcov/mastodon.lcov
|
||||
|
||||
@@ -224,7 +224,7 @@ jobs:
|
||||
if: failure()
|
||||
with:
|
||||
name: e2e-screenshots
|
||||
path: tmp/screenshots/
|
||||
path: tmp/capybara/
|
||||
|
||||
test-search:
|
||||
name: Elastic Search integration testing
|
||||
@@ -328,4 +328,4 @@ jobs:
|
||||
if: failure()
|
||||
with:
|
||||
name: test-search-screenshots
|
||||
path: tmp/screenshots/
|
||||
path: tmp/capybara/
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
yarn lint-staged
|
||||
|
||||
16
.rubocop.yml
16
.rubocop.yml
@@ -96,12 +96,6 @@ Rails/FilePath:
|
||||
Rails/HttpStatus:
|
||||
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
|
||||
# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter
|
||||
Rails/LexicallyScopedActionFilter:
|
||||
@@ -134,6 +128,11 @@ Rails/UnusedIgnoredColumns:
|
||||
Rails/NegateInclude:
|
||||
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
|
||||
# https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#rspecfilepath
|
||||
RSpec/FilePath:
|
||||
@@ -211,11 +210,6 @@ Style/RedundantBegin:
|
||||
Style/RescueStandardError:
|
||||
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
|
||||
# https://docs.rubocop.org/rubocop/cops_style.html#stylesymbolarray
|
||||
Style/SymbolArray:
|
||||
|
||||
@@ -36,10 +36,10 @@ Metrics/PerceivedComplexity:
|
||||
|
||||
# Configuration parameters: CountAsOne.
|
||||
RSpec/ExampleLength:
|
||||
Max: 22
|
||||
Max: 20 # Override default of 5
|
||||
|
||||
RSpec/MultipleExpectations:
|
||||
Max: 8
|
||||
Max: 7
|
||||
|
||||
# Configuration parameters: AllowSubject.
|
||||
RSpec/MultipleMemoizedHelpers:
|
||||
|
||||
95
CHANGELOG.md
95
CHANGELOG.md
@@ -2,6 +2,101 @@
|
||||
|
||||
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
|
||||
|
||||
### Added
|
||||
|
||||
4
Gemfile
4
Gemfile
@@ -26,7 +26,7 @@ gem 'blurhash', '~> 0.1'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.10'
|
||||
gem 'addressable', '~> 2.8'
|
||||
gem 'bootsnap', '~> 1.17.0', require: false
|
||||
gem 'bootsnap', '~> 1.18.0', require: false
|
||||
gem 'browser'
|
||||
gem 'charlock_holmes', '~> 0.7.7'
|
||||
gem 'chewy', '~> 7.3'
|
||||
@@ -63,7 +63,7 @@ gem 'kaminari', '~> 1.2'
|
||||
gem 'link_header', '~> 0.0'
|
||||
gem 'mime-types', '~> 3.5.0', require: 'mime/types/columnar'
|
||||
gem 'nokogiri', '~> 1.15'
|
||||
gem 'nsa', github: 'jhawthorn/nsa', ref: 'e020fcc3a54d993ab45b7194d89ab720296c111b'
|
||||
gem 'nsa'
|
||||
gem 'oj', '~> 3.14'
|
||||
gem 'ox', '~> 2.14'
|
||||
gem 'parslet'
|
||||
|
||||
161
Gemfile.lock
161
Gemfile.lock
@@ -7,49 +7,38 @@ GIT
|
||||
hkdf (~> 0.2)
|
||||
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
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actioncable (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
zeitwerk (~> 2.6)
|
||||
actionmailbox (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
activejob (= 7.1.3)
|
||||
activerecord (= 7.1.3)
|
||||
activestorage (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actionmailbox (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
actionview (= 7.1.3)
|
||||
activejob (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actionmailer (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.2)
|
||||
actionpack (7.1.3)
|
||||
actionview (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actionpack (7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
racc
|
||||
rack (>= 2.2.4)
|
||||
@@ -57,15 +46,15 @@ GEM
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.2)
|
||||
rails-html-sanitizer (~> 1.6)
|
||||
actiontext (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
activerecord (= 7.1.3)
|
||||
activestorage (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actiontext (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
actionview (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.11)
|
||||
rails-dom-testing (~> 2.2)
|
||||
@@ -75,22 +64,22 @@ GEM
|
||||
activemodel (>= 4.1)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
activejob (7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
activejob (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
activerecord (7.1.3)
|
||||
activemodel (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
activemodel (7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
activerecord (7.1.3.2)
|
||||
activemodel (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
timeout (>= 0.4.0)
|
||||
activestorage (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
activejob (= 7.1.3)
|
||||
activerecord (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
activestorage (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
marcel (~> 1.0)
|
||||
activesupport (7.1.3)
|
||||
activesupport (7.1.3.2)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
@@ -155,9 +144,9 @@ GEM
|
||||
binding_of_caller (1.0.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
blurhash (0.1.7)
|
||||
bootsnap (1.17.1)
|
||||
bootsnap (1.18.3)
|
||||
msgpack (~> 1.2)
|
||||
brakeman (6.1.1)
|
||||
brakeman (6.1.2)
|
||||
racc
|
||||
browser (5.3.1)
|
||||
brpoplpush-redis_script (0.1.3)
|
||||
@@ -193,7 +182,8 @@ GEM
|
||||
cose (1.3.0)
|
||||
cbor (~> 0.5.9)
|
||||
openssl-signature_algorithm (~> 1.0)
|
||||
crack (0.4.5)
|
||||
crack (0.4.6)
|
||||
bigdecimal
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
css_parser (1.14.0)
|
||||
@@ -229,7 +219,7 @@ GEM
|
||||
docile (1.4.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
doorkeeper (5.6.8)
|
||||
doorkeeper (5.6.9)
|
||||
railties (>= 5)
|
||||
dotenv (2.8.1)
|
||||
dotenv-rails (2.8.1)
|
||||
@@ -319,13 +309,13 @@ GEM
|
||||
activesupport (>= 5.1)
|
||||
haml (>= 4.0.6)
|
||||
railties (>= 5.1)
|
||||
haml_lint (0.55.0)
|
||||
haml_lint (0.57.0)
|
||||
haml (>= 5.0)
|
||||
parallel (~> 1.10)
|
||||
rainbow
|
||||
rubocop (>= 1.0)
|
||||
sysexits (~> 1.1)
|
||||
hashdiff (1.0.1)
|
||||
hashdiff (1.1.0)
|
||||
hashie (5.0.0)
|
||||
hcaptcha (7.1.0)
|
||||
json
|
||||
@@ -361,7 +351,7 @@ GEM
|
||||
terminal-table (>= 1.5.1)
|
||||
idn-ruby (0.1.5)
|
||||
io-console (0.7.2)
|
||||
irb (1.11.1)
|
||||
irb (1.11.2)
|
||||
rdoc
|
||||
reline (>= 0.4.2)
|
||||
jmespath (1.6.2)
|
||||
@@ -454,7 +444,7 @@ GEM
|
||||
uri
|
||||
net-http-persistent (4.0.2)
|
||||
connection_pool (~> 2.2)
|
||||
net-imap (0.4.9.1)
|
||||
net-imap (0.4.10)
|
||||
date
|
||||
net-protocol
|
||||
net-ldap (0.19.0)
|
||||
@@ -465,9 +455,14 @@ GEM
|
||||
net-smtp (0.4.0.1)
|
||||
net-protocol
|
||||
nio4r (2.5.9)
|
||||
nokogiri (1.16.0)
|
||||
nokogiri (1.16.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
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)
|
||||
bigdecimal (>= 3.0)
|
||||
omniauth (2.1.1)
|
||||
@@ -510,8 +505,8 @@ GEM
|
||||
parslet (2.0.0)
|
||||
pastel (0.8.0)
|
||||
tty-color (~> 0.5)
|
||||
pg (1.5.4)
|
||||
pghero (3.4.0)
|
||||
pg (1.5.5)
|
||||
pghero (3.4.1)
|
||||
activerecord (>= 6)
|
||||
posix-spawn (0.3.15)
|
||||
premailer (1.21.0)
|
||||
@@ -537,7 +532,7 @@ GEM
|
||||
activesupport (>= 3.0.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.7.3)
|
||||
rack (2.2.8)
|
||||
rack (2.2.8.1)
|
||||
rack-attack (6.7.0)
|
||||
rack (>= 1.0, < 4)
|
||||
rack-cors (2.0.1)
|
||||
@@ -559,20 +554,20 @@ GEM
|
||||
rackup (1.0.0)
|
||||
rack (< 3)
|
||||
webrick
|
||||
rails (7.1.3)
|
||||
actioncable (= 7.1.3)
|
||||
actionmailbox (= 7.1.3)
|
||||
actionmailer (= 7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
actiontext (= 7.1.3)
|
||||
actionview (= 7.1.3)
|
||||
activejob (= 7.1.3)
|
||||
activemodel (= 7.1.3)
|
||||
activerecord (= 7.1.3)
|
||||
activestorage (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
rails (7.1.3.2)
|
||||
actioncable (= 7.1.3.2)
|
||||
actionmailbox (= 7.1.3.2)
|
||||
actionmailer (= 7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
actiontext (= 7.1.3.2)
|
||||
actionview (= 7.1.3.2)
|
||||
activejob (= 7.1.3.2)
|
||||
activemodel (= 7.1.3.2)
|
||||
activerecord (= 7.1.3.2)
|
||||
activestorage (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.1.3)
|
||||
railties (= 7.1.3.2)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
@@ -587,9 +582,9 @@ GEM
|
||||
rails-i18n (7.0.8)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
railties (7.1.3)
|
||||
actionpack (= 7.1.3)
|
||||
activesupport (= 7.1.3)
|
||||
railties (7.1.3.2)
|
||||
actionpack (= 7.1.3.2)
|
||||
activesupport (= 7.1.3.2)
|
||||
irb
|
||||
rackup (>= 1.0.0)
|
||||
rake (>= 12.2)
|
||||
@@ -696,7 +691,7 @@ GEM
|
||||
scenic (1.7.0)
|
||||
activerecord (>= 4.0.0)
|
||||
railties (>= 4.0.0)
|
||||
selenium-webdriver (4.17.0)
|
||||
selenium-webdriver (4.18.1)
|
||||
base64 (~> 0.2)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
@@ -712,7 +707,7 @@ GEM
|
||||
rufus-scheduler (~> 3.2)
|
||||
sidekiq (>= 6, < 8)
|
||||
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)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.5)
|
||||
redis (< 5.0)
|
||||
@@ -771,7 +766,7 @@ GEM
|
||||
unf (~> 0.1.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
tzinfo-data (1.2023.4)
|
||||
tzinfo-data (1.2024.1)
|
||||
tzinfo (>= 1.0.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
@@ -798,7 +793,7 @@ GEM
|
||||
webfinger (1.2.0)
|
||||
activesupport
|
||||
httpclient (>= 2.4)
|
||||
webmock (3.19.1)
|
||||
webmock (3.22.0)
|
||||
addressable (>= 2.8.0)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
@@ -816,7 +811,7 @@ GEM
|
||||
xorcist (1.1.3)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.12)
|
||||
zeitwerk (2.6.13)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -829,7 +824,7 @@ DEPENDENCIES
|
||||
better_errors (~> 2.9)
|
||||
binding_of_caller (~> 1.0)
|
||||
blurhash (~> 0.1)
|
||||
bootsnap (~> 1.17.0)
|
||||
bootsnap (~> 1.18.0)
|
||||
brakeman (~> 6.0)
|
||||
browser
|
||||
bundler-audit (~> 0.9)
|
||||
@@ -886,7 +881,7 @@ DEPENDENCIES
|
||||
net-http (~> 0.4.0)
|
||||
net-ldap (~> 0.18)
|
||||
nokogiri (~> 1.15)
|
||||
nsa!
|
||||
nsa
|
||||
oj (~> 3.14)
|
||||
omniauth (~> 2.0)
|
||||
omniauth-cas (~> 3.0.0.beta.1)
|
||||
|
||||
@@ -69,7 +69,7 @@ Mastodon acts as an OAuth2 provider, so 3rd party apps can use the REST and Stre
|
||||
|
||||
- **PostgreSQL** 12+
|
||||
- **Redis** 4+
|
||||
- **Ruby** 2.7+
|
||||
- **Ruby** 3.0+
|
||||
- **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.
|
||||
|
||||
@@ -62,11 +62,10 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
|
||||
return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' || signed_request_account.nil?
|
||||
|
||||
# Re-using the syntax for signature parameters
|
||||
tree = SignatureParamsParser.new.parse(raw_params)
|
||||
params = SignatureParamsTransformer.new.apply(tree)
|
||||
params = SignatureParser.parse(raw_params)
|
||||
|
||||
ActivityPub::PrepareFollowersSynchronizationService.new.call(signed_request_account, params)
|
||||
rescue Parslet::ParseFailed
|
||||
rescue SignatureParser::ParsingError
|
||||
Rails.logger.warn 'Error parsing Collection-Synchronization header'
|
||||
end
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::BaseController < ApplicationController
|
||||
DEFAULT_STATUSES_LIMIT = 20
|
||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||
DEFAULT_STATUSES_LIMIT = 20
|
||||
DEFAULT_ACCOUNTS_LIMIT = 40
|
||||
|
||||
include Api::RateLimitHeaders
|
||||
include Api::AccessTokenTrackingConcern
|
||||
|
||||
@@ -8,9 +8,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||
|
||||
def index
|
||||
cache_if_unauthenticated!
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||
|
||||
@@ -35,6 +35,7 @@ class Api::V1::Admin::ReportsController < Api::BaseController
|
||||
def update
|
||||
authorize @report, :update?
|
||||
@report.update!(report_params)
|
||||
log_action :update, @report
|
||||
render json: @report, serializer: REST::Admin::ReportSerializer
|
||||
end
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ class Api::V1::BookmarksController < Api::BaseController
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||
|
||||
@@ -6,9 +6,9 @@ class Api::V1::FavouritesController < Api::BaseController
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
account_relationships: AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::EmojiReactionedByAccountsController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
||||
before_action :set_status
|
||||
after_action :insert_pagination_headers
|
||||
|
||||
def index
|
||||
@accounts = load_accounts
|
||||
render json: @accounts, each_serializer: REST::EmojiReactionAccountSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_accounts
|
||||
scope = default_accounts
|
||||
# scope = scope.where.not(account_id: current_account.excluded_from_timeline_account_ids) unless current_account.nil?
|
||||
scope.merge(paginated_emoji_reactions).to_a
|
||||
end
|
||||
|
||||
def default_accounts
|
||||
EmojiReaction
|
||||
.where(status_id: @status.id)
|
||||
#.where(account: { suspended_at: nil })
|
||||
end
|
||||
|
||||
def paginated_emoji_reactions
|
||||
EmojiReaction.paginate_by_max_id(
|
||||
limit_param(1000), #limit_param(DEFAULT_ACCOUNTS_LIMIT),
|
||||
params[:max_id],
|
||||
params[:since_id]
|
||||
)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
api_v1_status_emoji_reactioned_by_index_url pagination_params(max_id: pagination_max_id) if records_continue?
|
||||
end
|
||||
|
||||
def prev_path
|
||||
api_v1_status_emoji_reactioned_by_index_url pagination_params(since_id: pagination_since_id) unless @accounts.empty?
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
@accounts.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
@accounts.first.id
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
|
||||
end
|
||||
|
||||
def set_status
|
||||
@status = Status.find(params[:status_id])
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::EmojiReactionedByAccountsSlimController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { authorize_if_got_token! :read, :'read:accounts' }
|
||||
before_action :set_status
|
||||
|
||||
def index
|
||||
@accounts = load_emoji_reactions
|
||||
|
||||
# TODO for serialize hash object
|
||||
render json: @accounts, each_serializer: REST::EmojiReactedBySlimSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_emoji_reactions
|
||||
@status.generate_emoji_reactions_grouped_by_account
|
||||
end
|
||||
|
||||
def set_status
|
||||
@status = Status.find(params[:status_id])
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,64 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Statuses::EmojiReactionsController < Api::BaseController
|
||||
include Authorization
|
||||
|
||||
before_action -> { doorkeeper_authorize! :write, :'write:emoji_reactions' }
|
||||
before_action :require_user!
|
||||
before_action :set_status, only: %i(create update destroy)
|
||||
before_action :set_status_without_authorize, only: [:destroy]
|
||||
|
||||
def create
|
||||
create_private(params[:emoji])
|
||||
end
|
||||
|
||||
# For compatible with Fedibird API
|
||||
def update
|
||||
create_private(params[:id])
|
||||
end
|
||||
|
||||
def destroy
|
||||
emoji = params[:emoji] || params[:id]
|
||||
|
||||
if emoji
|
||||
shortcode, domain = emoji.split('@')
|
||||
emoji_reaction = EmojiReaction.where(account_id: current_account.id).where(status_id: @status.id).where(name: shortcode)
|
||||
.find { |reaction| domain == '' ? reaction.custom_emoji.nil? : reaction.custom_emoji&.domain == domain }
|
||||
|
||||
authorize @status, :show? if emoji_reaction.nil?
|
||||
end
|
||||
|
||||
UnEmojiReactWorker.perform_async(current_account.id, @status.id, emoji)
|
||||
|
||||
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(
|
||||
[@status], current_account.id, emoji_reactions_map: { @status.id => false }
|
||||
)
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_private(emoji)
|
||||
count = EmojiReaction.where(account: current_account, status: @status).count
|
||||
|
||||
if count >= EmojiReaction::EMOJI_REACTION_PER_ACCOUNT_LIMIT
|
||||
bad_request
|
||||
return
|
||||
end
|
||||
|
||||
EmojiReactService.new.call(current_account, @status, emoji)
|
||||
render json: @status, serializer: REST::StatusSerializer
|
||||
end
|
||||
|
||||
def set_status
|
||||
set_status_without_authorize
|
||||
authorize @status, :show?
|
||||
rescue Mastodon::NotPermittedError
|
||||
not_found
|
||||
end
|
||||
|
||||
def set_status_without_authorize
|
||||
@status = Status.find(params[:status_id])
|
||||
end
|
||||
end
|
||||
@@ -47,10 +47,10 @@ class Api::V1::StatusesController < Api::BaseController
|
||||
loaded_ancestors = cache_collection(ancestors_results, Status)
|
||||
loaded_descendants = cache_collection(descendants_results, Status)
|
||||
|
||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
||||
statuses = [@status] + @context.ancestors + @context.descendants
|
||||
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
|
||||
statuses = [@status] + @context.ancestors + @context.descendants
|
||||
accounts = statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
|
||||
render json: @context, serializer: REST::ContextSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id),
|
||||
@@ -76,13 +76,9 @@ class Api::V1::StatusesController < Api::BaseController
|
||||
quote_id: status_params[:quote_id].presence
|
||||
)
|
||||
|
||||
render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
|
||||
render json: @status, serializer: serializer_for_status
|
||||
rescue PostStatusService::UnexpectedMentionsError => e
|
||||
unexpected_accounts = ActiveModel::Serializer::CollectionSerializer.new(
|
||||
e.accounts,
|
||||
serializer: REST::AccountSerializer
|
||||
)
|
||||
render json: { error: e.message, unexpected_accounts: unexpected_accounts }, status: 422
|
||||
render json: unexpected_accounts_error_json(e), status: 422
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -161,6 +157,21 @@ class Api::V1::StatusesController < Api::BaseController
|
||||
)
|
||||
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)
|
||||
params.slice(:limit).permit(:limit).merge(core_params)
|
||||
end
|
||||
|
||||
@@ -10,8 +10,8 @@ class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
|
||||
with_read_replica do
|
||||
@statuses = load_statuses
|
||||
@relationships = StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
|
||||
@account_relationships = AccountRelationshipsPresenter.new(accounts, current_user&.account_id)
|
||||
end
|
||||
|
||||
@@ -9,8 +9,8 @@ class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
|
||||
PERMITTED_PARAMS = %i(limit).freeze
|
||||
|
||||
def show
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
|
||||
render json: @statuses,
|
||||
each_serializer: REST::StatusSerializer,
|
||||
|
||||
@@ -7,9 +7,9 @@ class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
|
||||
|
||||
def show
|
||||
cache_if_unauthenticated!
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
|
||||
@@ -8,9 +8,9 @@ class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
|
||||
|
||||
def show
|
||||
cache_if_unauthenticated!
|
||||
@statuses = load_statuses
|
||||
@statuses = load_statuses
|
||||
accounts = @statuses.filter_map { |status| status.quote&.account }.uniq
|
||||
account_ids = @statuses.filter(&:quote?).map { |status| status.quote.account_id }.uniq
|
||||
accounts = Account.where(id: account_ids)
|
||||
|
||||
render json: @statuses, each_serializer: REST::StatusSerializer,
|
||||
relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id),
|
||||
|
||||
@@ -7,7 +7,7 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
def self.provides_callback_for(provider)
|
||||
define_method provider do
|
||||
@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?
|
||||
record_login_activity
|
||||
@@ -17,6 +17,9 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
session["devise.#{provider}_data"] = request.env['omniauth.auth']
|
||||
redirect_to new_user_registration_url
|
||||
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
|
||||
|
||||
|
||||
@@ -183,7 +183,9 @@ class Auth::SessionsController < Devise::SessionsController
|
||||
)
|
||||
|
||||
# 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!
|
||||
end
|
||||
|
||||
@@ -12,39 +12,6 @@ module SignatureVerification
|
||||
|
||||
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!
|
||||
render json: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account
|
||||
end
|
||||
@@ -135,12 +102,8 @@ module SignatureVerification
|
||||
end
|
||||
|
||||
def signature_params
|
||||
@signature_params ||= begin
|
||||
raw_signature = request.headers['Signature']
|
||||
tree = SignatureParamsParser.new.parse(raw_signature)
|
||||
SignatureParamsTransformer.new.apply(tree)
|
||||
end
|
||||
rescue Parslet::ParseFailed
|
||||
@signature_params ||= SignatureParser.parse(request.headers['Signature'])
|
||||
rescue SignatureParser::ParsingError
|
||||
raise SignatureVerificationError, 'Error parsing signature parameters'
|
||||
end
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@ class CustomCssController < ActionController::Base # rubocop:disable Rails/Appli
|
||||
helper_method :custom_css_styles
|
||||
|
||||
def set_user_roles
|
||||
@user_roles = UserRole.where(highlighted: true).where.not(color: [nil, ''])
|
||||
@user_roles = UserRole.providing_styles
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
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
|
||||
|
||||
def show
|
||||
if uri.scheme == 'web+mastodon'
|
||||
case uri.host
|
||||
when 'follow'
|
||||
return redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:'))
|
||||
when 'share'
|
||||
return redirect_to share_path(text: uri.query_values['text'])
|
||||
end
|
||||
case uri.host
|
||||
when 'follow'
|
||||
redirect_to authorize_interaction_path(uri: uri.query_values['uri'].delete_prefix('acct:'))
|
||||
when 'share'
|
||||
redirect_to share_path(text: uri.query_values['text'])
|
||||
else
|
||||
handle_invalid_uri
|
||||
end
|
||||
|
||||
not_found
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_uri
|
||||
not_found if uri.blank?
|
||||
def valid_uri?
|
||||
uri.present? && uri.scheme == EXPECTED_SCHEME
|
||||
end
|
||||
|
||||
def handle_invalid_uri
|
||||
|
||||
@@ -23,7 +23,7 @@ module FormattingHelper
|
||||
status.text,
|
||||
status.local?,
|
||||
preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []),
|
||||
quote: status.respond_to?(:quote) && status.quote
|
||||
quote: status.respond_to?(:quote) && status.quote,
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -174,7 +174,19 @@ module JsonLdHelper
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -15,9 +15,20 @@ module ReactComponentHelper
|
||||
div_tag_with_data(data)
|
||||
end
|
||||
|
||||
def serialized_media_attachments(media_attachments)
|
||||
media_attachments.map { |attachment| serialized_attachment(attachment) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def div_tag_with_data(data)
|
||||
content_tag(:div, nil, data: data)
|
||||
end
|
||||
|
||||
def serialized_attachment(attachment)
|
||||
ActiveModelSerializers::SerializableResource.new(
|
||||
attachment,
|
||||
serializer: REST::MediaAttachmentSerializer
|
||||
).as_json
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,7 +25,6 @@ export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
|
||||
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
|
||||
export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
|
||||
export const COMPOSE_QUOTE = 'COMPOSE_QUOTE';
|
||||
export const COMPOSE_QUOTE_CANCEL = 'COMPOSE_QUOTE_CANCEL';
|
||||
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
|
||||
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
|
||||
export const COMPOSE_RESET = 'COMPOSE_RESET';
|
||||
@@ -137,13 +136,7 @@ export function quoteCompose(status, routerHistory) {
|
||||
|
||||
ensureComposeIsVisible(getState, routerHistory);
|
||||
};
|
||||
};
|
||||
|
||||
export function cancelQuoteCompose() {
|
||||
return {
|
||||
type: COMPOSE_QUOTE_CANCEL,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function resetCompose() {
|
||||
return {
|
||||
|
||||
@@ -40,6 +40,10 @@ export function normalizeStatus(status, normalOldStatus) {
|
||||
normalStatus.filtered = status.filtered.map(normalizeFilterResult);
|
||||
}
|
||||
|
||||
if (status.emoji_reactions) {
|
||||
normalStatus.emojiReactions = status.emoji_reactions;
|
||||
}
|
||||
|
||||
// Only calculate these values when status first encountered and
|
||||
// when the underlying values change. Otherwise keep the ones
|
||||
// already in the reducer
|
||||
|
||||
@@ -15,6 +15,10 @@ export const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST';
|
||||
export const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
|
||||
export const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
|
||||
|
||||
export const EMOJIREACT_REQUEST = 'EMOJIREACT_REQUEST';
|
||||
export const EMOJIREACT_SUCCESS = 'EMOJIREACT_SUCCESS';
|
||||
export const EMOJIREACT_FAIL = 'EMOJIREACT_FAIL';
|
||||
|
||||
export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
|
||||
export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
|
||||
export const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
|
||||
@@ -23,6 +27,10 @@ export const UNFAVOURITE_REQUEST = 'UNFAVOURITE_REQUEST';
|
||||
export const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
|
||||
export const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
|
||||
|
||||
export const UNEMOJIREACT_REQUEST = 'UNEMOJIREACT_REQUEST';
|
||||
export const UNEMOJIREACT_SUCCESS = 'UNEMOJIREACT_SUCCESS';
|
||||
export const UNEMOJIREACT_FAIL = 'UNEMOJIREACT_FAIL';
|
||||
|
||||
export const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
|
||||
export const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
|
||||
export const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
|
||||
@@ -33,7 +41,11 @@ export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL';
|
||||
|
||||
export const FAVOURITES_EXPAND_REQUEST = 'FAVOURITES_EXPAND_REQUEST';
|
||||
export const FAVOURITES_EXPAND_SUCCESS = 'FAVOURITES_EXPAND_SUCCESS';
|
||||
export const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
|
||||
export const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
|
||||
|
||||
export const EMOJI_REACTIONS_FETCH_REQUEST = 'EMOJI_REACTIONS_FETCH_REQUEST';
|
||||
export const EMOJI_REACTIONS_FETCH_SUCCESS = 'EMOJI_REACTIONS_FETCH_SUCCESS';
|
||||
export const EMOJI_REACTIONS_FETCH_FAIL = 'EMOJI_REACTIONS_FETCH_FAIL';
|
||||
|
||||
export const PIN_REQUEST = 'PIN_REQUEST';
|
||||
export const PIN_SUCCESS = 'PIN_SUCCESS';
|
||||
@@ -205,6 +217,88 @@ export function unfavouriteFail(status, error) {
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReact(status, emoji) {
|
||||
return function (dispatch, getState) {
|
||||
dispatch(emojiReactRequest(status, emoji));
|
||||
|
||||
const api_emoji = typeof emoji !== 'string' ? (emoji.custom ? (emoji.name + (emoji.domain || '')) : emoji.native) : emoji;
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/emoji_reactions`, { emoji: api_emoji }).then(function () {
|
||||
dispatch(emojiReactSuccess(status, emoji));
|
||||
}).catch(function (error) {
|
||||
dispatch(emojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReact(status, emoji) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(unEmojiReactRequest(status, emoji));
|
||||
|
||||
api(getState).post(`/api/v1/statuses/${status.get('id')}/emoji_unreaction`, { emoji }).then(() => {
|
||||
dispatch(unEmojiReactSuccess(status, emoji));
|
||||
}).catch(error => {
|
||||
dispatch(unEmojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactRequest(status, emoji) {
|
||||
return {
|
||||
type: EMOJIREACT_REQUEST,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactSuccess(status, emoji) {
|
||||
return {
|
||||
type: EMOJIREACT_SUCCESS,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactFail(status, emoji, error) {
|
||||
return {
|
||||
type: EMOJIREACT_FAIL,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactRequest(status, emoji) {
|
||||
return {
|
||||
type: UNEMOJIREACT_REQUEST,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactSuccess(status, emoji) {
|
||||
return {
|
||||
type: UNEMOJIREACT_SUCCESS,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactFail(status, emoji, error) {
|
||||
return {
|
||||
type: UNEMOJIREACT_FAIL,
|
||||
status: status,
|
||||
emoji: emoji,
|
||||
error: error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function bookmark(status) {
|
||||
return function (dispatch, getState) {
|
||||
dispatch(bookmarkRequest(status));
|
||||
@@ -441,6 +535,85 @@ export function expandFavouritesFail(id, error) {
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactions(id) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(fetchEmojiReactionsRequest(id));
|
||||
|
||||
api(getState).get(`/api/v1/statuses/${id}/emoji_reactioned_by`).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
dispatch(importFetchedAccounts(response.data.map((er) => er.account)));
|
||||
dispatch(fetchEmojiReactionsSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => {
|
||||
dispatch(fetchEmojiReactionsFail(id, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactionsRequest(id) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_FETCH_REQUEST,
|
||||
id,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactionsSuccess(id, accounts, next) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_FETCH_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactionsFail(id, error) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandEmojiReactions(id) {
|
||||
return (dispatch, getState) => {
|
||||
const url = getState().getIn(['user_lists', 'emoji_reactioned_by', id, 'next']);
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(expandEmojiReactionsRequest(id));
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
dispatch(importFetchedAccounts(response.data.map((er) => er.account)));
|
||||
dispatch(expandEmojiReactionsSuccess(id, response.data, next ? next.uri : null));
|
||||
}).catch(error => dispatch(expandEmojiReactionsFail(id, error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function expandEmojiReactionsRequest(id) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_EXPAND_REQUEST,
|
||||
id,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandEmojiReactionsSuccess(id, accounts, next) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_EXPAND_SUCCESS,
|
||||
id,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandEmojiReactionsFail(id, error) {
|
||||
return {
|
||||
type: EMOJI_REACTIONS_EXPAND_FAIL,
|
||||
id,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function pin(status) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(pinRequest(status));
|
||||
|
||||
@@ -21,6 +21,7 @@ import { submitMarkers } from './markers';
|
||||
import { notificationsUpdate } from "./notifications_typed";
|
||||
import { register as registerPushNotifications } from './push_notifications';
|
||||
import { saveSettings } from './settings';
|
||||
import { STATUS_EMOJI_REACTION_UPDATE } from './statuses';
|
||||
|
||||
export * from "./notifications_typed";
|
||||
|
||||
@@ -61,6 +62,15 @@ export const loadPending = () => ({
|
||||
type: NOTIFICATIONS_LOAD_PENDING,
|
||||
});
|
||||
|
||||
export function updateEmojiReactions(emoji_reaction, accountId) {
|
||||
return (dispatch) =>
|
||||
dispatch({
|
||||
type: STATUS_EMOJI_REACTION_UPDATE,
|
||||
emoji_reaction,
|
||||
accountId,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
return (dispatch, getState) => {
|
||||
const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
|
||||
@@ -130,10 +140,13 @@ const excludeTypesFromFilter = filter => {
|
||||
'follow',
|
||||
'follow_request',
|
||||
'favourite',
|
||||
'emoji_reaction',
|
||||
'reblog',
|
||||
'status_reference',
|
||||
'mention',
|
||||
'poll',
|
||||
'status',
|
||||
'list_status',
|
||||
'update',
|
||||
'admin.sign_up',
|
||||
'admin.report',
|
||||
|
||||
@@ -42,6 +42,8 @@ export const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS';
|
||||
export const STATUS_TRANSLATE_FAIL = 'STATUS_TRANSLATE_FAIL';
|
||||
export const STATUS_TRANSLATE_UNDO = 'STATUS_TRANSLATE_UNDO';
|
||||
|
||||
export const STATUS_EMOJI_REACTION_UPDATE = 'STATUS_EMOJI_REACTION_UPDATE';
|
||||
|
||||
export function fetchStatusRequest(id, skipLoading) {
|
||||
return {
|
||||
type: STATUS_FETCH_REQUEST,
|
||||
@@ -361,7 +363,7 @@ export function hideQuote(ids) {
|
||||
type: QUOTE_HIDE,
|
||||
ids,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function revealQuote(ids) {
|
||||
if (!Array.isArray(ids)) {
|
||||
@@ -373,3 +375,8 @@ export function revealQuote(ids) {
|
||||
ids,
|
||||
};
|
||||
};
|
||||
|
||||
export const updateEmojiReaction = (emoji_reaction) => ({
|
||||
type: STATUS_EMOJI_REACTION_UPDATE,
|
||||
emoji_reaction,
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
deleteAnnouncement,
|
||||
} from './announcements';
|
||||
import { updateConversations } from './conversations';
|
||||
import { updateNotifications, expandNotifications } from './notifications';
|
||||
import { updateNotifications, expandNotifications, updateEmojiReactions } from './notifications';
|
||||
import { updateStatus } from './statuses';
|
||||
import {
|
||||
updateTimeline,
|
||||
@@ -24,6 +24,8 @@ import {
|
||||
fillListTimelineGaps,
|
||||
} from './timelines';
|
||||
|
||||
const { messages } = getLocale();
|
||||
|
||||
/**
|
||||
* @param {number} max
|
||||
* @returns {number}
|
||||
@@ -102,6 +104,10 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
|
||||
// @ts-expect-error
|
||||
dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
|
||||
break;
|
||||
case 'emoji_reaction':
|
||||
// @ts-expect-error
|
||||
dispatch(updateEmojiReactions(JSON.parse(data.payload), getState().getIn(['meta', 'me'])));
|
||||
break;
|
||||
case 'conversation':
|
||||
// @ts-expect-error
|
||||
dispatch(updateConversations(JSON.parse(data.payload)));
|
||||
|
||||
@@ -46,6 +46,8 @@ class Account extends ImmutablePureComponent {
|
||||
minimal: PropTypes.bool,
|
||||
defaultAction: PropTypes.string,
|
||||
withBio: PropTypes.bool,
|
||||
onActionClick: PropTypes.func,
|
||||
children: PropTypes.object,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@@ -73,7 +75,7 @@ class Account extends ImmutablePureComponent {
|
||||
};
|
||||
|
||||
render () {
|
||||
const { account, intl, hidden, withBio, defaultAction, size, minimal } = this.props;
|
||||
const { account, intl, hidden, onActionClick, actionIcon, actionTitle, withBio, defaultAction, size, minimal, children } = this.props;
|
||||
|
||||
if (!account) {
|
||||
return <EmptyAccount size={size} minimal={minimal} />;
|
||||
@@ -156,11 +158,13 @@ class Account extends ImmutablePureComponent {
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{!minimal && (
|
||||
<div className='account__relationship'>
|
||||
{buttons}
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
<div className='account__relationship'>
|
||||
{buttons}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{withBio && (account.get('note').length > 0 ? (
|
||||
|
||||
@@ -124,7 +124,7 @@ class ReportReasonSelector extends PureComponent {
|
||||
|
||||
api().put(`/api/v1/admin/reports/${id}`, {
|
||||
category,
|
||||
rule_ids,
|
||||
rule_ids: category === 'violation' ? rule_ids : [],
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
33
app/javascript/mastodon/components/emoji_view.jsx
Normal file
33
app/javascript/mastodon/components/emoji_view.jsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import emojify from '../features/emoji/emoji';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default class EmojiView extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
staticUrl: PropTypes.string,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { name, url, staticUrl } = this.props;
|
||||
|
||||
let emojiHtml = null;
|
||||
if (url) {
|
||||
let customEmojis = {};
|
||||
customEmojis[`:${name}:`] = { url, static_url: staticUrl };
|
||||
emojiHtml = emojify(`:${name}:`, customEmojis);
|
||||
} else {
|
||||
emojiHtml = emojify(name);
|
||||
}
|
||||
|
||||
return (
|
||||
<span className='emoji' dangerouslySetInnerHTML={{ __html: emojiHtml }} />
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StatusEmojiReactionsBar from './status_emoji_reactions_bar';
|
||||
import AttachmentList from './attachment_list';
|
||||
|
||||
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
@@ -134,7 +137,7 @@ export const quote = (status, muted, quoteMuted, handleQuoteClick, handleExpande
|
||||
return (
|
||||
<div>
|
||||
<div className='status__info'>
|
||||
{identity(quoteStatus, null, null, true)}
|
||||
{identity(quoteStatus, null, true)}
|
||||
</div>
|
||||
<StatusContent status={quoteStatus} onClick={handleQuoteClick} expanded={!status.get('quote_hidden')} onExpandedToggle={handleExpandedQuoteToggle} quote />
|
||||
{media(quoteStatus, true)}
|
||||
@@ -146,7 +149,6 @@ export const quote = (status, muted, quoteMuted, handleQuoteClick, handleExpande
|
||||
<div
|
||||
className={classNames('quote-status', `status-${quoteStatus.get('visibility')}`, { muted: muted })}
|
||||
data-id={quoteStatus.get('id')}
|
||||
dataurl={quoteStatus.get('url')}
|
||||
>
|
||||
{quoteInner}
|
||||
</div>
|
||||
@@ -164,6 +166,8 @@ class Status extends ImmutablePureComponent {
|
||||
onClick: PropTypes.func,
|
||||
onReply: PropTypes.func,
|
||||
onFavourite: PropTypes.func,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onUnEmojiReact: PropTypes.func,
|
||||
onReblog: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
onDirect: PropTypes.func,
|
||||
@@ -199,6 +203,7 @@ class Status extends ImmutablePureComponent {
|
||||
}),
|
||||
contextType: PropTypes.string,
|
||||
...WithOptionalRouterPropTypes,
|
||||
withoutEmojiReactions: PropTypes.bool,
|
||||
};
|
||||
|
||||
// Avoid checking props that are functions (and whose equality will always
|
||||
@@ -238,7 +243,7 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
handleToggleQuoteMediaVisibility = () => {
|
||||
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
||||
}
|
||||
};
|
||||
|
||||
handleClick = e => {
|
||||
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||
@@ -253,10 +258,6 @@ class Status extends ImmutablePureComponent {
|
||||
};
|
||||
|
||||
handlePrependAccountClick = e => {
|
||||
this.handleAccountClick(e, false);
|
||||
};
|
||||
|
||||
handleAccountClick = (e, proper = true) => {
|
||||
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||
return;
|
||||
}
|
||||
@@ -266,17 +267,29 @@ class Status extends ImmutablePureComponent {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
this._openProfile(proper);
|
||||
this._openProfile(false);
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
if (!this.props) {
|
||||
handleAccountClick = (e) => {
|
||||
if (e && (e.button !== 0 || e.ctrlKey || e.metaKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { status } = this.props;
|
||||
this.props.history.push(`/statuses/${status.getIn(['reblog', 'quote', 'id'], status.getIn(['quote', 'id']))}`);
|
||||
}
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
const acct = e.currentTarget.getAttribute('data-acct');
|
||||
this.props.history.push(`/@${acct}`);
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
if (this.props.history) {
|
||||
const status = this._properStatus();
|
||||
this.props.history.push(`/@${status.getIn(['quote', 'account', 'acct'])}/${status.getIn(['quote', 'id'])}`);
|
||||
}
|
||||
};
|
||||
|
||||
handleQuoteUserClick = () =>{
|
||||
if (!this.props) {
|
||||
@@ -301,7 +314,7 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
handleExpandedQuoteToggle = () => {
|
||||
this.props.onQuoteToggleHidden(this._properStatus());
|
||||
}
|
||||
};
|
||||
|
||||
getAttachmentAspectRatio () {
|
||||
const attachments = this._properStatus().get('media_attachments');
|
||||
@@ -554,9 +567,10 @@ class Status extends ImmutablePureComponent {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const media = (status, quote = false) => {
|
||||
if (pictureInPicture.get('inUse')) {
|
||||
return <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} />;
|
||||
return <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} width={this.props.cachedMediaWidth} />;
|
||||
} else if (status.get('media_attachments').size > 0) {
|
||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||
|
||||
@@ -655,9 +669,9 @@ class Status extends ImmutablePureComponent {
|
||||
return <AvatarOverlay account={status.get('account')} friend={account} />;
|
||||
}
|
||||
};
|
||||
|
||||
const identity = (status, account, _0, quote = false) => (
|
||||
<a onClick={quote ? this.handleQuoteUserClick : this.handleAccountClick} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' rel='noopener noreferrer'>
|
||||
|
||||
const identity = (status, account) => (
|
||||
<a onClick={this.handleAccountClick} data-acct={status.getIn(['account', 'acct'])} href={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} className='status__display-name' target='_blank' rel='noopener noreferrer'>
|
||||
<div className='status__avatar'>
|
||||
{statusAvatar(status, account)}
|
||||
</div>
|
||||
@@ -669,6 +683,12 @@ class Status extends ImmutablePureComponent {
|
||||
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
|
||||
const expanded = !status.get('hidden') || status.get('spoiler_text').length === 0;
|
||||
|
||||
let emojiReactionsBar = null;
|
||||
if (!this.props.withoutEmojiReactions && status.get('emoji_reactions')) {
|
||||
const emojiReactions = status.get('emoji_reactions');
|
||||
emojiReactionsBar = <StatusEmojiReactionsBar emojiReactions={emojiReactions} status={status} onEmojiReact={this.props.onEmojiReact} onUnEmojiReact={this.props.onUnEmojiReact} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<HotKeys handlers={handlers}>
|
||||
<div className={classNames('status__wrapper', `status__wrapper-${status.get('visibility')}`, { 'status__wrapper-reply': !!status.get('in_reply_to_id'), unread, focusable: !this.props.muted })} tabIndex={this.props.muted ? null : 0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText)} ref={this.handleRef} data-nosnippet={status.getIn(['account', 'noindex'], true) || undefined}>
|
||||
@@ -712,6 +732,8 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
{expanded && hashtagBar}
|
||||
|
||||
{emojiReactionsBar}
|
||||
|
||||
<StatusActionBar scrollKey={scrollKey} status={status} account={account} onFilter={matchedFilters ? this.handleFilterClick : null} {...other} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import EmojiPickerDropdown from '../features/compose/containers/emoji_picker_dropdown_container';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
@@ -11,12 +12,12 @@ import { connect } from 'react-redux';
|
||||
|
||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg';
|
||||
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
||||
import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
|
||||
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
|
||||
import QuoteIcon from '@material-symbols/400-24px/format_quote.svg?react';
|
||||
import StarBorderIcon from '@/material-icons/400-24px/star.svg?react';
|
||||
import VisibilityIcon from '@/material-icons/400-24px/visibility.svg?react';
|
||||
import RepeatActiveIcon from '@/svg-icons/repeat_active.svg?react';
|
||||
@@ -50,6 +51,7 @@ const messages = defineMessages({
|
||||
quote: { id: 'status.quote', defaultMessage: 'Quote' },
|
||||
cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' },
|
||||
favourite: { id: 'status.favourite', defaultMessage: 'Favorite' },
|
||||
emojiReaction: { id: 'status.emoji_reaction', defaultMessage: 'Emoji Reaction' },
|
||||
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
|
||||
removeBookmark: { id: 'status.remove_bookmark', defaultMessage: 'Remove bookmark' },
|
||||
open: { id: 'status.open', defaultMessage: 'Expand this status' },
|
||||
@@ -87,6 +89,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
relationship: ImmutablePropTypes.map,
|
||||
onReply: PropTypes.func,
|
||||
onFavourite: PropTypes.func,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onReblog: PropTypes.func,
|
||||
onQuote: PropTypes.func,
|
||||
onDelete: PropTypes.func,
|
||||
@@ -149,6 +152,16 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
handleEmojiPick = (data) => {
|
||||
const { signedIn } = this.context.identity;
|
||||
|
||||
if (signedIn) {
|
||||
this.props.onEmojiReact(this.props.status, data);
|
||||
} else {
|
||||
this.props.onInteractionModal('favourite', this.props.status);
|
||||
}
|
||||
};
|
||||
|
||||
handleReblogClick = e => {
|
||||
const { signedIn } = this.context.identity;
|
||||
|
||||
@@ -160,8 +173,8 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
this.props.onQuote(this.props.status, this.props.history);
|
||||
}
|
||||
this.props.onQuote(this.props.status);
|
||||
};
|
||||
|
||||
handleBookmarkClick = () => {
|
||||
this.props.onBookmark(this.props.status);
|
||||
@@ -262,7 +275,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
} else {
|
||||
return intl.formatMessage(messages.cannot_quote);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { status, relationship, intl, withDismiss, withCounters, scrollKey } = this.props;
|
||||
@@ -402,13 +415,18 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||
|
||||
const isReply = status.get('in_reply_to_account_id') === status.getIn(['account', 'id']);
|
||||
|
||||
const emojiPickerButton = (
|
||||
<IconButton className='status__action-bar__button' title={intl.formatMessage(messages.emojiReaction)} icon='smile-o' />
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='status__action-bar'>
|
||||
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
|
||||
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
|
||||
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
||||
<IconButton className='status__action-bar__button' disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='quote' iconComponent={QuoteIcon} onClick={this.handleQuoteClick} />
|
||||
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} pressed={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
|
||||
<IconButton className='status__action-bar__button' disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='format-quote' iconComponent={FormatQuoteIcon} onClick={this.handleQuoteClick} />
|
||||
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />
|
||||
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} />
|
||||
|
||||
{filterButton}
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ class StatusContent extends PureComponent {
|
||||
};
|
||||
|
||||
render () {
|
||||
const { status, intl, statusContent, quote } = this.props;
|
||||
const { status, intl, quote, statusContent } = this.props;
|
||||
|
||||
const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden;
|
||||
const renderReadMore = this.props.onClick && status.get('collapsed');
|
||||
@@ -336,4 +336,4 @@ class StatusContent extends PureComponent {
|
||||
|
||||
}
|
||||
|
||||
export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));
|
||||
export default withRouter(connect(mapStateToProps)(injectIntl(StatusContent)));
|
||||
@@ -0,0 +1,96 @@
|
||||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import emojify from '../features/emoji/emoji';
|
||||
import classNames from 'classnames';
|
||||
import EmojiView from './emoji_view';
|
||||
|
||||
class EmojiReactionButton extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
domain: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
staticUrl: PropTypes.string,
|
||||
count: PropTypes.number.isRequired,
|
||||
me: PropTypes.bool,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onUnEmojiReact: PropTypes.func,
|
||||
};
|
||||
|
||||
onClick = () => {
|
||||
const { name, domain, me } = this.props;
|
||||
|
||||
const nameParameter = domain ? `${name}@${domain}` : name;
|
||||
if (me) {
|
||||
if (this.props.onUnEmojiReact) this.props.onUnEmojiReact(nameParameter);
|
||||
} else {
|
||||
if (this.props.onEmojiReact) this.props.onEmojiReact(nameParameter);
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { name, url, staticUrl, count, me } = this.props;
|
||||
|
||||
const classList = {
|
||||
'reactions-bar__item': true,
|
||||
'active': me,
|
||||
};
|
||||
|
||||
return (
|
||||
<button className={classNames(classList)} type='button' onClick={this.onClick}>
|
||||
<span className='reactions-bar__item__emoji'>
|
||||
<EmojiView name={name} url={url} staticUrl={staticUrl} />
|
||||
</span>
|
||||
<span className='reactions-bar__item__count'>{count}</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StatusEmojiReactionsBar extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
emojiReactions: ImmutablePropTypes.list.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onUnEmojiReact: PropTypes.func,
|
||||
};
|
||||
|
||||
onEmojiReact = (name) => {
|
||||
if (!this.props.onEmojiReact) return;
|
||||
this.props.onEmojiReact(this.props.status, name);
|
||||
};
|
||||
|
||||
onUnEmojiReact = (name) => {
|
||||
if (!this.props.onUnEmojiReact) return;
|
||||
this.props.onUnEmojiReact(this.props.status, name);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { emojiReactions } = this.props;
|
||||
|
||||
const emojiButtons = Array.from(emojiReactions).map((emoji, index) => (
|
||||
<EmojiReactionButton
|
||||
key={index}
|
||||
name={emoji.get('name')}
|
||||
count={emoji.get('count')}
|
||||
me={emoji.get('me')}
|
||||
url={emoji.get('url')}
|
||||
staticUrl={emoji.get('static_url')}
|
||||
domain={emoji.get('domain')}
|
||||
onEmojiReact={this.onEmojiReact}
|
||||
onUnEmojiReact={this.onUnEmojiReact}
|
||||
/>));
|
||||
|
||||
return (
|
||||
<div className='status__emoji-reactions-bar'>
|
||||
{emojiButtons}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
export default injectIntl(StatusEmojiReactionsBar);
|
||||
@@ -25,9 +25,11 @@ import {
|
||||
import {
|
||||
reblog,
|
||||
favourite,
|
||||
emojiReact,
|
||||
bookmark,
|
||||
unreblog,
|
||||
unfavourite,
|
||||
unEmojiReact,
|
||||
unbookmark,
|
||||
pin,
|
||||
unpin,
|
||||
@@ -140,6 +142,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
||||
}
|
||||
},
|
||||
|
||||
onEmojiReact (status, emoji) {
|
||||
dispatch(emojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onUnEmojiReact (status, emoji) {
|
||||
dispatch(unEmojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onBookmark (status) {
|
||||
if (status.get('bookmarked')) {
|
||||
dispatch(unbookmark(status));
|
||||
|
||||
@@ -29,6 +29,7 @@ import { CharacterCounter } from './character_counter';
|
||||
import { EditIndicator } from './edit_indicator';
|
||||
import { NavigationBar } from './navigation_bar';
|
||||
import { PollForm } from "./poll_form";
|
||||
import { QuoteIndicator } from './quote_indicator';
|
||||
import { ReplyIndicator } from './reply_indicator';
|
||||
|
||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
||||
@@ -296,6 +297,8 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
<UploadFormContainer />
|
||||
<PollForm />
|
||||
|
||||
<QuoteIndicator />
|
||||
|
||||
<div className='compose-form__footer'>
|
||||
<div className='compose-form__dropdowns'>
|
||||
<PrivacyDropdownContainer disabled={this.props.isEditing} />
|
||||
|
||||
@@ -6,9 +6,9 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import BarChart4BarsIcon from 'mastodon/../material-icons/400-24px/bar_chart_4_bars.svg?react';
|
||||
import CloseIcon from 'mastodon/../material-icons/400-24px/close.svg?react';
|
||||
import PhotoLibraryIcon from 'mastodon/../material-icons/400-24px/photo_library.svg?react';
|
||||
import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react';
|
||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||
import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react';
|
||||
import { cancelReplyCompose } from 'mastodon/actions/compose';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
|
||||
@@ -10,7 +10,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
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 { assetHost } from 'mastodon/utils/config';
|
||||
|
||||
@@ -330,6 +330,7 @@ class EmojiPickerDropdown extends PureComponent {
|
||||
state = {
|
||||
active: false,
|
||||
loading: false,
|
||||
bottom: true,
|
||||
};
|
||||
|
||||
setRef = (c) => {
|
||||
@@ -337,6 +338,7 @@ class EmojiPickerDropdown extends PureComponent {
|
||||
};
|
||||
|
||||
onShowDropdown = () => {
|
||||
this.updateDropdownPosition();
|
||||
this.setState({ active: true });
|
||||
|
||||
if (!EmojiPicker) {
|
||||
@@ -357,6 +359,23 @@ class EmojiPickerDropdown extends PureComponent {
|
||||
this.setState({ active: false });
|
||||
};
|
||||
|
||||
updateDropdownPosition = () => {
|
||||
let bottom = true;
|
||||
|
||||
if (this.target) {
|
||||
const height = window.innerHeight;
|
||||
const rect = this.target.getBoundingClientRect();
|
||||
|
||||
if (height && rect) {
|
||||
bottom = height / 2 > rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.state.bottom !== bottom) {
|
||||
this.setState({ bottom });
|
||||
}
|
||||
};
|
||||
|
||||
onToggle = (e) => {
|
||||
if (!this.state.loading && (!e.key || e.key === 'Enter')) {
|
||||
if (this.state.active) {
|
||||
@@ -384,7 +403,7 @@ class EmojiPickerDropdown extends PureComponent {
|
||||
render () {
|
||||
const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props;
|
||||
const title = intl.formatMessage(messages.emoji);
|
||||
const { active, loading } = this.state;
|
||||
const { active, loading, bottom } = this.state;
|
||||
|
||||
return (
|
||||
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown} ref={this.setTargetRef}>
|
||||
@@ -397,7 +416,7 @@ class EmojiPickerDropdown extends PureComponent {
|
||||
inverted
|
||||
/>
|
||||
|
||||
<Overlay show={active} placement={'bottom'} target={this.findTarget} popperConfig={{ strategy: 'fixed' }}>
|
||||
<Overlay show={active} placement={ bottom ? 'bottom' : 'top' } target={this.findTarget} popperConfig={{ strategy: 'fixed' }}>
|
||||
{({ props, placement })=> (
|
||||
<div {...props} style={{ ...props.style }}>
|
||||
<div className={`dropdown-animation ${placement}`}>
|
||||
|
||||
@@ -9,9 +9,9 @@ import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
import fuzzysort from 'fuzzysort';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
import CancelIcon from 'mastodon/../material-icons/400-24px/cancel-fill.svg?react';
|
||||
import SearchIcon from 'mastodon/../material-icons/400-24px/search.svg?react';
|
||||
import TranslateIcon from 'mastodon/../material-icons/400-24px/translate.svg?react';
|
||||
import CancelIcon from '@/material-icons/400-24px/cancel-fill.svg?react';
|
||||
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
import TranslateIcon from '@/material-icons/400-24px/translate.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
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 Account from 'mastodon/components/account';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
|
||||
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
|
||||
|
||||
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';
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { useCallback } from "react";
|
||||
|
||||
import { FormattedMessage, defineMessages, useIntl } from "react-intl";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import BarChart4BarsIcon from 'mastodon/../material-icons/400-24px/bar_chart_4_bars.svg?react';
|
||||
import CloseIcon from 'mastodon/../material-icons/400-24px/close.svg?react';
|
||||
import PhotoLibraryIcon from 'mastodon/../material-icons/400-24px/photo_library.svg?react';
|
||||
import { cancelReplyCompose } from "mastodon/actions/compose";
|
||||
import { Avatar } from "mastodon/components/avatar";
|
||||
import { DisplayName } from "mastodon/components/display_name";
|
||||
import { Icon } from "mastodon/components/icon";
|
||||
import { IconButton } from "mastodon/components/icon_button";
|
||||
|
||||
const messages = defineMessages({
|
||||
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
|
||||
});
|
||||
|
||||
export const QuoteIndicator = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useDispatch();
|
||||
const id = useSelector(state => state.getIn(['compose', 'quote_from']));
|
||||
const status = useSelector(state => state.getIn(['statuses', id]));
|
||||
const account = useSelector(state => state.getIn(['accounts', status?.get('account')]));
|
||||
|
||||
const handleCancelClick = useCallback(() => {
|
||||
dispatch(cancelReplyCompose());
|
||||
}, [dispatch]);
|
||||
|
||||
if (!status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = { __html: status.get('contentHtml') };
|
||||
|
||||
return (
|
||||
<div className='edit-indicator'>
|
||||
<div className='edit-indicator__header'>
|
||||
<Link to={`/@${account.get('acct')}`} className='status__display-name'>
|
||||
<Avatar account={account} size={46} />
|
||||
<DisplayName account={account} />
|
||||
</Link>
|
||||
|
||||
<div className='edit-indicator__cancel'>
|
||||
<IconButton title={intl.formatMessage(messages.cancel)} icon='times' iconComponent={CloseIcon} onClick={handleCancelClick} inverted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='edit-indicator__content translate' dangerouslySetInnerHTML={content} />
|
||||
|
||||
{(status.get('poll') || status.get('media_attachments').size > 0) && (
|
||||
<div className='edit-indicator__attachments'>
|
||||
{status.get('poll') && <><Icon icon={BarChart4BarsIcon} /><FormattedMessage id='reply_indicator.poll' defaultMessage='Poll' /></>}
|
||||
{status.get('media_attachments').size > 0 && <><Icon icon={PhotoLibraryIcon} /><FormattedMessage id='reply_indicator.attachments' defaultMessage='{count, plural, one {# attachment} other {# attachments}}' values={{ count: status.get('media_attachments').size }} /></>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -9,7 +9,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
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 WarningIcon from '@/material-icons/400-24px/warning.svg?react';
|
||||
import { Blurhash } from 'mastodon/components/blurhash';
|
||||
|
||||
@@ -6,7 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
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';
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -65,6 +65,7 @@ class UploadButton extends ImmutablePureComponent {
|
||||
key={resetFileKey}
|
||||
ref={this.setRef}
|
||||
type='file'
|
||||
name='file-upload-input'
|
||||
multiple
|
||||
accept={acceptContentTypes.toArray().join(',')}
|
||||
onChange={this.handleChange}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { injectIntl, defineMessages } from 'react-intl';
|
||||
|
||||
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 { changeComposeSpoilerness } from '../../../actions/compose';
|
||||
|
||||
121
app/javascript/mastodon/features/emoji_reactions/index.jsx
Normal file
121
app/javascript/mastodon/features/emoji_reactions/index.jsx
Normal file
@@ -0,0 +1,121 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Helmet } from 'react-helmet';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { fetchEmojiReactions, expandEmojiReactions } from 'mastodon/actions/interactions';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import AccountContainer from 'mastodon/containers/account_container';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
|
||||
|
||||
|
||||
import EmojiView from '../../components/emoji_view';
|
||||
import { LoadingIndicator } from '../../components/loading_indicator';
|
||||
|
||||
const messages = defineMessages({
|
||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
return {
|
||||
accountIds: state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'next']),
|
||||
isLoading: state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId, 'isLoading'], true),
|
||||
};
|
||||
};
|
||||
|
||||
class EmojiReactions extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
multiColumn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchEmojiReactions(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
handleRefresh = () => {
|
||||
this.props.dispatch(fetchEmojiReactions(this.props.params.statusId));
|
||||
};
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandEmojiReactions(this.props.params.statusId));
|
||||
}, 300, { leading: true });
|
||||
|
||||
render () {
|
||||
const { intl, accountIds, hasMore, isLoading, multiColumn } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
<Column>
|
||||
<LoadingIndicator />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
let groups = {};
|
||||
for (const emoji_reaction of accountIds) {
|
||||
const key = emoji_reaction.account_id;
|
||||
const value = emoji_reaction;
|
||||
if (!groups[key]) groups[key] = [value];
|
||||
else groups[key].push(value);
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactions' defaultMessage='No one has reacted with emoji this post yet. When someone does, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn}>
|
||||
<ColumnHeader
|
||||
showBackButton
|
||||
multiColumn={multiColumn}
|
||||
extraButton={(
|
||||
<button type='button' className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' icon={RefreshIcon} /></button>
|
||||
)}
|
||||
/>
|
||||
|
||||
<ScrollableList
|
||||
scrollKey='emoji_reactions'
|
||||
onLoadMore={this.handleLoadMore}
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{Object.keys(groups).map((key) =>(
|
||||
<AccountContainer key={key} id={key} withNote={false} hideButtons>
|
||||
<div style={{ 'maxWidth': '100px' }}>
|
||||
{groups[key].map((value, index2) => <EmojiView key={index2} name={value.name} url={value.url} staticUrl={value.static_url} />)}
|
||||
</div>
|
||||
</AccountContainer>
|
||||
))}
|
||||
</ScrollableList>
|
||||
|
||||
<Helmet>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(injectIntl(EmojiReactions));
|
||||
@@ -8,8 +8,8 @@ import { NavLink, Switch, Route } from 'react-router-dom';
|
||||
|
||||
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 TagIcon from '@/material-icons/400-24px/tag.svg?react';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import Search from 'mastodon/features/compose/containers/search_container';
|
||||
@@ -59,7 +59,7 @@ class Explore extends PureComponent {
|
||||
<Column bindToDocument={!multiColumn} ref={this.setRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
icon={isSearching ? 'search' : 'hashtag'}
|
||||
iconComponent={isSearching ? SearchIcon : TagIcon}
|
||||
iconComponent={isSearching ? SearchIcon : ExploreIcon}
|
||||
title={intl.formatMessage(isSearching ? messages.searchResults : messages.title)}
|
||||
onClick={this.handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { DisplayName } from 'mastodon/components/display_name';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
import { VerifiedBadge } from 'mastodon/components/verified_badge';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
|
||||
const messages = defineMessages({
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
@@ -28,27 +29,43 @@ const messages = defineMessages({
|
||||
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
||||
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
||||
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 }) => {
|
||||
let label;
|
||||
const intl = useIntl();
|
||||
|
||||
let label, hint;
|
||||
|
||||
switch (id) {
|
||||
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':
|
||||
hint = intl.formatMessage(messages.similarToRecentlyFollowedHint);
|
||||
label = <FormattedMessage id='follow_suggestions.personalized_suggestion' defaultMessage='Personalized suggestion' />;
|
||||
break;
|
||||
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;
|
||||
case 'most_followed':
|
||||
hint = intl.formatMessage(messages.mostFollowedHint, { domain });
|
||||
label = <FormattedMessage id='follow_suggestions.popular_suggestion' defaultMessage='Popular suggestion' />;
|
||||
break;
|
||||
case 'most_interactions':
|
||||
hint = intl.formatMessage(messages.mostInteractionsHint, { domain });
|
||||
label = <FormattedMessage id='follow_suggestions.popular_suggestion' defaultMessage='Popular suggestion' />;
|
||||
break;
|
||||
}
|
||||
|
||||
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} />
|
||||
{label}
|
||||
</div>
|
||||
@@ -59,7 +76,7 @@ Source.propTypes = {
|
||||
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 account = useSelector(state => state.getIn(['accounts', 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'>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
);
|
||||
};
|
||||
|
||||
Card.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
source: ImmutablePropTypes.list,
|
||||
sources: ImmutablePropTypes.list,
|
||||
};
|
||||
|
||||
const DISMISSIBLE_ID = 'home/follow-suggestions';
|
||||
@@ -175,7 +192,7 @@ export const InlineFollowSuggestions = ({ hidden }) => {
|
||||
<Card
|
||||
key={suggestion.get('account')}
|
||||
id={suggestion.get('account')}
|
||||
source={suggestion.get('source')}
|
||||
sources={suggestion.get('sources')}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -119,6 +119,17 @@ export default class ColumnSettings extends PureComponent {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role='group' aria-labelledby='notifications-emoji_reaction'>
|
||||
<span id='notifications-emoji_reaction' className='column-settings__section'><FormattedMessage id='notifications.column_settings.emoji_reaction' defaultMessage='Emoji Reactions:' /></span>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'emoji_reaction']} onChange={onChange} label={alertStr} />
|
||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'emoji_reaction']} onChange={this.onPushChange} label={pushStr} />}
|
||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'emoji_reaction']} onChange={onChange} label={showStr} />
|
||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'emoji_reaction']} onChange={onChange} label={soundStr} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role='group' aria-labelledby='notifications-mention'>
|
||||
<span id='notifications-mention' className='column-settings__section'><FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' /></span>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
|
||||
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
||||
import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react';
|
||||
import EmojiReactionIcon from '@/material-icons/400-24px/mood.svg?react';
|
||||
import PersonAddIcon from '@/material-icons/400-24px/person_add.svg?react';
|
||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||
import ReplyAllIcon from '@/material-icons/400-24px/reply_all.svg?react';
|
||||
@@ -14,6 +15,7 @@ import { Icon } from 'mastodon/components/icon';
|
||||
const tooltips = defineMessages({
|
||||
mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
|
||||
favourites: { id: 'notifications.filter.favourites', defaultMessage: 'Favorites' },
|
||||
emojiReactions: { id: 'notifications.filter.emoji_reactions', defaultMessage: 'Stamps' },
|
||||
boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Boosts' },
|
||||
polls: { id: 'notifications.filter.polls', defaultMessage: 'Poll results' },
|
||||
follows: { id: 'notifications.filter.follows', defaultMessage: 'Follows' },
|
||||
@@ -81,6 +83,13 @@ class FilterBar extends PureComponent {
|
||||
>
|
||||
<Icon id='star' icon={StarIcon} />
|
||||
</button>
|
||||
<button
|
||||
className={selectedFilter === 'emoji_reaction' ? 'active' : ''}
|
||||
onClick={this.onClick('emoji_reaction')}
|
||||
title={intl.formatMessage(tooltips.emojiReactions)}
|
||||
>
|
||||
<Icon id='smile-o' icon={EmojiReactionIcon} fixedWidth />
|
||||
</button>
|
||||
<button
|
||||
className={selectedFilter === 'reblog' ? 'active' : ''}
|
||||
onClick={this.onClick('reblog')}
|
||||
|
||||
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
@@ -27,9 +28,11 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
import FollowRequestContainer from '../containers/follow_request_container';
|
||||
|
||||
import Report from './report';
|
||||
import EmojiView from '../../../components/emoji_view';
|
||||
|
||||
const messages = defineMessages({
|
||||
favourite: { id: 'notification.favourite', defaultMessage: '{name} favorited your status' },
|
||||
emojiReaction: { id: 'notification.emoji_reaction', defaultMessage: '{name} reacted your status with emoji' },
|
||||
follow: { id: 'notification.follow', defaultMessage: '{name} followed you' },
|
||||
ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' },
|
||||
poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' },
|
||||
@@ -183,6 +186,7 @@ class Notification extends ImmutablePureComponent {
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
unread={this.props.unread}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -211,6 +215,41 @@ class Notification extends ImmutablePureComponent {
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
);
|
||||
}
|
||||
|
||||
renderEmojiReaction (notification, link) {
|
||||
const { intl, unread } = this.props;
|
||||
const emoji_reaction = notification.get('emoji_reaction');
|
||||
|
||||
return (
|
||||
<HotKeys handlers={this.getHandlers()}>
|
||||
<div className={classNames('notification notification-emoji_reaction focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.emojiReaction, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||
<div className='notification__message'>
|
||||
<div className='notification__emoji_reaction-icon-wrapper'>
|
||||
<EmojiView name={emoji_reaction.get('name')} url={emoji_reaction.get('url')} staticUrl={emoji_reaction.get('static_url')} className='star-icon' fixedWidth />
|
||||
</div>
|
||||
|
||||
<span title={notification.get('created_at')}>
|
||||
<FormattedMessage id='notification.emoji_reaction' defaultMessage='{name} reacted your status with emoji' values={{ name: link }} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<StatusContainer
|
||||
id={notification.get('status')}
|
||||
account={notification.get('account')}
|
||||
muted
|
||||
withDismiss
|
||||
hidden={!!this.props.hidden}
|
||||
getScrollPosition={this.props.getScrollPosition}
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
@@ -241,6 +280,7 @@ class Notification extends ImmutablePureComponent {
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
@@ -276,6 +316,7 @@ class Notification extends ImmutablePureComponent {
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
@@ -311,6 +352,7 @@ class Notification extends ImmutablePureComponent {
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
@@ -352,6 +394,7 @@ class Notification extends ImmutablePureComponent {
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
withoutEmojiReactions={true}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
@@ -421,6 +464,8 @@ class Notification extends ImmutablePureComponent {
|
||||
return this.renderMention(notification);
|
||||
case 'favourite':
|
||||
return this.renderFavourite(notification, link);
|
||||
case 'emoji_reaction':
|
||||
return this.renderEmojiReaction(notification, link);
|
||||
case 'reblog':
|
||||
return this.renderReblog(notification, link);
|
||||
case 'status':
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
favourite,
|
||||
unreblog,
|
||||
unfavourite,
|
||||
emojiReact,
|
||||
} from '../../../actions/interactions';
|
||||
import {
|
||||
hideStatus,
|
||||
@@ -62,6 +63,10 @@ const mapDispatchToProps = dispatch => ({
|
||||
}
|
||||
},
|
||||
|
||||
onEmojiReact (status, emoji) {
|
||||
dispatch(emojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onToggleHidden (status) {
|
||||
if (status.get('hidden')) {
|
||||
dispatch(revealStatus(status.get('id')));
|
||||
|
||||
@@ -167,7 +167,7 @@ class Footer extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
dispatch(quoteCompose(status, router.history));
|
||||
}
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
const { dispatch, askReplyConfirmation, intl } = this.props;
|
||||
@@ -181,7 +181,7 @@ class Footer extends ImmutablePureComponent {
|
||||
} else {
|
||||
this._performQuote();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleOpenClick = e => {
|
||||
if (e.button !== 0 || !history) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import EmojiPickerDropdown from '../../compose/containers/emoji_picker_dropdown_container';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
@@ -11,6 +12,7 @@ import { connect } from 'react-redux';
|
||||
|
||||
import BookmarkIcon from '@/material-icons/400-24px/bookmark-fill.svg?react';
|
||||
import BookmarkBorderIcon from '@/material-icons/400-24px/bookmark.svg?react';
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
||||
@@ -83,6 +85,7 @@ class ActionBar extends PureComponent {
|
||||
onReblog: PropTypes.func.isRequired,
|
||||
onQuote: PropTypes.func,
|
||||
onFavourite: PropTypes.func.isRequired,
|
||||
onEmojiReact: PropTypes.func.isRequired,
|
||||
onBookmark: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func.isRequired,
|
||||
onEdit: PropTypes.func.isRequired,
|
||||
@@ -111,8 +114,8 @@ class ActionBar extends PureComponent {
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
this.props.onQuote(this.props.status, this.props.history);
|
||||
}
|
||||
this.props.onQuote(this.props.status);
|
||||
};
|
||||
|
||||
handleFavouriteClick = () => {
|
||||
this.props.onFavourite(this.props.status);
|
||||
@@ -205,6 +208,10 @@ class ActionBar extends PureComponent {
|
||||
navigator.clipboard.writeText(url);
|
||||
};
|
||||
|
||||
handleEmojiPick = (data) => {
|
||||
this.props.onEmojiReact(this.props.status, data);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { status, relationship, intl } = this.props;
|
||||
const { signedIn, permissions } = this.context.identity;
|
||||
@@ -324,8 +331,9 @@ class ActionBar extends PureComponent {
|
||||
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div>
|
||||
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} /></div>
|
||||
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div>
|
||||
<div className='detailed-status__button'><IconButton disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='quote' iconComponent={QuoteIcon} onClick={this.handleQuoteClick} /></div>
|
||||
<div className='detailed-status__button'><IconButton disabled={!publicStatus} title={StatusActionBar.quoteTitle(intl, messages, publicStatus)} icon='format-quote' iconComponent={FormatQuoteIcon} onClick={this.handleQuoteClick} /></div>
|
||||
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>
|
||||
<div className='detailed-status__button'><EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} /></div>
|
||||
<div className='detailed-status__action-bar-dropdown'>
|
||||
<DropdownMenuContainer icon='ellipsis-h' iconComponent={MoreHorizIcon} status={status} items={menu} direction='left' title={intl.formatMessage(messages.more)} />
|
||||
</div>
|
||||
|
||||
@@ -152,9 +152,9 @@ export default class Card extends PureComponent {
|
||||
};
|
||||
|
||||
if (largeImage && card.get('type') === 'video') {
|
||||
thumbnailStyle.aspectRatio = `16 / 9`;
|
||||
thumbnailStyle.aspectRatio = `${quote ? 8 : 16} / 9`;
|
||||
} else if (largeImage) {
|
||||
thumbnailStyle.aspectRatio = '1.91 / 1';
|
||||
thumbnailStyle.aspectRatio = `1.91 / ${quote ? 2 : 1}`;
|
||||
} else {
|
||||
thumbnailStyle.aspectRatio = 1;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { FormattedDate, FormattedMessage } from 'react-intl';
|
||||
import { FormattedDate, FormattedMessage, injectIntl } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import StatusEmojiReactionsBar from '../../../components/status_emoji_reactions_bar';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
|
||||
@@ -53,6 +54,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
onToggleMediaVisibility: PropTypes.func,
|
||||
onQuoteToggleMediaVisibility: PropTypes.func,
|
||||
...WithRouterPropTypes,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onUnEmojiReact: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
@@ -62,7 +65,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
handleAccountClick = (e) => {
|
||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.props.history) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
const acct = e.currentTarget.getAttribute('data-acct');
|
||||
this.props.history.push(`/@${acct}`);
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
@@ -78,17 +82,15 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
handleExpandedQuoteToggle = () => {
|
||||
this.props.onQuoteToggleHidden(this.props.status);
|
||||
}
|
||||
};
|
||||
|
||||
handleQuoteClick = () => {
|
||||
if (!this.props) {
|
||||
return;
|
||||
if (this.props.history) {
|
||||
const status = this._properStatus();
|
||||
this.props.history.push(`/@${status.getIn(['quote', 'account', 'acct'])}/${status.getIn(['quote', 'id'])}`);
|
||||
}
|
||||
};
|
||||
|
||||
const { status } = this.props;
|
||||
this.props.history.push(`/statuses/${status.getIn(['quote', 'id'])}`);
|
||||
}
|
||||
|
||||
handleQuoteUserClick = () =>{
|
||||
if (!this.props) {
|
||||
return;
|
||||
@@ -161,7 +163,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
render () {
|
||||
const status = this._properStatus();
|
||||
const outerStyle = { boxSizing: 'border-box' };
|
||||
const { compact, pictureInPicture, quoteMuted } = this.props;
|
||||
const { compact, pictureInPicture, quoteMuted } = this.props;
|
||||
|
||||
if (!status) {
|
||||
return null;
|
||||
@@ -172,6 +174,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
const reblogIcon = 'retweet';
|
||||
const reblogIconComponent = RepeatIcon;
|
||||
let favouriteLink = '';
|
||||
let emojiReactionsLink = '';
|
||||
let edited = '';
|
||||
|
||||
if (this.props.measureHeight) {
|
||||
@@ -180,11 +183,19 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||
|
||||
const identity = (status, _0, _1, quote = false) => (
|
||||
<a href={`/@${status.getIn(['account', 'acct'])}`} onClick={quote ? this.handleQuoteUserClick : this.handleAccountClick} data-acct={status.getIn(['account', 'acct'])} className='detailed-status__display-name'>
|
||||
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={46} /></div>
|
||||
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
||||
</a>
|
||||
const identity = (status, _, quote) => (
|
||||
<>
|
||||
{status.get('visibility') === 'direct' && (
|
||||
<div className='status__prepend'>
|
||||
<div className='status__prepend-icon-wrapper'><Icon id='at' className='status__prepend-icon' fixedWidth /></div>
|
||||
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
|
||||
</div>
|
||||
)}
|
||||
<a href={`/@${status.getIn(['account', 'acct'])}`} data-acct={status.getIn(['account', 'acct'])} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
||||
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={quote ? 20 : 48} /></div>
|
||||
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
||||
</a>
|
||||
</>
|
||||
);
|
||||
|
||||
const media = (status, quote = false) => {
|
||||
@@ -251,11 +262,17 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
);
|
||||
}
|
||||
} else if (status.get('spoiler_text').length === 0) {
|
||||
return <Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} quote={quote} />;
|
||||
return (<Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia}
|
||||
card={status.get('card', null)} quote={quote} />);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let emojiReactionsBar = null;
|
||||
if (status.get('emoji_reactions')) {
|
||||
const emojiReactions = status.get('emoji_reactions');
|
||||
emojiReactionsBar = <StatusEmojiReactionsBar emojiReactions={emojiReactions} status={status} onEmojiReact={this.props.onEmojiReact} onUnEmojiReact={this.props.onUnEmojiReact} />;
|
||||
}
|
||||
|
||||
if (status.get('application')) {
|
||||
applicationLink = <> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener noreferrer'>{status.getIn(['application', 'name'])}</a></>;
|
||||
}
|
||||
@@ -310,6 +327,22 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
if (this.context.router) {
|
||||
emojiReactionsLink = (
|
||||
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/emoji_reactions`} className='detailed-status__link'>
|
||||
<Icon id='smile-o' />
|
||||
<FormattedMessage id='status.emoji' defaultMessage='Emoji' />
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
emojiReactionsLink = (
|
||||
<a href={`/interact/${status.get('id')}?type=emoji_reactions`} className='detailed-status__link' onClick={this.handleModalLink}>
|
||||
<Icon id='smile-o' />
|
||||
<FormattedMessage id='status.emoji' defaultMessage='Emoji' />
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
if (status.get('edited_at')) {
|
||||
edited = (
|
||||
<>
|
||||
@@ -331,10 +364,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
|
||||
</div>
|
||||
)}
|
||||
<a href={`/@${status.getIn(['account', 'acct'])}`} onClick={this.handleAccountClick} className='detailed-status__display-name'>
|
||||
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={46} /></div>
|
||||
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
|
||||
</a>
|
||||
{identity(status, null, false)}
|
||||
|
||||
<StatusContent
|
||||
status={status}
|
||||
@@ -350,10 +380,12 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
{expanded && hashtagBar}
|
||||
|
||||
{emojiReactionsBar}
|
||||
|
||||
<div className='detailed-status__meta'>
|
||||
<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' />
|
||||
</a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink}
|
||||
</a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink} · {emojiReactionsLink}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -362,4 +394,4 @@ class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
}
|
||||
|
||||
export default withRouter(DetailedStatus);
|
||||
export default withRouter(DetailedStatus);
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
unfavourite,
|
||||
pin,
|
||||
unpin,
|
||||
emojiReact,
|
||||
unEmojiReact,
|
||||
} from '../../../actions/interactions';
|
||||
import { openModal } from '../../../actions/modal';
|
||||
import { initMuteModal } from '../../../actions/mutes';
|
||||
@@ -100,6 +102,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||
}
|
||||
},
|
||||
|
||||
onEmojiReact (status, emoji) {
|
||||
dispatch(emojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onUnEmojiReact (status, emoji) {
|
||||
dispatch(unEmojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onPin (status) {
|
||||
if (status.get('pinned')) {
|
||||
dispatch(unpin(status));
|
||||
|
||||
@@ -41,6 +41,8 @@ import {
|
||||
import {
|
||||
favourite,
|
||||
unfavourite,
|
||||
emojiReact,
|
||||
unEmojiReact,
|
||||
bookmark,
|
||||
unbookmark,
|
||||
reblog,
|
||||
@@ -255,7 +257,7 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
handleToggleQuoteMediaVisibility = () => {
|
||||
this.setState({ showQuoteMedia: !this.state.showQuoteMedia });
|
||||
}
|
||||
};
|
||||
|
||||
handleFavouriteClick = (status) => {
|
||||
const { dispatch } = this.props;
|
||||
@@ -279,6 +281,16 @@ class Status extends ImmutablePureComponent {
|
||||
}
|
||||
};
|
||||
|
||||
handleEmojiReact = (status, emoji) => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(emojiReact(status, emoji));
|
||||
};
|
||||
|
||||
handleUnEmojiReact = (status, emoji) => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(unEmojiReact(status, emoji));
|
||||
};
|
||||
|
||||
handlePin = (status) => {
|
||||
if (status.get('pinned')) {
|
||||
this.props.dispatch(unpin(status));
|
||||
@@ -327,7 +339,7 @@ class Status extends ImmutablePureComponent {
|
||||
} else {
|
||||
dispatch(quoteCompose(status, this.props.history));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleModalReblog = (status, privacy) => {
|
||||
this.props.dispatch(reblog(status, privacy));
|
||||
@@ -450,7 +462,7 @@ class Status extends ImmutablePureComponent {
|
||||
} else {
|
||||
this.props.dispatch(hideQuote(status.get('id')));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleToggleAll = () => {
|
||||
const { status, ancestorsIds, descendantsIds } = this.props;
|
||||
@@ -749,6 +761,8 @@ class Status extends ImmutablePureComponent {
|
||||
onToggleMediaVisibility={this.handleToggleMediaVisibility}
|
||||
onToggleQuoteMediaVisibility={this.handleToggleQuoteMediaVisibility}
|
||||
pictureInPicture={pictureInPicture}
|
||||
onEmojiReact={this.handleEmojiReact}
|
||||
onUnEmojiReact={this.handleUnEmojiReact}
|
||||
/>
|
||||
|
||||
<ActionBar
|
||||
@@ -756,6 +770,7 @@ class Status extends ImmutablePureComponent {
|
||||
status={status}
|
||||
onReply={this.handleReplyClick}
|
||||
onFavourite={this.handleFavouriteClick}
|
||||
onEmojiReact={this.handleEmojiReact}
|
||||
onReblog={this.handleReblogClick}
|
||||
onQuote={this.handleQuoteClick}
|
||||
onBookmark={this.handleBookmarkClick}
|
||||
|
||||
@@ -31,10 +31,9 @@ import NavigationPanel from './navigation_panel';
|
||||
|
||||
import { place_tab_bar_at_bottom } from 'mastodon/initial_state';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import TabsBar from './tabs_bar';
|
||||
|
||||
import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
|
||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||
|
||||
const componentMap = {
|
||||
'COMPOSE': Compose,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.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 ListAltIcon from '@/material-icons/400-24px/list_alt.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 SettingsIcon from '@/material-icons/400-24px/settings-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 { NavigationPortal } from 'mastodon/components/navigation_portal';
|
||||
import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
|
||||
@@ -94,7 +94,7 @@ class NavigationPanel extends Component {
|
||||
)}
|
||||
|
||||
{trendsEnabled ? (
|
||||
<ColumnLink transparent to='/explore' icon='hashtag' iconComponent={TagIcon} text={intl.formatMessage(messages.explore)} />
|
||||
<ColumnLink transparent to='/explore' icon='hashtag' iconComponent={ExploreIcon} text={intl.formatMessage(messages.explore)} />
|
||||
) : (
|
||||
<ColumnLink transparent to='/search' icon='search' iconComponent={SearchIcon} text={intl.formatMessage(messages.search)} />
|
||||
)}
|
||||
|
||||
@@ -4,10 +4,10 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ColumnLink from './column_link';
|
||||
import NotificationsCounterIcon from './notifications_counter_icon';
|
||||
|
||||
import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
|
||||
import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
|
||||
import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
|
||||
import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
|
||||
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import PublicIcon from '@/material-icons/400-24px/public.svg?react';
|
||||
import SearchIcon from '@/material-icons/400-24px/search.svg?react';
|
||||
|
||||
const messages = defineMessages({
|
||||
home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
|
||||
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
Following,
|
||||
Reblogs,
|
||||
Favourites,
|
||||
EmojiReactions,
|
||||
DirectTimeline,
|
||||
HashtagTimeline,
|
||||
Notifications,
|
||||
@@ -214,6 +215,7 @@ class SwitchingColumnsArea extends PureComponent {
|
||||
<WrappedRoute path='/directory' component={Directory} content={children} />
|
||||
<WrappedRoute path={['/explore', '/search']} component={Explore} content={children} />
|
||||
<WrappedRoute path={['/publish', '/statuses/new']} component={Compose} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/emoji_reactions' component={EmojiReactions} content={children} />
|
||||
|
||||
<WrappedRoute path={['/@:acct', '/accounts/:id']} exact component={AccountTimeline} content={children} />
|
||||
<WrappedRoute path='/@:acct/tagged/:tagged?' exact component={AccountTimeline} content={children} />
|
||||
@@ -224,6 +226,7 @@ class SwitchingColumnsArea extends PureComponent {
|
||||
<WrappedRoute path='/@:acct/:statusId' exact component={Status} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/reblogs' component={Reblogs} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/favourites' component={Favourites} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/emoji_reactions' component={EmojiReactions} content={children} />
|
||||
|
||||
{/* Legacy routes, cannot be easily factored with other routes because they share a param name */}
|
||||
<WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} />
|
||||
|
||||
@@ -82,6 +82,10 @@ export function Favourites () {
|
||||
return import(/* webpackChunkName: "features/favourites" */'../../favourites');
|
||||
}
|
||||
|
||||
export function EmojiReactions () {
|
||||
return import(/* webpackChunkName: "features/favourites" */'../../emoji_reactions');
|
||||
}
|
||||
|
||||
export function FollowRequests () {
|
||||
return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests');
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"account.follows.empty": "Die gebruiker volg nog niemand.",
|
||||
"account.go_to_profile": "Gaan na profiel",
|
||||
"account.hide_reblogs": "Versteek plasings wat deur @{name} aangestuur is",
|
||||
"account.in_memoriam": "Ter nagedagtenis.",
|
||||
"account.joined_short": "Aangesluit",
|
||||
"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.",
|
||||
@@ -71,6 +72,7 @@
|
||||
"bundle_column_error.network.title": "Netwerkfout",
|
||||
"bundle_column_error.retry": "Probeer weer",
|
||||
"bundle_column_error.return": "Keer terug na die tuisblad",
|
||||
"bundle_column_error.routing.title": "404",
|
||||
"bundle_modal_error.close": "Sluit",
|
||||
"bundle_modal_error.message": "Die laai van die komponent het iewers skeefgeloop.",
|
||||
"bundle_modal_error.retry": "Probeer weer",
|
||||
@@ -149,6 +151,8 @@
|
||||
"emoji_button.food": "Eet- en drinkgoed",
|
||||
"emoji_button.nature": "Natuur",
|
||||
"emoji_button.not_found": "Geen passende emoji gevind nie",
|
||||
"emoji_button.objects": "Voorwerpe",
|
||||
"emoji_button.people": "Mense",
|
||||
"emoji_button.search": "Soek...",
|
||||
"emoji_button.search_results": "Soekresultate",
|
||||
"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.notifications": "Jy het nog geen kennisgewings nie. Interaksie van ander mense met jou, sal hier vertoon.",
|
||||
"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",
|
||||
"firehose.local": "Hierdie bediener",
|
||||
"firehose.remote": "Ander bedieners",
|
||||
"footer.about": "Oor",
|
||||
"footer.directory": "Profielgids",
|
||||
"footer.get_app": "Kry die app",
|
||||
@@ -170,14 +179,21 @@
|
||||
"footer.privacy_policy": "Privaatheidsbeleid",
|
||||
"footer.source_code": "Wys bronkode",
|
||||
"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.tag_toggle": "Voeg meer etikette by hierdie kolom",
|
||||
"hashtag.follow": "Volg hutsetiket",
|
||||
"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.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.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.blocked": "Vertoon lys van geblokkeerde gebruikers",
|
||||
"keyboard_shortcuts.boost": "Stuur aan",
|
||||
@@ -209,8 +225,11 @@
|
||||
"keyboard_shortcuts.toot": "Begin ’n nuwe plasing",
|
||||
"keyboard_shortcuts.unfocus": "Fokus uit van teksveld/soekveld",
|
||||
"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.title": "Hierdie profiel is deur moderators van {domain} versteek.",
|
||||
"link_preview.author": "Deur {name}",
|
||||
"lists.account.add": "Voeg by lys",
|
||||
"lists.account.remove": "Verwyder vanaf lys",
|
||||
"lists.delete": "Verwyder lys",
|
||||
@@ -237,6 +256,7 @@
|
||||
"notification.reblog": "{name} het jou plasing aangestuur",
|
||||
"notifications.column_settings.push": "Stootkennisgewings",
|
||||
"notifications.column_settings.reblog": "Aangestuurde plasings:",
|
||||
"notifications.column_settings.sound": "Speel klank",
|
||||
"notifications.column_settings.status": "Nuwe plasings:",
|
||||
"notifications.column_settings.unread_notifications.highlight": "Lig ongelese kennisgewings uit",
|
||||
"notifications.filter.boosts": "Aangestuurde plasings",
|
||||
@@ -300,5 +320,8 @@
|
||||
"upload_form.audio_description": "Describe for people with hearing loss",
|
||||
"upload_form.description": "Describe for the visually impaired",
|
||||
"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"
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"account.blocked": "محظور",
|
||||
"account.browse_more_on_origin_server": "تصفح المزيد في الملف الشخصي الأصلي",
|
||||
"account.cancel_follow_request": "إلغاء طلب المتابعة",
|
||||
"account.copy": "نسخ الرابط إلى الملف الشخصي",
|
||||
"account.direct": "إشارة خاصة لـ @{name}",
|
||||
"account.disable_notifications": "توقف عن إشعاري عندما ينشر @{name}",
|
||||
"account.domain_blocked": "اسم النِّطاق محظور",
|
||||
@@ -31,6 +32,7 @@
|
||||
"account.featured_tags.last_status_never": "لا توجد رسائل",
|
||||
"account.featured_tags.title": "وسوم {name} المميَّزة",
|
||||
"account.follow": "متابعة",
|
||||
"account.follow_back": "تابعه بدورك",
|
||||
"account.followers": "مُتابِعون",
|
||||
"account.followers.empty": "لا أحدَ يُتابع هذا المُستخدم إلى حد الآن.",
|
||||
"account.followers_counter": "{count, plural, zero{لا مُتابع} one {مُتابعٌ واحِد} two {مُتابعانِ اِثنان} few {{counter} مُتابِعين} many {{counter} مُتابِعًا} other {{counter} مُتابع}}",
|
||||
@@ -51,6 +53,7 @@
|
||||
"account.mute_notifications_short": "كتم الإشعارات",
|
||||
"account.mute_short": "اكتم",
|
||||
"account.muted": "مَكتوم",
|
||||
"account.mutual": "متبادل",
|
||||
"account.no_bio": "لم يتم تقديم وصف.",
|
||||
"account.open_original_page": "افتح الصفحة الأصلية",
|
||||
"account.posts": "منشورات",
|
||||
@@ -143,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "مُقفَل",
|
||||
"compose_form.placeholder": "فِيمَ تُفكِّر؟",
|
||||
"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_single": "تغيِير الاستطلاع للسماح باِخيار واحد فقط",
|
||||
"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.unmarked": "إضافة تحذير للمحتوى",
|
||||
"compose_form.spoiler_placeholder": "تحذير المحتوى (اختياري)",
|
||||
"confirmation_modal.cancel": "إلغاء",
|
||||
"confirmations.block.block_and_report": "حظره والإبلاغ عنه",
|
||||
"confirmations.block.confirm": "حظر",
|
||||
@@ -179,6 +190,7 @@
|
||||
"conversation.mark_as_read": "اعتبرها كمقروءة",
|
||||
"conversation.open": "اعرض المحادثة",
|
||||
"conversation.with": "مع {names}",
|
||||
"copy_icon_button.copied": "نُسِخ إلى الحافظة",
|
||||
"copypaste.copied": "تم نسخه",
|
||||
"copypaste.copy_to_clipboard": "نسخ إلى الحافظة",
|
||||
"directory.federated": "مِن الفديفرس المعروف",
|
||||
@@ -210,6 +222,7 @@
|
||||
"emoji_button.search_results": "نتائج البحث",
|
||||
"emoji_button.symbols": "رموز",
|
||||
"emoji_button.travel": "الأماكن والسفر",
|
||||
"empty_column.account_hides_collections": "اختار هذا المستخدم عدم إتاحة هذه المعلومات للعامة",
|
||||
"empty_column.account_suspended": "حساب معلق",
|
||||
"empty_column.account_timeline": "لا توجد منشورات هنا!",
|
||||
"empty_column.account_unavailable": "الملف التعريفي غير متوفر",
|
||||
@@ -264,6 +277,11 @@
|
||||
"follow_request.authorize": "ترخيص",
|
||||
"follow_request.reject": "رفض",
|
||||
"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": "الوسوم المتابَعة",
|
||||
"footer.about": "عن",
|
||||
"footer.directory": "دليل الصفحات التعريفية",
|
||||
@@ -290,13 +308,9 @@
|
||||
"hashtag.follow": "اتبع الوسم",
|
||||
"hashtag.unfollow": "ألغِ متابعة الوسم",
|
||||
"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.show_reblogs": "اعرض المعاد نشرها",
|
||||
"home.column_settings.show_replies": "اعرض الردود",
|
||||
"home.explore_prompt.body": "سوف يحتوي خيط أخبارك الرئيسي على مزيج من المنشورات مِنها التي تحتوي على وسوم اخترتَ متابعتها، وأشخاص اخترتَ متابعتهم والمنشورات التي أعادوا نشرها. ومع ذلك، إن لا زال خيط أخبارك يبدو هادئا جدا، ماذا لو:",
|
||||
"home.explore_prompt.title": "هذه هي صفحتك الرئيسة في ماستدون.",
|
||||
"home.hide_announcements": "إخفاء الإعلانات",
|
||||
"home.pending_critical_update.body": "يرجى تحديث خادم ماستدون في أقرب وقت ممكن!",
|
||||
"home.pending_critical_update.link": "اطّلع على التحديثات",
|
||||
@@ -377,6 +391,7 @@
|
||||
"lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
|
||||
"lists.subheading": "قوائمك",
|
||||
"load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}",
|
||||
"loading_indicator.label": "جاري التحميل…",
|
||||
"media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}",
|
||||
"moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.",
|
||||
"mute_modal.duration": "المدة",
|
||||
@@ -464,6 +479,17 @@
|
||||
"onboarding.follows.empty": "نأسف، لا يمكن عرض نتائج في الوقت الحالي. جرب البحث أو انتقل لصفحة الاستكشاف لإيجاد أشخاص للمتابعة، أو حاول مرة أخرى.",
|
||||
"onboarding.follows.lead": "مقتطفات خيطك الرئيس هي الطريقة الأساسية لتجربة ماستدون. كلما زاد عدد الأشخاص الذين تتبعهم، كلما زاد خيط أخبارك نشاطا وإثارة للاهتمام. بداية، إليك بعض الاقتراحات:",
|
||||
"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.message": "أنا {username} في #Mastodon! تعال لمتابعتي على {url}",
|
||||
"onboarding.share.next_steps": "الخطوات المحتملة التالية:",
|
||||
@@ -497,9 +523,18 @@
|
||||
"poll_button.add_poll": "إضافة استطلاع للرأي",
|
||||
"poll_button.remove_poll": "إزالة استطلاع الرأي",
|
||||
"privacy.change": "اضبط خصوصية المنشور",
|
||||
"privacy.direct.long": "كل من ذُكر في المنشور",
|
||||
"privacy.direct.short": "أشخاص محددون",
|
||||
"privacy.private.long": "متابعيك فقط",
|
||||
"privacy.private.short": "للمتابِعين",
|
||||
"privacy.public.long": "أي شخص على أو خارج ماستدون",
|
||||
"privacy.public.short": "للعامة",
|
||||
"privacy.unlisted.additional": "هذا يتصرف بالضبط مثل النشر للعامة، باستثناء أن المنشور لن يظهر في الموجزات الحية أو في الوسوم أو في الإستكشاف، أو في نتائج بحث ماستدون، حتى وإن قمت بتفعيله على مستوى الحساب.",
|
||||
"privacy.unlisted.long": "خوارزميات أقل",
|
||||
"privacy.unlisted.short": "للعامة دون صخب",
|
||||
"privacy_policy.last_updated": "آخر تحديث {date}",
|
||||
"privacy_policy.title": "سياسة الخصوصية",
|
||||
"recommended": "موصى به",
|
||||
"refresh": "أنعِش",
|
||||
"regeneration_indicator.label": "جارٍ التحميل…",
|
||||
"regeneration_indicator.sublabel": "جارٍ تجهيز موجزات خيطك الرئيس!",
|
||||
@@ -514,7 +549,9 @@
|
||||
"relative_time.minutes": "{number}د",
|
||||
"relative_time.seconds": "{number}ثا",
|
||||
"relative_time.today": "اليوم",
|
||||
"reply_indicator.attachments": "{count, plural, zero {}one {# مرفق} two {# المرفقات} few {# مرفقات} many {# مرفقات} other {# مرفقًا}}",
|
||||
"reply_indicator.cancel": "إلغاء",
|
||||
"reply_indicator.poll": "استطلاع رأي",
|
||||
"report.block": "حظر",
|
||||
"report.block_explanation": "لن ترى منشوراته ولن يمكنه متابعتك أو رؤية منشوراتك، سيكون بديهيا له أنه مكتوم.",
|
||||
"report.categories.legal": "إشعارات قانونية",
|
||||
@@ -570,6 +607,7 @@
|
||||
"search.quick_action.status_search": "المنشورات المطابقة لـ {x}",
|
||||
"search.search_or_paste": "ابحث أو أدخل رابطا تشعبيا URL",
|
||||
"search_popout.full_text_search_disabled_message": "غير متوفر على {domain}.",
|
||||
"search_popout.full_text_search_logged_out_message": "متاح فقط عند تسجيل الدخول.",
|
||||
"search_popout.language_code": "رمز لغة ISO",
|
||||
"search_popout.options": "خيارات البحث",
|
||||
"search_popout.quick_actions": "الإجراءات السريعة",
|
||||
|
||||
@@ -199,6 +199,11 @@
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"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_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.directory": "Direutoriu de perfiles",
|
||||
"footer.get_app": "Consiguir l'aplicación",
|
||||
|
||||
@@ -146,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "закрыты",
|
||||
"compose_form.placeholder": "Што здарылася?",
|
||||
"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_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.unmarked": "Дадаць папярэджанне аб змесціве",
|
||||
"compose_form.spoiler_placeholder": "Папярэджанне аб змесціве (неабавязкова)",
|
||||
"confirmation_modal.cancel": "Скасаваць",
|
||||
"confirmations.block.block_and_report": "Заблакіраваць і паскардзіцца",
|
||||
"confirmations.block.confirm": "Заблакіраваць",
|
||||
@@ -269,6 +277,17 @@
|
||||
"follow_request.authorize": "Аўтарызацыя",
|
||||
"follow_request.reject": "Адхіліць",
|
||||
"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": "Падпіскі",
|
||||
"footer.about": "Пра нас",
|
||||
"footer.directory": "Дырэкторыя профіляў",
|
||||
@@ -295,13 +314,9 @@
|
||||
"hashtag.follow": "Падпісацца на хэштэг",
|
||||
"hashtag.unfollow": "Адпісацца ад хэштэга",
|
||||
"hashtags.and_other": "…і яшчэ {count, plural, other {#}}",
|
||||
"home.actions.go_to_explore": "Паглядзіце, што ў трэндзе",
|
||||
"home.actions.go_to_suggestions": "Знайсці людзей, каб падпісацца",
|
||||
"home.column_settings.basic": "Асноўныя",
|
||||
"home.column_settings.show_reblogs": "Паказаць пашырэнні",
|
||||
"home.column_settings.show_replies": "Паказваць адказы",
|
||||
"home.explore_prompt.body": "Ваша галоўная стужка змяшчае сумесь допісаў з хэштэгамі, за якімі вы вырашылі сачыць, допісаў ад людзей, за якімі вы вырашылі сачыць, і допісаў, якія яны пашыраюць. Зараз усё выглядае даволі ціха, так што як наконт:",
|
||||
"home.explore_prompt.title": "Гэта ваша апорная кропка ў Mastodon.",
|
||||
"home.hide_announcements": "Схаваць аб'явы",
|
||||
"home.pending_critical_update.body": "Калі ласка, абнавіце свой сервер Mastodon як мага хутчэй!",
|
||||
"home.pending_critical_update.link": "Прагледзець абнаўленні",
|
||||
@@ -514,7 +529,15 @@
|
||||
"poll_button.add_poll": "Дадаць апытанне",
|
||||
"poll_button.remove_poll": "Выдаліць апытанне",
|
||||
"privacy.change": "Змяніць прыватнасць допісу",
|
||||
"privacy.direct.long": "Усе згаданыя ў допісе",
|
||||
"privacy.direct.short": "Канкрэтныя людзі",
|
||||
"privacy.private.long": "Толькі вашыя падпісчыкі",
|
||||
"privacy.private.short": "Падпісчыкі",
|
||||
"privacy.public.long": "Усе, хто ёсць і каго няма ў Mastodon",
|
||||
"privacy.public.short": "Публічны",
|
||||
"privacy.unlisted.additional": "Паводзіць сябе гэтак жа, як і публічны, за выключэннем таго, што пост не будзе адлюстроўвацца ў жывой стужцы, хэштэгах, аглядзе або ў пошуку Mastodon, нават калі вы ўключылі бачнасць у пошуку ў наладах.",
|
||||
"privacy.unlisted.long": "Менш фанфар ад алгарытмаў",
|
||||
"privacy.unlisted.short": "Ціхі публічны",
|
||||
"privacy_policy.last_updated": "Адноўлена {date}",
|
||||
"privacy_policy.title": "Палітыка канфідэнцыйнасці",
|
||||
"recommended": "Рэкамендуем",
|
||||
@@ -532,7 +555,9 @@
|
||||
"relative_time.minutes": "{number} хв",
|
||||
"relative_time.seconds": "{number} с",
|
||||
"relative_time.today": "сёння",
|
||||
"reply_indicator.attachments": "{count, plural, one {# далучэнне} few {# далучэнні} many {# далучэнняў} other {# далучэння}}",
|
||||
"reply_indicator.cancel": "Скасаваць",
|
||||
"reply_indicator.poll": "Апытанне",
|
||||
"report.block": "Заблакіраваць",
|
||||
"report.block_explanation": "Вы перастанеце бачыць допісы гэтага карыстальніка. Ён не зможа сачыць за вамі і бачыць вашы допісы. Ён зможа зразумець, што яго заблакіравалі.",
|
||||
"report.categories.legal": "Права",
|
||||
@@ -664,7 +689,7 @@
|
||||
"status.show_more": "Паказаць болей",
|
||||
"status.show_more_all": "Разгарнуць усё",
|
||||
"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.translated_from_with": "Перакладзена з {lang} з дапамогай {provider}",
|
||||
"status.uncached_media_warning": "Перадпрагляд недаступны",
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
"about.contact": "За контакти:",
|
||||
"about.disclaimer": "Mastodon е безплатен софтуер с отворен изходен код и търговска марка на Mastodon gGmbH.",
|
||||
"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.title": "Ограничено",
|
||||
"about.domain_blocks.suspended.explanation": "Никакви данни от този сървър няма да се обработват, съхраняват или обменят, правещи невъзможно всяко взаимодействие или комуникация с потребители от тези сървъри.",
|
||||
"about.domain_blocks.suspended.title": "Спряно",
|
||||
"about.not_available": "Тази информация не е била направена налична на този сървър.",
|
||||
"about.not_available": "Тази информация не е публична на този сървър.",
|
||||
"about.powered_by": "Децентрализирана социална мрежа, захранвана от {mastodon}",
|
||||
"about.rules": "Правила на сървъра",
|
||||
"account.account_note_header": "Бележка",
|
||||
@@ -110,7 +110,7 @@
|
||||
"column.about": "Относно",
|
||||
"column.blocks": "Блокирани потребители",
|
||||
"column.bookmarks": "Отметки",
|
||||
"column.community": "Локална часова ос",
|
||||
"column.community": "Локален инфопоток",
|
||||
"column.direct": "Частни споменавания",
|
||||
"column.directory": "Разглеждане на профили",
|
||||
"column.domain_blocks": "Блокирани домейни",
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "Вашият акаунт не е в положение {locked}. Всеки може да ви последва, за да разглежда публикациите ви само за последователи.",
|
||||
"compose_form.lock_disclaimer.lock": "заключено",
|
||||
"compose_form.placeholder": "Какво мислите?",
|
||||
"compose_form.poll.add_option": "Добавяне на избор",
|
||||
"compose_form.poll.duration": "Времетраене на анкетата",
|
||||
"compose_form.poll.multiple": "Множествен избор",
|
||||
"compose_form.poll.option_placeholder": "Избор {number}",
|
||||
"compose_form.poll.remove_option": "Премахване на тази възможност",
|
||||
"compose_form.poll.single": "Подберете нещо",
|
||||
"compose_form.poll.switch_to_multiple": "Промяна на анкетата, за да се позволят множество възможни избора",
|
||||
"compose_form.poll.switch_to_single": "Промяна на анкетата, за да се позволи един възможен избор",
|
||||
@@ -203,7 +201,7 @@
|
||||
"disabled_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен.",
|
||||
"dismissable_banner.community_timeline": "Ето най-скорошните публични публикации от хора, чиито акаунти са разположени в {domain}.",
|
||||
"dismissable_banner.dismiss": "Отхвърляне",
|
||||
"dismissable_banner.explore_links": "Тези новини се разказват от хората в този и други сървъри на децентрализираната мрежа точно сега.",
|
||||
"dismissable_banner.explore_links": "Това са най-споделяните новини в социалната мрежа днес. По-нови истории, споделени от повече хора се показват по-напред.",
|
||||
"dismissable_banner.explore_statuses": "Има публикации през социалната мрежа, които днес набират популярност. По-новите публикации с повече подсилвания и любими са класирани по-високо.",
|
||||
"dismissable_banner.explore_tags": "Тези хаштагове сега набират популярност сред хората в този и други сървъри на децентрализирата мрежа.",
|
||||
"dismissable_banner.public_timeline": "Ето най-новите обществени публикации от хора в социална мрежа, която хората в {domain} следват.",
|
||||
@@ -224,16 +222,16 @@
|
||||
"emoji_button.search_results": "Резултати от търсене",
|
||||
"emoji_button.symbols": "Символи",
|
||||
"emoji_button.travel": "Пътуване и места",
|
||||
"empty_column.account_hides_collections": "Този потребител е избрал да не прави това сведение достъпно",
|
||||
"empty_column.account_hides_collections": "Този потребител е избрал да не дава тази информация",
|
||||
"empty_column.account_suspended": "Спрян акаунт",
|
||||
"empty_column.account_timeline": "Тук няма публикации!",
|
||||
"empty_column.account_unavailable": "Профилът не е наличен",
|
||||
"empty_column.blocks": "Още не сте блокирали никакви потребители.",
|
||||
"empty_column.bookmarked_statuses": "Още не сте отметнали публикации. Отметвайки някоя, то тя ще се покаже тук.",
|
||||
"empty_column.community": "Местната часова ос е празна. Напишете нещо обществено, за да завъртите нещата!",
|
||||
"empty_column.community": "Локалният инфопоток е празен. Публикувайте нещо, за да започнете!",
|
||||
"empty_column.direct": "Още нямате никакви частни споменавания. Тук ще се показват, изпращайки или получавайки едно.",
|
||||
"empty_column.domain_blocks": "Още няма блокирани домейни.",
|
||||
"empty_column.explore_statuses": "Няма нищо налагащо се в момента. Проверете пак по-късно!",
|
||||
"empty_column.explore_statuses": "Няма тенденции в момента. Проверете пак по-късно!",
|
||||
"empty_column.favourited_statuses": "Още нямате никакви любими публикации. Правейки любима, то тя ще се покаже тук.",
|
||||
"empty_column.favourites": "Още никого не е слагал публикацията в любими. Когато някой го направи, този човек ще се покаже тук.",
|
||||
"empty_column.follow_requests": "Още нямате заявки за последване. Получавайки такава, то тя ще се покаже тук.",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Упълномощаване",
|
||||
"follow_request.reject": "Отхвърляне",
|
||||
"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": "Последвани хаштагове",
|
||||
"footer.about": "Относно",
|
||||
"footer.directory": "Директория на профилите",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Следване на хаштаг",
|
||||
"hashtag.unfollow": "Спиране на следване на хаштаг",
|
||||
"hashtags.and_other": "…и {count, plural, other {# още}}",
|
||||
"home.actions.go_to_explore": "Вижте какво изгрява",
|
||||
"home.actions.go_to_suggestions": "Намиране на хора за следване",
|
||||
"home.column_settings.basic": "Основно",
|
||||
"home.column_settings.show_reblogs": "Показване на подсилванията",
|
||||
"home.column_settings.show_replies": "Показване на отговорите",
|
||||
"home.explore_prompt.body": "Вашият начален инфоканал ще е смес на публикации от хаштаговете, които сте избрали да следвате, избраните хора да следвате, а и публикациите, които са подсилили. Ако изглежда твърде тихо в момента, то може да искате да:",
|
||||
"home.explore_prompt.title": "Това е началната ви база с Mastodon.",
|
||||
"home.hide_announcements": "Скриване на оповестяванията",
|
||||
"home.pending_critical_update.body": "Обновете сървъра си в Mastodon възможно най-скоро!",
|
||||
"home.pending_critical_update.link": "Преглед на обновяванията",
|
||||
@@ -348,10 +353,10 @@
|
||||
"keyboard_shortcuts.favourites": "Отваряне на списъка с любими",
|
||||
"keyboard_shortcuts.federated": "Отваряне на федерирания инфопоток",
|
||||
"keyboard_shortcuts.heading": "Клавишни съчетания",
|
||||
"keyboard_shortcuts.home": "Отваряне на началната часова ос",
|
||||
"keyboard_shortcuts.home": "Отваряне на личния инфопоток",
|
||||
"keyboard_shortcuts.hotkey": "Бърз клавиш",
|
||||
"keyboard_shortcuts.legend": "Показване на тази легенда",
|
||||
"keyboard_shortcuts.local": "Отваряне на местна часова ос",
|
||||
"keyboard_shortcuts.local": "Отваряне на локалния инфопоток",
|
||||
"keyboard_shortcuts.mention": "Споменаване на автора",
|
||||
"keyboard_shortcuts.muted": "Отваряне на списъка със заглушени потребители",
|
||||
"keyboard_shortcuts.my_profile": "Отваряне на профила ви",
|
||||
@@ -402,12 +407,12 @@
|
||||
"navigation_bar.advanced_interface": "Отваряне в разширен уебинтерфейс",
|
||||
"navigation_bar.blocks": "Блокирани потребители",
|
||||
"navigation_bar.bookmarks": "Отметки",
|
||||
"navigation_bar.community_timeline": "Локална часова ос",
|
||||
"navigation_bar.community_timeline": "Локален инфопоток",
|
||||
"navigation_bar.compose": "Съставяне на нова публикация",
|
||||
"navigation_bar.direct": "Частни споменавания",
|
||||
"navigation_bar.discover": "Откриване",
|
||||
"navigation_bar.domain_blocks": "Блокирани домейни",
|
||||
"navigation_bar.explore": "Изследване",
|
||||
"navigation_bar.explore": "Разглеждане",
|
||||
"navigation_bar.favourites": "Любими",
|
||||
"navigation_bar.filters": "Заглушени думи",
|
||||
"navigation_bar.follow_requests": "Заявки за последване",
|
||||
@@ -471,13 +476,13 @@
|
||||
"notifications.permission_required": "Известията на работния плот ги няма, щото няма дадено нужното позволение.",
|
||||
"notifications_permission_banner.enable": "Включване на известията на работния плот",
|
||||
"notifications_permission_banner.how_to_control": "За да получавате известия, когато Mastodon не е отворен, включете известията на работния плот. Може да управлявате точно кои видове взаимодействия пораждат известия на работния плот чрез бутона {icon} по-горе, след като бъдат включени.",
|
||||
"notifications_permission_banner.title": "Никога не пропускате нещо",
|
||||
"notifications_permission_banner.title": "Никога не пропускайте нищо",
|
||||
"onboarding.action.back": "Върнете ме обратно",
|
||||
"onboarding.actions.back": "Върнете ме обратно",
|
||||
"onboarding.actions.go_to_explore": "Вижте какво изгрява",
|
||||
"onboarding.actions.go_to_explore": "Виж тенденции",
|
||||
"onboarding.actions.go_to_home": "Към началния ви инфоканал",
|
||||
"onboarding.compose.template": "Здравейте, #Mastodon!",
|
||||
"onboarding.follows.empty": "За съжаление, в момента не могат да се показват резултати. Може да опитате да употребявате търсене или да прегледате страницата за изследване, за да намерите страница за последване, или да опитате пак по-късно.",
|
||||
"onboarding.follows.empty": "За съжаление, в момента не могат да бъдат показани резултати. Може да опитате да търсите или да разгледате, за да намерите кого да последвате, или опитайте отново по-късно.",
|
||||
"onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!",
|
||||
"onboarding.follows.title": "Популярно в Mastodon",
|
||||
"onboarding.profile.discoverable": "Правене на моя профил откриваем",
|
||||
@@ -524,12 +529,13 @@
|
||||
"poll_button.add_poll": "Анкетиране",
|
||||
"poll_button.remove_poll": "Премахване на анкета",
|
||||
"privacy.change": "Промяна на поверителността на публикация",
|
||||
"privacy.direct.long": "Всеки споменат в публикацията",
|
||||
"privacy.direct.long": "Споменатите в публикацията",
|
||||
"privacy.direct.short": "Определени хора",
|
||||
"privacy.private.long": "Само последователите ви",
|
||||
"privacy.private.short": "Последователи",
|
||||
"privacy.public.long": "Всеки във и извън Mastodon",
|
||||
"privacy.public.short": "Публично",
|
||||
"privacy.unlisted.additional": "Това действие е точно като публичното, с изключение на това, че публикацията няма да се появява в каналите на живо, хаштаговете, разглеждането или търсенето в Mastodon, дори ако сте избрали да се публично видими на ниво акаунт.",
|
||||
"privacy.unlisted.long": "По-малко алгоритмични фанфари",
|
||||
"privacy.unlisted.short": "Тиха публика",
|
||||
"privacy_policy.last_updated": "Последно осъвременяване на {date}",
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"account.enable_notifications": "Ma c'hemenn pa vez embannet traoù gant @{name}",
|
||||
"account.endorse": "Lakaat war-wel war ar profil",
|
||||
"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.follow": "Heuliañ",
|
||||
"account.follow_back": "Heuliañ d'ho tro",
|
||||
@@ -62,7 +62,7 @@
|
||||
"account.requested_follow": "Gant {name} eo bet goulennet ho heuliañ",
|
||||
"account.share": "Skignañ profil @{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_domain": "Diverzañ an domani {domain}",
|
||||
"account.unblock_short": "Distankañ",
|
||||
@@ -118,9 +118,9 @@
|
||||
"column.lists": "Listennoù",
|
||||
"column.mutes": "Implijer·ion·ezed kuzhet",
|
||||
"column.notifications": "Kemennoù",
|
||||
"column.pins": "Toudoù spilhennet",
|
||||
"column.pins": "Embannadurioù spilhennet",
|
||||
"column.public": "Red-amzer kevredet",
|
||||
"column_back_button.label": "Distro",
|
||||
"column_back_button.label": "Distreiñ",
|
||||
"column_header.hide_settings": "Kuzhat an arventennoù",
|
||||
"column_header.moveLeft_settings": "Dilec'hiañ ar bannad a-gleiz",
|
||||
"column_header.moveRight_settings": "Dilec'hiañ ar bannad a-zehou",
|
||||
@@ -143,9 +143,14 @@
|
||||
"compose_form.lock_disclaimer.lock": "prennet",
|
||||
"compose_form.placeholder": "Petra emaoc'h o soñjal e-barzh ?",
|
||||
"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_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.reply": "Respont",
|
||||
"compose_form.save_changes": "Hizivadur",
|
||||
"compose_form.spoiler.marked": "Kuzhet eo an destenn a-dreñv ur c'hemenn",
|
||||
"compose_form.spoiler.unmarked": "N'eo ket kuzhet an destenn",
|
||||
"confirmation_modal.cancel": "Nullañ",
|
||||
@@ -194,9 +199,9 @@
|
||||
"embed.preview": "Setu penaos e teuio war wel :",
|
||||
"emoji_button.activity": "Obererezh",
|
||||
"emoji_button.clear": "Diverkañ",
|
||||
"emoji_button.custom": "Kempennet",
|
||||
"emoji_button.custom": "Personelaet",
|
||||
"emoji_button.flags": "Bannieloù",
|
||||
"emoji_button.food": "Boued hag Evaj",
|
||||
"emoji_button.food": "Boued & Evajoù",
|
||||
"emoji_button.label": "Enlakaat un emoji",
|
||||
"emoji_button.nature": "Natur",
|
||||
"emoji_button.not_found": "Emoji ebet !! (╯°□°)╯︵ ┻━┻",
|
||||
@@ -206,12 +211,12 @@
|
||||
"emoji_button.search": "O klask...",
|
||||
"emoji_button.search_results": "Disoc'hoù an enklask",
|
||||
"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_timeline": "Toud ebet amañ !",
|
||||
"empty_column.account_unavailable": "Profil dihegerz",
|
||||
"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.domain_blocks": "N'eus domani kuzh ebet c'hoazh.",
|
||||
"empty_column.explore_statuses": "N'eus tuadur ebet evit c'hoazh. Distroit diwezhatoc'h !",
|
||||
@@ -255,6 +260,7 @@
|
||||
"follow_request.authorize": "Aotren",
|
||||
"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_suggestions.view_all": "Gwelet pep tra",
|
||||
"followed_tags": "Hashtagoù o heuliañ",
|
||||
"footer.about": "Diwar-benn",
|
||||
"footer.directory": "Kavlec'h ar profiloù",
|
||||
@@ -262,7 +268,7 @@
|
||||
"footer.invite": "Pediñ tud",
|
||||
"footer.keyboard_shortcuts": "Berradennoù klavier",
|
||||
"footer.privacy_policy": "Reolennoù prevezded",
|
||||
"footer.source_code": "Gwelet kod mammenn",
|
||||
"footer.source_code": "Gwelet ar c'hod mammenn",
|
||||
"footer.status": "Statud",
|
||||
"generic.saved": "Enrollet",
|
||||
"getting_started.heading": "Loc'hañ",
|
||||
@@ -280,12 +286,9 @@
|
||||
"hashtag.follow": "Heuliañ ar ger-klik",
|
||||
"hashtag.unfollow": "Paouez heuliañ an hashtag",
|
||||
"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.show_reblogs": "Diskouez ar skignadennoù",
|
||||
"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.pending_critical_update.body": "Hizivait ho servijer Mastodon kerkent ha ma c'hallit mar plij!",
|
||||
"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.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.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_this_server": "War ar servijer-mañ",
|
||||
"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.title": "Customize your profile",
|
||||
"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",
|
||||
"picture_in_picture.restore": "Adlakaat",
|
||||
"poll.closed": "Serret",
|
||||
@@ -474,7 +477,9 @@
|
||||
"poll.votes": "{votes, plural,one {#votadenn} other {# votadenn}}",
|
||||
"poll_button.add_poll": "Ouzhpennañ ur 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_policy.last_updated": "Hizivadenn ziwezhañ {date}",
|
||||
"privacy_policy.title": "Reolennoù Prevezded",
|
||||
@@ -494,6 +499,7 @@
|
||||
"relative_time.seconds": "{number}eil",
|
||||
"relative_time.today": "hiziv",
|
||||
"reply_indicator.cancel": "Nullañ",
|
||||
"reply_indicator.poll": "Sontadeg",
|
||||
"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.categories.legal": "Lezennel",
|
||||
|
||||
@@ -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.lock": "blocat",
|
||||
"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.multiple": "Opcions múltiples",
|
||||
"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.switch_to_multiple": "Canvia l’enquesta per a permetre múltiples opcions",
|
||||
"compose_form.poll.switch_to_single": "Canvia l’enquesta per a permetre una única opció",
|
||||
"compose_form.poll.type": "Estil",
|
||||
"compose_form.publish": "Publica",
|
||||
"compose_form.publish_form": "Nou tut",
|
||||
"compose_form.reply": "Responeu",
|
||||
"compose_form.reply": "Respon",
|
||||
"compose_form.save_changes": "Actualitza",
|
||||
"compose_form.spoiler.marked": "Elimina l'avís de contingut",
|
||||
"compose_form.spoiler.unmarked": "Afegeix avís de contingut",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Autoritza",
|
||||
"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 d’aquests 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",
|
||||
"footer.about": "Quant a",
|
||||
"footer.directory": "Directori de perfils",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Segueix l'etiqueta",
|
||||
"hashtag.unfollow": "Deixa de seguir l'etiqueta",
|
||||
"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.show_reblogs": "Mostra els impulsos",
|
||||
"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.pending_critical_update.body": "Si us plau actualitza el teu servidor Mastodon tant aviat com sigui possible!",
|
||||
"home.pending_critical_update.link": "Veure actualitzacions",
|
||||
@@ -524,12 +529,15 @@
|
||||
"poll_button.add_poll": "Afegeix una enquesta",
|
||||
"poll_button.remove_poll": "Elimina l'enquesta",
|
||||
"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.private.long": "Només els vostres seguidors",
|
||||
"privacy.private.short": "Seguidors",
|
||||
"privacy.public.long": "Tothom dins o fora Mastodon",
|
||||
"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.title": "Política de Privacitat",
|
||||
"recommended": "Recomanat",
|
||||
@@ -547,7 +555,9 @@
|
||||
"relative_time.minutes": "{number}min",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"relative_time.today": "avui",
|
||||
"reply_indicator.attachments": "{count, plural, one {# adjunt} other {# adjunts}}",
|
||||
"reply_indicator.cancel": "Cancel·la",
|
||||
"reply_indicator.poll": "Enquesta",
|
||||
"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.categories.legal": "Legal",
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
"account.badges.group": "گرووپ",
|
||||
"account.block": "بلۆکی @{name}",
|
||||
"account.block_domain": "بلۆکی هەموو شتێک لە {domain}",
|
||||
"account.block_short": "بلۆک",
|
||||
"account.blocked": "بلۆککرا",
|
||||
"account.browse_more_on_origin_server": "گەڕانی فرەتر لە سەر پرۆفایلی سەرەکی",
|
||||
"account.cancel_follow_request": "داواکاری فۆڵۆو بکشێنەوە",
|
||||
"account.copy": "ڕوونووسی بەستەر بۆ توت",
|
||||
"account.direct": "بە شێوەیەکی تایبەت باسی @{name} بکە",
|
||||
"account.disable_notifications": "ئاگانامە مەنێرە بۆم کاتێک @{name} پۆست دەکرێت",
|
||||
"account.domain_blocked": "دۆمەین قەپاتکرا",
|
||||
@@ -30,6 +32,7 @@
|
||||
"account.featured_tags.last_status_never": "هیچ پۆستێک نییە",
|
||||
"account.featured_tags.title": "هاشتاگە تایبەتەکانی {name}",
|
||||
"account.follow": "بەدواداچوون",
|
||||
"account.follow_back": "فۆڵۆو بکەنەوە",
|
||||
"account.followers": "شوێنکەوتووان",
|
||||
"account.followers.empty": "کەسێک شوێن ئەم بەکارهێنەرە نەکەوتووە",
|
||||
"account.followers_counter": "{count, plural, one {{counter} شوێنکەوتوو} other {{counter} شوێنکەوتوو}}",
|
||||
@@ -38,6 +41,7 @@
|
||||
"account.follows.empty": "ئەم بەکارهێنەرە تا ئێستا شوێن کەس نەکەوتووە.",
|
||||
"account.go_to_profile": "بڕۆ بۆ پڕۆفایلی",
|
||||
"account.hide_reblogs": "داشاردنی بووستەکان لە @{name}",
|
||||
"account.in_memoriam": "لە یادەوەریدا.",
|
||||
"account.joined_short": "بەشداری کردووە",
|
||||
"account.languages": "گۆڕینی زمانە بەشداربووەکان",
|
||||
"account.link_verified_on": "خاوەنداریەتی ئەم لینکە لە {date} چێک کراوە",
|
||||
@@ -46,7 +50,11 @@
|
||||
"account.mention": "ئاماژە @{name}",
|
||||
"account.moved_to": "{name} ئاماژەی بەوە کردووە کە ئەکاونتە نوێیەکەیان ئێستا:",
|
||||
"account.mute": "بێدەنگکردن @{name}",
|
||||
"account.mute_notifications_short": "پاڵ بە ئاگادارکردنەوەکانەوە بنێ",
|
||||
"account.mute_short": "بێدەنگ",
|
||||
"account.muted": "بێ دەنگ",
|
||||
"account.mutual": "دوولایەنە",
|
||||
"account.no_bio": "هیچ وەسفێک نەخراوەتەڕوو.",
|
||||
"account.open_original_page": "لاپەڕەی ئەسڵی بکەرەوە",
|
||||
"account.posts": "نووسراوەکان",
|
||||
"account.posts_with_replies": "توتس و وەڵامەکان",
|
||||
@@ -62,6 +70,7 @@
|
||||
"account.unendorse": "تایبەتمەندی لەسەر پرۆفایلەکە نیە",
|
||||
"account.unfollow": "بەدوادانەچو",
|
||||
"account.unmute": "بێدەنگکردنی @{name}",
|
||||
"account.unmute_notifications_short": "ئاگادارکردنەوەکان بێدەنگ بکەرەوە",
|
||||
"account.unmute_short": "بێدەنگی مەکە",
|
||||
"account_note.placeholder": "کرتەبکە بۆ زیادکردنی تێبینی",
|
||||
"admin.dashboard.daily_retention": "ڕێژەی مانەوەی بەکارهێنەر بەپێی ڕۆژ دوای ناو تۆمارکردن",
|
||||
@@ -69,6 +78,10 @@
|
||||
"admin.dashboard.retention.average": "ڕێژە",
|
||||
"admin.dashboard.retention.cohort": "چوونەژوورەوەی مانگانە",
|
||||
"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.title": "ڕێژەی سنووردار",
|
||||
"alert.unexpected.message": "هەڵەیەکی چاوەڕوان نەکراو ڕوویدا.",
|
||||
@@ -101,6 +114,8 @@
|
||||
"column.direct": "ئاماژەی تایبەت",
|
||||
"column.directory": "گەڕان لە پرۆفایلەکان",
|
||||
"column.domain_blocks": "دۆمەینە داخراوەکان",
|
||||
"column.favourites": "دڵخوازەکان",
|
||||
"column.firehose": "فیدی ڕاستەوخۆ",
|
||||
"column.follow_requests": "بەدواداچوی داواکاریەکان بکە",
|
||||
"column.home": "سەرەتا",
|
||||
"column.lists": "پێرست",
|
||||
@@ -121,6 +136,9 @@
|
||||
"community.column_settings.remote_only": "تەنها بۆ دوور",
|
||||
"compose.language.change": "گۆڕینی زمان",
|
||||
"compose.language.search": "گەڕان بە زمانەکان...",
|
||||
"compose.published.body": "پۆست بڵاوکراوەتەوە.",
|
||||
"compose.published.open": "بیکەوە",
|
||||
"compose.saved.body": "پۆستەکە سەیڤ کراوە.",
|
||||
"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.hashtag_warning": "ئەم بڵاوکراوەیە لە ژێر هیچ هاشتاگێکدا دا نانرێت وەک ئەوەیە، کە گشتی نەبێت. تەنها بڵاوکراوە گشتیەکان دەتوانرێ بە هاشتاگ گەڕانی بۆ بکرێت.",
|
||||
@@ -128,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "قفڵ دراوە",
|
||||
"compose_form.placeholder": "چی لە مێشکتدایە?",
|
||||
"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_single": "گۆڕینی ڕاپرسی بۆ ڕێگەدان بە تاکە هەڵبژاردنێک",
|
||||
"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.unmarked": "دەق شاراوە نییە",
|
||||
"compose_form.spoiler_placeholder": "ئاگادارکردنەوەی ناوەڕۆک (ئیختیاری)",
|
||||
"confirmation_modal.cancel": "هەڵوەشاندنەوه",
|
||||
"confirmations.block.block_and_report": "بلۆک & گوزارشت",
|
||||
"confirmations.block.confirm": "بلۆک",
|
||||
@@ -155,6 +181,7 @@
|
||||
"confirmations.mute.explanation": "ئەمەش دەبێتە هۆی شاردنەوەی پۆستەکان یان ئەو بابەتانەی کە ئاماژەیان پێ دەکات ، بەڵام هێشتا ڕێگەیان پێ دەدات کە پۆستەکانتان ببینن و شوێنتان بکەون.",
|
||||
"confirmations.mute.message": "ئایا دڵنیایت لەوەی دەتەوێت بیلێیت {name}?",
|
||||
"confirmations.redraft.confirm": "سڕینەوە & دووبارە ڕەشکردنەوە",
|
||||
"confirmations.redraft.message": "دڵنیای دەتەوێت ئەم پۆستە بسڕیتەوە و دووبارە دایبڕێژیتەوە؟ فەڤۆریت و بووستەکان لەدەست دەچن، وەڵامەکانی پۆستە ئەسڵیەکەش هەتیو دەبن.",
|
||||
"confirmations.reply.confirm": "وەڵام",
|
||||
"confirmations.reply.message": "وەڵامدانەوە ئێستا ئەو نامەیە ی کە تۆ ئێستا دایڕشتووە، دەنووسێتەوە. ئایا دڵنیایت کە دەتەوێت بەردەوام بیت?",
|
||||
"confirmations.unfollow.confirm": "بەدوادانەچو",
|
||||
@@ -163,7 +190,9 @@
|
||||
"conversation.mark_as_read": "نیشانەکردن وەک خوێندراوە",
|
||||
"conversation.open": "نیشاندان گفتوگۆ",
|
||||
"conversation.with": "لەگەڵ{names}",
|
||||
"copy_icon_button.copied": "کۆپی کراوە بۆ کلیپبۆرد",
|
||||
"copypaste.copied": "کۆپی کراوە",
|
||||
"copypaste.copy_to_clipboard": "کۆپی کراوە بۆ کلیپبۆرد",
|
||||
"directory.federated": "لە ڕاژەکانی ناسراو",
|
||||
"directory.local": "تەنها لە {domain}",
|
||||
"directory.new_arrivals": "تازە گەیشتنەکان",
|
||||
@@ -173,6 +202,7 @@
|
||||
"dismissable_banner.community_timeline": "ئەمانە دوایین پۆستی گشتی ئەو کەسانەن کە ئەکاونتەکانیان لەلایەن {domain}ەوە هۆست کراوە.",
|
||||
"dismissable_banner.dismiss": "بەلاوە نان",
|
||||
"dismissable_banner.explore_links": "ئەم هەواڵانە لە ئێستادا لەلایەن کەسانێکەوە لەسەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزی باس دەکرێن.",
|
||||
"dismissable_banner.explore_statuses": "ئەمانە پۆستەکانن لە سەرانسەری وێبی کۆمەڵایەتی کە ئەمڕۆ کێشکردنیان بەدەستهێناوە. پۆستە نوێیەکان کە بووست و فەڤریتی زیاتریان هەیە ڕیزبەندی بەرزتریان هەیە.",
|
||||
"dismissable_banner.explore_tags": "ئەم هاشتاگانە لە ئێستادا لە نێو خەڵکی سەر ئەم سێرڤەرە و سێرڤەرەکانی تری تۆڕی لامەرکەزیدا جێگەی خۆیان دەگرن.",
|
||||
"embed.instructions": "ئەم توتە بنچین بکە لەسەر وێب سایتەکەت بە کۆپیکردنی کۆدەکەی خوارەوە.",
|
||||
"embed.preview": "ئەمە ئەو شتەیە کە لە شێوەی خۆی دەچێت:",
|
||||
@@ -216,6 +246,7 @@
|
||||
"errors.unexpected_crash.copy_stacktrace": "کۆپیکردنی ستێکتراسی بۆ کلیپ بۆرد",
|
||||
"errors.unexpected_crash.report_issue": "کێشەی گوزارشت",
|
||||
"explore.search_results": "ئەنجامەکانی گەڕان",
|
||||
"explore.suggested_follows": "خەڵک",
|
||||
"explore.title": "گەڕان",
|
||||
"explore.trending_links": "هەواڵەکان",
|
||||
"explore.trending_statuses": "بڵاوکراوەکان",
|
||||
@@ -236,9 +267,16 @@
|
||||
"filter_modal.select_filter.subtitle": "بەکارهێنانی پۆلێنی بەردەست یان دروستکردنی پۆلێنێکی نوێ",
|
||||
"filter_modal.select_filter.title": "ئەم بڵاوکراوەیە بپاڵێوە",
|
||||
"filter_modal.title.status": "بڵاوکراوەیەک بپاڵێوە",
|
||||
"firehose.all": "هەموو",
|
||||
"firehose.local": "لەسەر ئەم ڕاژەیە",
|
||||
"firehose.remote": "ڕاژەکانی دی",
|
||||
"follow_request.authorize": "دهسهڵاتپێدراو",
|
||||
"follow_request.reject": "ڕەتکردنەوە",
|
||||
"follow_requests.unlocked_explanation": "هەرچەندە هەژمارەکەت داخراو نییە، ستافی {domain} وا بیریان کردەوە کە لەوانەیە بتانەوێت پێداچوونەوە بە داواکاریەکانی ئەم هەژمارەدا بکەن بە دەستی.",
|
||||
"follow_suggestions.curated_suggestion": "ستاف هەڵبژاردنی",
|
||||
"follow_suggestions.dismiss": "دوبارە پشانی مەدە",
|
||||
"follow_suggestions.view_all": "بینینی هەموو",
|
||||
"follow_suggestions.who_to_follow": "دواکەوتنی کێ",
|
||||
"followed_tags": "هاشتاگە شوێنکەوتووەکان",
|
||||
"footer.about": "دەربارە",
|
||||
"footer.directory": "ڕابەری پەڕەی ناساندن",
|
||||
@@ -259,6 +297,7 @@
|
||||
"hashtag.column_settings.tag_mode.any": "هەر کام لەمانە",
|
||||
"hashtag.column_settings.tag_mode.none": "هیچ کام لەمانە",
|
||||
"hashtag.column_settings.tag_toggle": "تاگی زیادە ی ئەم ستوونە لەخۆ بنووسە",
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} participant} other {{counter} participants}}",
|
||||
"hashtag.follow": "شوێنکەوتنی هاشتاگ",
|
||||
"hashtag.unfollow": "شوێن نەکەوتنی هاشتاگ",
|
||||
"home.column_settings.basic": "بنەڕەتی",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"account.featured_tags.last_status_never": "Žádné příspěvky",
|
||||
"account.featured_tags.title": "Hlavní hashtagy uživatele {name}",
|
||||
"account.follow": "Sledovat",
|
||||
"account.follow_back": "Také sledovat",
|
||||
"account.followers": "Sledující",
|
||||
"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}}",
|
||||
@@ -52,6 +53,7 @@
|
||||
"account.mute_notifications_short": "Ztlumit upozornění",
|
||||
"account.mute_short": "Ztlumit",
|
||||
"account.muted": "Skrytý",
|
||||
"account.mutual": "Vzájemné",
|
||||
"account.no_bio": "Nebyl poskytnut žádný popis.",
|
||||
"account.open_original_page": "Otevřít původní stránku",
|
||||
"account.posts": "Příspěvky",
|
||||
@@ -144,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "zamčený",
|
||||
"compose_form.placeholder": "Co se vám honí hlavou?",
|
||||
"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_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.reply": "Odpovědět",
|
||||
"compose_form.save_changes": "Aktualizovat",
|
||||
"compose_form.spoiler.marked": "Odebrat 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",
|
||||
"confirmations.block.block_and_report": "Blokovat a nahlásit",
|
||||
"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.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.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.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.",
|
||||
@@ -266,7 +276,18 @@
|
||||
"firehose.remote": "Ostatní servery",
|
||||
"follow_request.authorize": "Autorizovat",
|
||||
"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",
|
||||
"footer.about": "O aplikaci",
|
||||
"footer.directory": "Adresář profilů",
|
||||
@@ -287,15 +308,15 @@
|
||||
"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_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.unfollow": "Přestat sledovat hashtag",
|
||||
"home.actions.go_to_explore": "Podívejte se, co frčí",
|
||||
"home.actions.go_to_suggestions": "Najít lidi ke sledování",
|
||||
"hashtags.and_other": "…a {count, plural, one {# další} few {# další} other {# dalších}}",
|
||||
"home.column_settings.basic": "Základní",
|
||||
"home.column_settings.show_reblogs": "Zobrazit boosty",
|
||||
"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.pending_critical_update.body": "Aktualizujte, prosím, svůj Mastodon server co nejdříve!",
|
||||
"home.pending_critical_update.link": "Zobrazit aktualizace",
|
||||
@@ -376,6 +397,7 @@
|
||||
"lists.search": "Hledejte mezi lidmi, které sledujete",
|
||||
"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}}",
|
||||
"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}}",
|
||||
"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í",
|
||||
@@ -461,8 +483,19 @@
|
||||
"onboarding.actions.go_to_home": "Přejít na svůj domovský feed",
|
||||
"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.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.title": "Populární na Mastodonu",
|
||||
"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": "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.message": "Jsem {username} na #Mastodonu! Pojď mě sledovat na {url}",
|
||||
"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.skip": "Want to skip right ahead?",
|
||||
"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.title": "Follow {count, plural, one {one person} other {# people}}",
|
||||
"onboarding.steps.publish_status.body": "Řekněte světu Ahoj.",
|
||||
"onboarding.steps.follow_people.body": "Mastodon je o sledování zajimavých lidí.",
|
||||
"onboarding.steps.follow_people.title": "Přispůsobit vlastní domovský kanál",
|
||||
"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.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.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.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!",
|
||||
@@ -496,9 +529,18 @@
|
||||
"poll_button.add_poll": "Přidat anketu",
|
||||
"poll_button.remove_poll": "Odebrat anketu",
|
||||
"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.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.title": "Zásady ochrany osobních údajů",
|
||||
"recommended": "Doporučeno",
|
||||
"refresh": "Obnovit",
|
||||
"regeneration_indicator.label": "Načítání…",
|
||||
"regeneration_indicator.sublabel": "Váš domovský kanál se připravuje!",
|
||||
@@ -513,7 +555,9 @@
|
||||
"relative_time.minutes": "{number} m",
|
||||
"relative_time.seconds": "{number} s",
|
||||
"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.poll": "Anketa",
|
||||
"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.categories.legal": "Právní ustanovení",
|
||||
@@ -569,6 +613,7 @@
|
||||
"search.quick_action.status_search": "Příspěvky odpovídající {x}",
|
||||
"search.search_or_paste": "Hledat nebo vložit URL",
|
||||
"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.options": "Možnosti hledání",
|
||||
"search_popout.quick_actions": "Rychlé akce",
|
||||
|
||||
@@ -146,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "wedi ei gloi",
|
||||
"compose_form.placeholder": "Beth sydd ar eich meddwl?",
|
||||
"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_single": "Newid pleidlais i gyfyngu i un dewis",
|
||||
"compose_form.poll.type": "Arddull",
|
||||
"compose_form.publish": "Postiad",
|
||||
"compose_form.publish_form": "Cyhoeddi",
|
||||
"compose_form.reply": "Ateb",
|
||||
"compose_form.save_changes": "Diweddariad",
|
||||
"compose_form.spoiler.marked": "Dileu rhybudd cynnwys",
|
||||
"compose_form.spoiler.unmarked": "Ychwanegu rhybudd cynnwys",
|
||||
"compose_form.spoiler_placeholder": "Rhybudd cynnwys (dewisol)",
|
||||
"confirmation_modal.cancel": "Diddymu",
|
||||
"confirmations.block.block_and_report": "Rhwystro ac Adrodd",
|
||||
"confirmations.block.confirm": "Blocio",
|
||||
@@ -269,6 +277,17 @@
|
||||
"follow_request.authorize": "Awdurdodi",
|
||||
"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_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",
|
||||
"footer.about": "Ynghylch",
|
||||
"footer.directory": "Cyfeiriadur proffiliau",
|
||||
@@ -295,13 +314,9 @@
|
||||
"hashtag.follow": "Dilyn hashnod",
|
||||
"hashtag.unfollow": "Dad-ddilyn hashnod",
|
||||
"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.show_reblogs": "Dangos hybiau",
|
||||
"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.pending_critical_update.body": "Diweddarwch eich gweinydd Mastodon cyn gynted â phosibl!",
|
||||
"home.pending_critical_update.link": "Gweld y diweddariadau",
|
||||
@@ -514,7 +529,15 @@
|
||||
"poll_button.add_poll": "Ychwanegu pleidlais",
|
||||
"poll_button.remove_poll": "Tynnu pleidlais",
|
||||
"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.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.title": "Polisi Preifatrwydd",
|
||||
"recommended": "Argymhellwyd",
|
||||
@@ -532,7 +555,9 @@
|
||||
"relative_time.minutes": "{number} munud",
|
||||
"relative_time.seconds": "{number} eiliad",
|
||||
"relative_time.today": "heddiw",
|
||||
"reply_indicator.attachments": "{count, plural, one {# attachment} arall {# attachments}}",
|
||||
"reply_indicator.cancel": "Canslo",
|
||||
"reply_indicator.poll": "Arolwg",
|
||||
"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.categories.legal": "Cyfreithiol",
|
||||
|
||||
@@ -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.lock": "låst",
|
||||
"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.multiple": "Multivalg",
|
||||
"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.switch_to_multiple": "Ændr afstemning til flervalgstype",
|
||||
"compose_form.poll.switch_to_single": "Ændr afstemning til enkeltvalgstype",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Godkend",
|
||||
"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_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",
|
||||
"footer.about": "Om",
|
||||
"footer.directory": "Profiloversigt",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Følg hashtag",
|
||||
"hashtag.unfollow": "Stop med at følge hashtag",
|
||||
"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.show_reblogs": "Vis boosts",
|
||||
"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.pending_critical_update.body": "Opdater din Mastodon-server snarest muligt!",
|
||||
"home.pending_critical_update.link": "Se opdateringer",
|
||||
|
||||
@@ -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.lock": "geschützt",
|
||||
"compose_form.placeholder": "Was gibt’s Neues?",
|
||||
"compose_form.poll.add_option": "Auswahl hinzufügen",
|
||||
"compose_form.poll.duration": "Umfragedauer",
|
||||
"compose_form.poll.multiple": "Mehrfachauswahl",
|
||||
"compose_form.poll.option_placeholder": "{number}. Auswahlmöglichkeit",
|
||||
"compose_form.poll.remove_option": "Dieses Auswahlfeld entfernen",
|
||||
"compose_form.poll.multiple": "Multiple-Choice",
|
||||
"compose_form.poll.option_placeholder": "Option {number}",
|
||||
"compose_form.poll.single": "Einfachauswahl",
|
||||
"compose_form.poll.switch_to_multiple": "Mehrfachauswahl 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_form": "Neuer Beitrag",
|
||||
"compose_form.reply": "Antworten",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Genehmigen",
|
||||
"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_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",
|
||||
"footer.about": "Über",
|
||||
"footer.directory": "Profilverzeichnis",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Hashtag folgen",
|
||||
"hashtag.unfollow": "Hashtag entfolgen",
|
||||
"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.show_reblogs": "Geteilte Beiträge 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.pending_critical_update.body": "Bitte aktualisiere deinen Mastodon-Server so schnell wie möglich!",
|
||||
"home.pending_critical_update.link": "Updates ansehen",
|
||||
@@ -528,7 +533,7 @@
|
||||
"privacy.direct.short": "Bestimmte Profile",
|
||||
"privacy.private.long": "Nur deine 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.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",
|
||||
|
||||
@@ -140,11 +140,9 @@
|
||||
"compose_form.lock_disclaimer": "Ο λογαριασμός σου δεν είναι {locked}. Οποιοσδήποτε μπορεί να σε ακολουθήσει για να δει τις δημοσιεύσεις σου προς τους ακολούθους σου.",
|
||||
"compose_form.lock_disclaimer.lock": "κλειδωμένο",
|
||||
"compose_form.placeholder": "Τι σκέφτεσαι;",
|
||||
"compose_form.poll.add_option": "Προσθήκη επιλογής",
|
||||
"compose_form.poll.duration": "Διάρκεια δημοσκόπησης",
|
||||
"compose_form.poll.multiple": "Πολλαπλή επιλογή",
|
||||
"compose_form.poll.option_placeholder": "Επιλογή {number}",
|
||||
"compose_form.poll.remove_option": "Αφαίρεση επιλογής",
|
||||
"compose_form.poll.switch_to_multiple": "Ενημέρωση δημοσκόπησης με πολλαπλές επιλογές",
|
||||
"compose_form.poll.switch_to_single": "Ενημέρωση δημοσκόπησης με μοναδική επιλογή",
|
||||
"compose_form.poll.type": "Στυλ",
|
||||
@@ -291,12 +289,9 @@
|
||||
"hashtag.column_settings.tag_toggle": "Προσθήκη επιπλέον ταμπελών για την κολώνα",
|
||||
"hashtag.follow": "Παρακολούθηση ετικέτας",
|
||||
"hashtag.unfollow": "Διακοπή παρακολούθησης ετικέτας",
|
||||
"home.actions.go_to_suggestions": "Βρείτε άτομα για να ακολουθήσετε",
|
||||
"home.column_settings.basic": "Βασικές ρυθμίσεις",
|
||||
"home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων",
|
||||
"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.pending_critical_update.link": "Δείτε ενημερώσεις",
|
||||
"home.pending_critical_update.title": "Κρίσιμη ενημέρωση ασφαλείας διαθέσιμη!",
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"account.featured_tags.last_status_never": "No posts",
|
||||
"account.featured_tags.title": "{name}'s featured hashtags",
|
||||
"account.follow": "Follow",
|
||||
"account.follow_back": "Follow back",
|
||||
"account.followers": "Followers",
|
||||
"account.followers.empty": "No one follows this user yet.",
|
||||
"account.followers_counter": "{count, plural, one {{counter} Follower} other {{counter} Followers}}",
|
||||
@@ -52,6 +53,7 @@
|
||||
"account.mute_notifications_short": "Mute notifications",
|
||||
"account.mute_short": "Mute",
|
||||
"account.muted": "Muted",
|
||||
"account.mutual": "Mutual",
|
||||
"account.no_bio": "No description provided.",
|
||||
"account.open_original_page": "Open original page",
|
||||
"account.posts": "Posts",
|
||||
@@ -144,11 +146,19 @@
|
||||
"compose_form.lock_disclaimer.lock": "locked",
|
||||
"compose_form.placeholder": "What's on your mind?",
|
||||
"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_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.reply": "Reply",
|
||||
"compose_form.save_changes": "Update",
|
||||
"compose_form.spoiler.marked": "Remove content warning",
|
||||
"compose_form.spoiler.unmarked": "Add content warning",
|
||||
"compose_form.spoiler_placeholder": "Content warning (optional)",
|
||||
"confirmation_modal.cancel": "Cancel",
|
||||
"confirmations.block.block_and_report": "Block & Report",
|
||||
"confirmations.block.confirm": "Block",
|
||||
@@ -267,6 +277,11 @@
|
||||
"follow_request.authorize": "Authorise",
|
||||
"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_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",
|
||||
"footer.about": "About",
|
||||
"footer.directory": "Profiles directory",
|
||||
@@ -292,14 +307,10 @@
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} post} other {{counter} posts}} today",
|
||||
"hashtag.follow": "Follow hashtag",
|
||||
"hashtag.unfollow": "Unfollow hashtag",
|
||||
"hashtags.and_other": "…and {count, plural, one {}other {# more}}",
|
||||
"home.actions.go_to_explore": "See what's trending",
|
||||
"home.actions.go_to_suggestions": "Find people to follow",
|
||||
"hashtags.and_other": "…and {count, plural, one {one more} other {# more}}",
|
||||
"home.column_settings.basic": "Basic",
|
||||
"home.column_settings.show_reblogs": "Show boosts",
|
||||
"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.pending_critical_update.body": "Please update your Mastodon server as soon as possible!",
|
||||
"home.pending_critical_update.link": "See updates",
|
||||
@@ -512,7 +523,15 @@
|
||||
"poll_button.add_poll": "Add a poll",
|
||||
"poll_button.remove_poll": "Remove poll",
|
||||
"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.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.title": "Privacy Policy",
|
||||
"recommended": "Recommended",
|
||||
@@ -530,7 +549,9 @@
|
||||
"relative_time.minutes": "{number}m",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"relative_time.today": "today",
|
||||
"reply_indicator.attachments": "{count, plural, one {# attachment} other {# attachments}}",
|
||||
"reply_indicator.cancel": "Cancel",
|
||||
"reply_indicator.poll": "Poll",
|
||||
"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.categories.legal": "Legal",
|
||||
|
||||
@@ -279,8 +279,13 @@
|
||||
"follow_request.authorize": "Authorize",
|
||||
"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_suggestions.curated_suggestion": "Editors' Choice",
|
||||
"follow_suggestions.curated_suggestion": "Staff pick",
|
||||
"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.popular_suggestion": "Popular suggestion",
|
||||
"follow_suggestions.view_all": "View all",
|
||||
@@ -428,7 +433,8 @@
|
||||
"not_signed_in_indicator.not_signed_in": "You need to login to access this resource.",
|
||||
"notification.admin.report": "{name} reported {target}",
|
||||
"notification.admin.sign_up": "{name} signed up",
|
||||
"notification.favourite": "{name} favorited your post",
|
||||
"notification.emoji_reaction": "{name} reacted your post with emoji",
|
||||
"notification.favourite": "{name} favourited your post",
|
||||
"notification.follow": "{name} followed you",
|
||||
"notification.follow_request": "{name} has requested to follow you",
|
||||
"notification.mention": "{name} mentioned you",
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
"column.directory": "Foliumi la profilojn",
|
||||
"column.domain_blocks": "Blokitaj domajnoj",
|
||||
"column.favourites": "Stelumoj",
|
||||
"column.firehose": "Vivantaj fluoj",
|
||||
"column.firehose": "Rektaj fluoj",
|
||||
"column.follow_requests": "Petoj de sekvado",
|
||||
"column.home": "Hejmo",
|
||||
"column.lists": "Listoj",
|
||||
@@ -295,13 +295,9 @@
|
||||
"hashtag.follow": "Sekvi la kradvorton",
|
||||
"hashtag.unfollow": "Ne plu sekvi la kradvorton",
|
||||
"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.show_reblogs": "Montri diskonigojn",
|
||||
"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.pending_critical_update.body": "Ĝisdatigu vian servilon de Mastodon kiel eble plej baldau!",
|
||||
"home.pending_critical_update.link": "Vidi ĝisdatigojn",
|
||||
|
||||
@@ -146,14 +146,13 @@
|
||||
"compose_form.lock_disclaimer.lock": "privada",
|
||||
"compose_form.placeholder": "¿Qué onda?",
|
||||
"compose_form.poll.duration": "Duración de la encuesta",
|
||||
"compose_form.poll.multiple": "Selección múltiple",
|
||||
"compose_form.poll.multiple": "Múltiples opciones",
|
||||
"compose_form.poll.option_placeholder": "Opción {number}",
|
||||
"compose_form.poll.remove_option": "Quitar esta opción",
|
||||
"compose_form.poll.single": "Elige uno",
|
||||
"compose_form.poll.single": "Elegí una",
|
||||
"compose_form.poll.switch_to_multiple": "Cambiar encuesta para permitir opciones múltiples",
|
||||
"compose_form.poll.switch_to_single": "Cambiar encuesta para permitir una sola opción",
|
||||
"compose_form.poll.type": "Estilo",
|
||||
"compose_form.publish": "Publicar",
|
||||
"compose_form.publish": "Enviar",
|
||||
"compose_form.publish_form": "Nuevo mensaje",
|
||||
"compose_form.reply": "Responder",
|
||||
"compose_form.save_changes": "Actualizar",
|
||||
@@ -278,6 +277,17 @@
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rechazar",
|
||||
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el equipo de {domain} pensó que podrías querer revisar manualmente las solicitudes de seguimiento de estas cuentas.",
|
||||
"follow_suggestions.curated_suggestion": "Selección del equipo",
|
||||
"follow_suggestions.dismiss": "No mostrar de nuevo",
|
||||
"follow_suggestions.hints.featured": "Este perfil fue seleccionado a mano por el equipo de {domain}.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las cuentas que seguís.",
|
||||
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
|
||||
"follow_suggestions.hints.most_interactions": "Este perfil ha estado recibiendo recientemente mucha atención en {domain}.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los que comenzaste a seguir.",
|
||||
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
|
||||
"follow_suggestions.popular_suggestion": "Sugerencia popular",
|
||||
"follow_suggestions.view_all": "Ver todo",
|
||||
"follow_suggestions.who_to_follow": "A quién seguir",
|
||||
"followed_tags": "Etiquetas seguidas",
|
||||
"footer.about": "Información",
|
||||
"footer.directory": "Directorio de perfiles",
|
||||
@@ -304,13 +314,9 @@
|
||||
"hashtag.follow": "Seguir etiqueta",
|
||||
"hashtag.unfollow": "Dejar de seguir etiqueta",
|
||||
"hashtags.and_other": "…y {count, plural, other {# más}}",
|
||||
"home.actions.go_to_explore": "Ver qué está en tendencia",
|
||||
"home.actions.go_to_suggestions": "Encontrar cuentas para seguir",
|
||||
"home.column_settings.basic": "Básico",
|
||||
"home.column_settings.show_reblogs": "Mostrar adhesiones",
|
||||
"home.column_settings.show_replies": "Mostrar respuestas",
|
||||
"home.explore_prompt.body": "Tu línea temporal principal tendrá una mezcla de mensajes de etiquetas que hayás decidido seguir, cuentas que hayás seguido y mensajes a los que éstas adhieran. Si está muy tranquilo por acá, quizás quieras:",
|
||||
"home.explore_prompt.title": "Este es tu inicio en Mastodon.",
|
||||
"home.hide_announcements": "Ocultar anuncios",
|
||||
"home.pending_critical_update.body": "Por favor, ¡actualizá tu servidor de Mastodon lo antes posible!",
|
||||
"home.pending_critical_update.link": "Ver actualizaciones",
|
||||
@@ -523,10 +529,15 @@
|
||||
"poll_button.add_poll": "Agregar encuesta",
|
||||
"poll_button.remove_poll": "Quitar encuesta",
|
||||
"privacy.change": "Configurar privacidad del mensaje",
|
||||
"privacy.direct.short": "Personas específicas",
|
||||
"privacy.direct.long": "Todas las cuentas mencionadas en el mensaje",
|
||||
"privacy.direct.short": "Cuentas específicas",
|
||||
"privacy.private.long": "Solo tus seguidores",
|
||||
"privacy.private.short": "Seguidores",
|
||||
"privacy.public.long": "Cualquier persona dentro y fuera de Mastodon",
|
||||
"privacy.public.short": "Público",
|
||||
"privacy.unlisted.additional": "Esto se comporta exactamente igual que con la configuración de privacidad de mensaje \"Público\", excepto que el mensaje no aparecerá en los líneas temporales en vivo, ni en las etiquetas, ni en la línea temporal \"Explorá\", ni en la búsqueda de Mastodon; incluso si optaste por hacer tu cuenta visible.",
|
||||
"privacy.unlisted.long": "Menos fanfarrias algorítmicas",
|
||||
"privacy.unlisted.short": "Público silencioso",
|
||||
"privacy_policy.last_updated": "Última actualización: {date}",
|
||||
"privacy_policy.title": "Política de privacidad",
|
||||
"recommended": "Opción recomendada",
|
||||
@@ -544,7 +555,9 @@
|
||||
"relative_time.minutes": "{number}m",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"relative_time.today": "hoy",
|
||||
"reply_indicator.attachments": "{count, plural,one {# adjunto} other {# adjuntos}}",
|
||||
"reply_indicator.cancel": "Cancelar",
|
||||
"reply_indicator.poll": "Encuesta",
|
||||
"report.block": "Bloquear",
|
||||
"report.block_explanation": "No verás sus mensajes. No podrán ver tus mensajes ni seguirte. Se van a dar cuentra de que están bloqueados.",
|
||||
"report.categories.legal": "Legales",
|
||||
@@ -644,8 +657,8 @@
|
||||
"status.filter": "Filtrar este mensaje",
|
||||
"status.filtered": "Filtrado",
|
||||
"status.hide": "Ocultar mensaje",
|
||||
"status.history.created": "Creado por {name} el {date}",
|
||||
"status.history.edited": "Editado por {name} el {date}",
|
||||
"status.history.created": "Creado por {name}, {date}",
|
||||
"status.history.edited": "Editado por {name}, {date}",
|
||||
"status.load_more": "Cargar más",
|
||||
"status.media.open": "Clic para abrir",
|
||||
"status.media.show": "Clic para mostrar",
|
||||
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "Tu cuenta no está bloqueada. Todos pueden seguirte para ver tus toots solo para seguidores.",
|
||||
"compose_form.lock_disclaimer.lock": "bloqueado",
|
||||
"compose_form.placeholder": "¿En qué estás pensando?",
|
||||
"compose_form.poll.add_option": "Agregar opción",
|
||||
"compose_form.poll.duration": "Duración de la encuesta",
|
||||
"compose_form.poll.multiple": "Selección múltiple",
|
||||
"compose_form.poll.option_placeholder": "Opción {number}",
|
||||
"compose_form.poll.remove_option": "Eliminar esta opción",
|
||||
"compose_form.poll.single": "Seleccione uno",
|
||||
"compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones",
|
||||
"compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rechazar",
|
||||
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
|
||||
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
|
||||
"follow_suggestions.dismiss": "No mostrar de nuevo",
|
||||
"follow_suggestions.hints.featured": "Este perfil ha sido elegido a mano por el equipo de {domain}.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
|
||||
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
|
||||
"follow_suggestions.hints.most_interactions": "Este perfil ha estado recibiendo recientemente mucha atención en {domain}.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
|
||||
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
|
||||
"follow_suggestions.popular_suggestion": "Sugerencia popular",
|
||||
"follow_suggestions.view_all": "Ver todo",
|
||||
"follow_suggestions.who_to_follow": "A quién seguir",
|
||||
"followed_tags": "Hashtags seguidos",
|
||||
"footer.about": "Acerca de",
|
||||
"footer.directory": "Directorio de perfiles",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Seguir etiqueta",
|
||||
"hashtag.unfollow": "Dejar de seguir etiqueta",
|
||||
"hashtags.and_other": "…y {count, plural, other {# más}}",
|
||||
"home.actions.go_to_explore": "Ver tendencias",
|
||||
"home.actions.go_to_suggestions": "Encuentra gente a la que seguir",
|
||||
"home.column_settings.basic": "Básico",
|
||||
"home.column_settings.show_reblogs": "Mostrar retoots",
|
||||
"home.column_settings.show_replies": "Mostrar respuestas",
|
||||
"home.explore_prompt.body": "Tu cronología de inicio tendrá una mezcla de publicaciones de los hashtags que has escogido seguir, las personas que has decidido seguir y las publicaciones que impulsen. Si crees que está demasiado tranquila, quizás quieras:",
|
||||
"home.explore_prompt.title": "Este es tu punto de partida en Mastodon.",
|
||||
"home.hide_announcements": "Ocultar anuncios",
|
||||
"home.pending_critical_update.body": "¡Por favor actualiza tu servidor Mastodon lo antes posible!",
|
||||
"home.pending_critical_update.link": "Ver actualizaciones",
|
||||
|
||||
@@ -148,7 +148,6 @@
|
||||
"compose_form.poll.duration": "Duración de la encuesta",
|
||||
"compose_form.poll.multiple": "Selección múltiple",
|
||||
"compose_form.poll.option_placeholder": "Opción {number}",
|
||||
"compose_form.poll.remove_option": "Quitar esta opción",
|
||||
"compose_form.poll.single": "Elige uno",
|
||||
"compose_form.poll.switch_to_multiple": "Modificar encuesta para permitir múltiples opciones",
|
||||
"compose_form.poll.switch_to_single": "Modificar encuesta para permitir una única opción",
|
||||
@@ -172,21 +171,21 @@
|
||||
"confirmations.delete_list.message": "¿Seguro que quieres borrar esta lista permanentemente?",
|
||||
"confirmations.discard_edit_media.confirm": "Descartar",
|
||||
"confirmations.discard_edit_media.message": "Tienes cambios sin guardar en la descripción o vista previa del archivo audiovisual, ¿descartarlos de todos modos?",
|
||||
"confirmations.domain_block.confirm": "Bloquear dominio entero",
|
||||
"confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio {domain} entero? En general unos cuantos bloqueos y silenciados concretos es suficiente y preferible.",
|
||||
"confirmations.domain_block.confirm": "Bloquear todo el dominio",
|
||||
"confirmations.domain_block.message": "¿Seguro que quieres bloquear todo el dominio {domain}? En general, unos cuantos bloqueos y silenciados concretos es suficiente y preferible. No verás contenido del dominio en ninguna cronología pública ni en tus notificaciones. Se eliminarán tus seguidores procedentes de ese dominio.",
|
||||
"confirmations.edit.confirm": "Editar",
|
||||
"confirmations.edit.message": "Editar ahora reemplazará el mensaje que está escribiendo. ¿Está seguro que quiere proceder?",
|
||||
"confirmations.edit.message": "Editar ahora reemplazará el mensaje que estás escribiendo. ¿Seguro que quieres proceder?",
|
||||
"confirmations.logout.confirm": "Cerrar sesión",
|
||||
"confirmations.logout.message": "¿Estás seguro de querer cerrar la sesión?",
|
||||
"confirmations.logout.message": "¿Seguro que quieres cerrar la sesión?",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
"confirmations.mute.explanation": "Esto esconderá las publicaciones de ellos y en las que los has mencionado, pero les permitirá ver tus mensajes y seguirte.",
|
||||
"confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?",
|
||||
"confirmations.mute.explanation": "Esto esconderá sus publicaciones y las publicaciones que los mencionen, pero podrán seguir viendo tus mensajes y seguirte.",
|
||||
"confirmations.mute.message": "¿Seguro que quieres silenciar a {name}?",
|
||||
"confirmations.redraft.confirm": "Borrar y volver a borrador",
|
||||
"confirmations.redraft.message": "¿Estás seguro de querer borrar esta publicación y reescribirla? Los favoritos e impulsos se perderán, y las respuestas a la publicación original quedarán sin contexto.",
|
||||
"confirmations.reply.confirm": "Responder",
|
||||
"confirmations.reply.message": "Responder sobrescribirá el mensaje que estás escribiendo. ¿Seguro que deseas continuar?",
|
||||
"confirmations.unfollow.confirm": "Dejar de seguir",
|
||||
"confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
|
||||
"confirmations.unfollow.message": "¿Seguro que quieres dejar de seguir a {name}?",
|
||||
"conversation.delete": "Borrar conversación",
|
||||
"conversation.mark_as_read": "Marcar como leído",
|
||||
"conversation.open": "Ver conversación",
|
||||
@@ -195,7 +194,7 @@
|
||||
"copypaste.copied": "Copiado",
|
||||
"copypaste.copy_to_clipboard": "Copiar al portapapeles",
|
||||
"directory.federated": "Desde el fediverso conocido",
|
||||
"directory.local": "Sólo de {domain}",
|
||||
"directory.local": "Solo de {domain}",
|
||||
"directory.new_arrivals": "Recién llegados",
|
||||
"directory.recently_active": "Recientemente activo",
|
||||
"disabled_account_banner.account_settings": "Ajustes de la cuenta",
|
||||
@@ -211,11 +210,11 @@
|
||||
"emoji_button.activity": "Actividad",
|
||||
"emoji_button.clear": "Limpiar",
|
||||
"emoji_button.custom": "Personalizado",
|
||||
"emoji_button.flags": "Marcas",
|
||||
"emoji_button.flags": "Banderas",
|
||||
"emoji_button.food": "Comida y bebida",
|
||||
"emoji_button.label": "Insertar emoji",
|
||||
"emoji_button.nature": "Naturaleza",
|
||||
"emoji_button.not_found": "No hay emojis!! ¯\\_(ツ)_/¯",
|
||||
"emoji_button.not_found": "No se encontró ningún emoji coincidente",
|
||||
"emoji_button.objects": "Objetos",
|
||||
"emoji_button.people": "Personas",
|
||||
"emoji_button.recent": "Usados frecuentemente",
|
||||
@@ -231,8 +230,8 @@
|
||||
"empty_column.bookmarked_statuses": "Aún no tienes ninguna publicación guardada como marcador. Cuando guardes una, se mostrará aquí.",
|
||||
"empty_column.community": "La línea de tiempo local está vacía. ¡Escribe algo para empezar la fiesta!",
|
||||
"empty_column.direct": "Aún no tienes menciones privadas. Cuando envíes o recibas una, aparecerán aquí.",
|
||||
"empty_column.domain_blocks": "Todavía no hay dominios ocultos.",
|
||||
"empty_column.explore_statuses": "Nada está en tendencia en este momento. ¡Revisa más tarde!",
|
||||
"empty_column.domain_blocks": "Todavía no hay dominios bloqueados.",
|
||||
"empty_column.explore_statuses": "No hay nada en tendencia en este momento. ¡Revisa más tarde!",
|
||||
"empty_column.favourited_statuses": "Todavía no tienes publicaciones favoritas. Cuando marques una publicación como favorita, se mostrarán aquí.",
|
||||
"empty_column.favourites": "Todavía nadie marcó esta publicación como favorita. Cuando alguien lo haga, se mostrarán aquí.",
|
||||
"empty_column.follow_requests": "No tienes ninguna petición de seguidor. Cuando recibas una, se mostrará aquí.",
|
||||
@@ -278,6 +277,17 @@
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rechazar",
|
||||
"follow_requests.unlocked_explanation": "A pesar de que tu cuenta no es privada, el personal de {domain} ha pensado que quizás deberías revisar manualmente las solicitudes de seguimiento de estas cuentas.",
|
||||
"follow_suggestions.curated_suggestion": "Recomendaciones del equipo",
|
||||
"follow_suggestions.dismiss": "No mostrar de nuevo",
|
||||
"follow_suggestions.hints.featured": "Este perfil ha sido elegido a mano por el equipo de {domain}.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Este perfil es popular entre las personas que sigues.",
|
||||
"follow_suggestions.hints.most_followed": "Este perfil es uno de los más seguidos en {domain}.",
|
||||
"follow_suggestions.hints.most_interactions": "Este perfil ha estado recibiendo recientemente mucha atención en {domain}.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Este perfil es similar a los perfiles que has seguido recientemente.",
|
||||
"follow_suggestions.personalized_suggestion": "Sugerencia personalizada",
|
||||
"follow_suggestions.popular_suggestion": "Sugerencia popular",
|
||||
"follow_suggestions.view_all": "Ver todo",
|
||||
"follow_suggestions.who_to_follow": "A quién seguir",
|
||||
"followed_tags": "Etiquetas seguidas",
|
||||
"footer.about": "Acerca de",
|
||||
"footer.directory": "Directorio de perfiles",
|
||||
@@ -304,13 +314,9 @@
|
||||
"hashtag.follow": "Seguir etiqueta",
|
||||
"hashtag.unfollow": "Dejar de seguir etiqueta",
|
||||
"hashtags.and_other": "…y {count, plural, other {# más}}",
|
||||
"home.actions.go_to_explore": "Ver tendencias",
|
||||
"home.actions.go_to_suggestions": "Encuentra personas a las que seguir",
|
||||
"home.column_settings.basic": "Básico",
|
||||
"home.column_settings.show_reblogs": "Mostrar impulsos",
|
||||
"home.column_settings.show_replies": "Mostrar respuestas",
|
||||
"home.explore_prompt.body": "Tu cronología de inicio tendrá una mezcla de publicaciones de las etiquetas que has escogido seguir, las personas que has decidido seguir y las publicaciones que impulsen. Si crees que está demasiado tranquila, quizás quieras:",
|
||||
"home.explore_prompt.title": "Este es tu punto de partida en Mastodon.",
|
||||
"home.hide_announcements": "Ocultar anuncios",
|
||||
"home.pending_critical_update.body": "Por favor, ¡actualiza tu servidor Mastodon lo antes posible!",
|
||||
"home.pending_critical_update.link": "Ver actualizaciones",
|
||||
@@ -523,10 +529,15 @@
|
||||
"poll_button.add_poll": "Añadir una encuesta",
|
||||
"poll_button.remove_poll": "Eliminar encuesta",
|
||||
"privacy.change": "Ajustar privacidad",
|
||||
"privacy.direct.long": "Todos los mencionados en el post",
|
||||
"privacy.direct.short": "Personas específicas",
|
||||
"privacy.private.long": "Solo tus seguidores",
|
||||
"privacy.private.short": "Seguidores",
|
||||
"privacy.public.long": "Cualquiera dentro y fuera de Mastodon",
|
||||
"privacy.public.short": "Público",
|
||||
"privacy.unlisted.additional": "Esto se comporta exactamente igual que el público, excepto que la publicación no aparecerá en la cronología en directo o en las etiquetas, la exploración o búsqueda de Mastodon, incluso si está optado por activar la cuenta de usuario.",
|
||||
"privacy.unlisted.long": "Menos fanfares algorítmicos",
|
||||
"privacy.unlisted.short": "Público tranquilo",
|
||||
"privacy_policy.last_updated": "Actualizado por última vez {date}",
|
||||
"privacy_policy.title": "Política de Privacidad",
|
||||
"recommended": "Recomendado",
|
||||
@@ -544,7 +555,9 @@
|
||||
"relative_time.minutes": "{number} m",
|
||||
"relative_time.seconds": "{number} s",
|
||||
"relative_time.today": "hoy",
|
||||
"reply_indicator.attachments": "{count, plural, one {# adjunto} other {# adjuntos}}",
|
||||
"reply_indicator.cancel": "Cancelar",
|
||||
"reply_indicator.poll": "Encuesta",
|
||||
"report.block": "Bloquear",
|
||||
"report.block_explanation": "No verás sus publicaciones. No podrán ver tus publicaciones ni seguirte. Podrán saber que están bloqueados.",
|
||||
"report.categories.legal": "Legal",
|
||||
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "Su konto ei ole {locked}. Igaüks saab sind jälgida, et näha su ainult-jälgijatele postitusi.",
|
||||
"compose_form.lock_disclaimer.lock": "lukus",
|
||||
"compose_form.placeholder": "Millest mõtled?",
|
||||
"compose_form.poll.add_option": "Lisa valik",
|
||||
"compose_form.poll.duration": "Küsitluse kestus",
|
||||
"compose_form.poll.multiple": "Valikvastustega",
|
||||
"compose_form.poll.option_placeholder": "Valik {number}",
|
||||
"compose_form.poll.remove_option": "Eemalda see valik",
|
||||
"compose_form.poll.single": "Vali üks",
|
||||
"compose_form.poll.switch_to_multiple": "Muuda küsitlust mitmikvaliku lubamiseks",
|
||||
"compose_form.poll.switch_to_single": "Muuda küsitlust ainult ühe valiku lubamiseks",
|
||||
@@ -305,13 +303,9 @@
|
||||
"hashtag.follow": "Jälgi silti",
|
||||
"hashtag.unfollow": "Lõpeta sildi jälgimine",
|
||||
"hashtags.and_other": "…ja {count, plural, one {}other {# veel}}",
|
||||
"home.actions.go_to_explore": "Vaata, mis on populaarne",
|
||||
"home.actions.go_to_suggestions": "Leia inimesi, keda jälgida",
|
||||
"home.column_settings.basic": "Peamine",
|
||||
"home.column_settings.show_reblogs": "Näita jagamisi",
|
||||
"home.column_settings.show_replies": "Näita vastuseid",
|
||||
"home.explore_prompt.body": "Sinu koduvoos on koos jälgimiseks valitud siltidega postitused, sinu jälgitavate inimeste postitused ja postitused, mida nad jagavad. Kui see tundub liiga vaikne, võid sa soovida:",
|
||||
"home.explore_prompt.title": "See on sinu kodubaas Mastodonis.",
|
||||
"home.hide_announcements": "Peida teadaanded",
|
||||
"home.pending_critical_update.body": "Palun uuenda oma Mastodoni server nii ruttu kui võimalik!",
|
||||
"home.pending_critical_update.link": "Vaata uuendusi",
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
"column_header.unpin": "Desfinkatu",
|
||||
"column_subheading.settings": "Ezarpenak",
|
||||
"community.column_settings.local_only": "Lokala soilik",
|
||||
"community.column_settings.media_only": "Multimedia besterik ez",
|
||||
"community.column_settings.media_only": "Edukiak soilik",
|
||||
"community.column_settings.remote_only": "Urrunekoa soilik",
|
||||
"compose.language.change": "Aldatu hizkuntza",
|
||||
"compose.language.search": "Bilatu hizkuntzak...",
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "Zure kontua ez dago {locked}. Edonork jarraitu zaitzake zure jarraitzaileentzako soilik diren bidalketak ikusteko.",
|
||||
"compose_form.lock_disclaimer.lock": "giltzapetuta",
|
||||
"compose_form.placeholder": "Zer duzu buruan?",
|
||||
"compose_form.poll.add_option": "Gehitu aukera",
|
||||
"compose_form.poll.duration": "Inkestaren iraupena",
|
||||
"compose_form.poll.multiple": "Aukera aniza",
|
||||
"compose_form.poll.option_placeholder": "{number}. aukera",
|
||||
"compose_form.poll.remove_option": "Kendu aukera hau",
|
||||
"compose_form.poll.single": "Hautatu bat",
|
||||
"compose_form.poll.switch_to_multiple": "Aldatu inkesta hainbat aukera onartzeko",
|
||||
"compose_form.poll.switch_to_single": "Aldatu inkesta aukera bakarra onartzeko",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Baimendu",
|
||||
"follow_request.reject": "Ukatu",
|
||||
"follow_requests.unlocked_explanation": "Zure kontua blokeatuta ez badago ere, {domain} domeinuko arduradunek uste dute kontu hauetako jarraipen eskaerak agian eskuz begiratu nahiko dituzula.",
|
||||
"follow_suggestions.curated_suggestion": "Domeinuaren iradokizuna",
|
||||
"follow_suggestions.dismiss": "Ez erakutsi berriro",
|
||||
"follow_suggestions.hints.featured": "Profil hau {domain} domeinuko taldeak eskuz aukeratu du.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Profil hau ezaguna da jarraitzen duzun jendearen artean.",
|
||||
"follow_suggestions.hints.most_followed": "Profil hau {domain} domeinuan gehien jarraitzen den profiletako bat da.",
|
||||
"follow_suggestions.hints.most_interactions": "Profil hau arreta handia jasotzen ari da berriki {domain} domeinuan.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Profil hau duela gutxi jarraitu dituzun profil askoren antzekoa da.",
|
||||
"follow_suggestions.personalized_suggestion": "Iradokizun pertsonalizatua",
|
||||
"follow_suggestions.popular_suggestion": "Iradokizun ezaguna",
|
||||
"follow_suggestions.view_all": "Ikusi denak",
|
||||
"follow_suggestions.who_to_follow": "Zein jarraitu",
|
||||
"followed_tags": "Jarraitutako traolak",
|
||||
"footer.about": "Honi buruz",
|
||||
"footer.directory": "Profil-direktorioa",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Jarraitu traolari",
|
||||
"hashtag.unfollow": "Utzi traola jarraitzeari",
|
||||
"hashtags.and_other": "…eta {count, plural, one {}other {# gehiago}}",
|
||||
"home.actions.go_to_explore": "Ikusi zer dagoen pil-pilean",
|
||||
"home.actions.go_to_suggestions": "Aurkitu jendea jarraitzeko",
|
||||
"home.column_settings.basic": "Oinarrizkoa",
|
||||
"home.column_settings.show_reblogs": "Erakutsi bultzadak",
|
||||
"home.column_settings.show_replies": "Erakutsi erantzunak",
|
||||
"home.explore_prompt.body": "Zure hasierako jarioak jarraitzeko aukeratu dituzun traolen, jarraitzeko aukeratu duzun jendearen eta beraiek bultzatutako argitalpenen nahasketa bat edukiko du. Nahiko isila dirudi oraintxe, beraz, zergatik ez:",
|
||||
"home.explore_prompt.title": "Hau zure hasiera da Mastodonen.",
|
||||
"home.hide_announcements": "Ezkutatu iragarpenak",
|
||||
"home.pending_critical_update.body": "Eguneratu zure Mastodoneko zerbitzaria leheinbailehen!",
|
||||
"home.pending_critical_update.link": "Ikusi eguneraketak",
|
||||
@@ -356,7 +361,7 @@
|
||||
"keyboard_shortcuts.muted": "mutututako erabiltzaileen zerrenda irekitzeko",
|
||||
"keyboard_shortcuts.my_profile": "zure profila irekitzeko",
|
||||
"keyboard_shortcuts.notifications": "jakinarazpenen zutabea irekitzeko",
|
||||
"keyboard_shortcuts.open_media": "media zabaltzeko",
|
||||
"keyboard_shortcuts.open_media": "Ireki edukia",
|
||||
"keyboard_shortcuts.pinned": "Ireki finkatutako bidalketen zerrenda",
|
||||
"keyboard_shortcuts.profile": "egilearen profila irekitzeko",
|
||||
"keyboard_shortcuts.reply": "Erantzun bidalketari",
|
||||
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "حسابتان {locked} نیست. هر کسی میتواند پیگیرتان شده و فرستههای ویژهٔ پیگیرانتان را ببیند.",
|
||||
"compose_form.lock_disclaimer.lock": "قفلشده",
|
||||
"compose_form.placeholder": "تازه چه خبر؟",
|
||||
"compose_form.poll.add_option": "افزودن گزینه",
|
||||
"compose_form.poll.duration": "مدت نظرسنجی",
|
||||
"compose_form.poll.multiple": "چند گزینهای",
|
||||
"compose_form.poll.option_placeholder": "گزینهٔ {number}",
|
||||
"compose_form.poll.remove_option": "برداشتن این گزینه",
|
||||
"compose_form.poll.single": "گزینش یکی",
|
||||
"compose_form.poll.switch_to_multiple": "تغییر نظرسنجی برای اجازه به چندین گزینه",
|
||||
"compose_form.poll.switch_to_single": "تبدیل به نظرسنجی تکگزینهای",
|
||||
@@ -305,13 +303,9 @@
|
||||
"hashtag.follow": "پیگرفتن برچسب",
|
||||
"hashtag.unfollow": "پینگرفتن برچسب",
|
||||
"hashtags.and_other": "…و {count, plural, other {# بیشتر}}",
|
||||
"home.actions.go_to_explore": "ببینید چه داغ است",
|
||||
"home.actions.go_to_suggestions": "یافتن افراد برای پیگیری",
|
||||
"home.column_settings.basic": "پایهای",
|
||||
"home.column_settings.show_reblogs": "نمایش تقویتها",
|
||||
"home.column_settings.show_replies": "نمایش پاسخها",
|
||||
"home.explore_prompt.body": "خوراک خانگیتان ترکیبی از فرستهها از برچسبهایی که برای پیگیری گزیدهاید، افرادی که پی میگیرید و فرستههایی که تقویت میکنند را خواهد داشت. اگر خیلی خلوت به نظر میرسد، شاید بخواهید:",
|
||||
"home.explore_prompt.title": "این پایگاه خانگیتان در ماستودون است.",
|
||||
"home.hide_announcements": "نهفتن اعلامیهها",
|
||||
"home.pending_critical_update.body": "لطفاً کارساز ماستودونتان را در نخستین فرصت بهروز کنید!",
|
||||
"home.pending_critical_update.link": "دیدن بهروز رسانیها",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"about.blocks": "Moderoidut palvelimet",
|
||||
"about.contact": "Ota yhteys:",
|
||||
"about.disclaimer": "Mastodon on vapaa avoimen lähdekoodin ohjelmisto ja Mastodon gGmbH:n tavaramerkki.",
|
||||
"about.domain_blocks.no_reason_available": "Syytä ei ole ilmoitettu",
|
||||
"about.domain_blocks.preamble": "Mastodonin avulla voidaan yleensä tarkastella minkä tahansa fediversumiin kuuluvan palvelimen sisältöä ja vuorovaikuttaa eri palvelinten käyttäjien kanssa. Nämä ovat tälle palvelimelle määritetyt poikkeukset.",
|
||||
"about.domain_blocks.no_reason_available": "Syy ei ole tiedossa",
|
||||
"about.domain_blocks.preamble": "Mastodonin avulla voidaan yleensä tarkastella minkä tahansa fediversumiin kuuluvan palvelimen sisältöä, ja olla yhteyksissä eri palvelinten käyttäjien kanssa. Nämä poikkeukset koskevat yksin tätä palvelinta.",
|
||||
"about.domain_blocks.silenced.explanation": "Et yleensä näe tämän palvelimen profiileja ja sisältöä, jollet erityisesti etsi juuri sitä tai liity siihen seuraamalla.",
|
||||
"about.domain_blocks.silenced.title": "Rajoitettu",
|
||||
"about.domain_blocks.suspended.explanation": "Mitään tämän palvelimen tietoja ei käsitellä, tallenneta tai vaihdeta, mikä tekee vuorovaikutuksesta ja viestinnästä sen käyttäjien kanssa mahdotonta.",
|
||||
@@ -19,7 +19,7 @@
|
||||
"account.block_domain": "Estä verkkotunnus {domain}",
|
||||
"account.block_short": "Estä",
|
||||
"account.blocked": "Estetty",
|
||||
"account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella",
|
||||
"account.browse_more_on_origin_server": "Selaile kattavampaa alkuperäprofiilia",
|
||||
"account.cancel_follow_request": "Peruuta seurantapyyntö",
|
||||
"account.copy": "Kopioi linkki profiiliin",
|
||||
"account.direct": "Mainitse @{name} yksityisesti",
|
||||
@@ -27,7 +27,7 @@
|
||||
"account.domain_blocked": "Verkkotunnus estetty",
|
||||
"account.edit_profile": "Muokkaa profiilia",
|
||||
"account.enable_notifications": "Ilmoita minulle, kun @{name} julkaisee",
|
||||
"account.endorse": "Pidä esillä profiilissa",
|
||||
"account.endorse": "Suosittele profiilissasi",
|
||||
"account.featured_tags.last_status_at": "Viimeisin julkaisu {date}",
|
||||
"account.featured_tags.last_status_never": "Ei julkaisuja",
|
||||
"account.featured_tags.title": "Käyttäjän {name} esillä pidettävät aihetunnisteet",
|
||||
@@ -39,7 +39,7 @@
|
||||
"account.following": "Seuratut",
|
||||
"account.following_counter": "{count, plural, one {{counter} seurattu} other {{counter} seurattua}}",
|
||||
"account.follows.empty": "Tämä käyttäjä ei vielä seuraa ketään.",
|
||||
"account.go_to_profile": "Avaa profiili",
|
||||
"account.go_to_profile": "Mene profiiliin",
|
||||
"account.hide_reblogs": "Piilota käyttäjän @{name} tehostukset",
|
||||
"account.in_memoriam": "Muistoissamme.",
|
||||
"account.joined_short": "Liittynyt",
|
||||
@@ -64,10 +64,10 @@
|
||||
"account.share": "Jaa käyttäjän @{name} profiili",
|
||||
"account.show_reblogs": "Näytä käyttäjän @{name} tehostukset",
|
||||
"account.statuses_counter": "{count, plural, one {{counter} julkaisu} other {{counter} julkaisua}}",
|
||||
"account.unblock": "Poista käyttäjän @{name} esto",
|
||||
"account.unblock_domain": "Poista verkkotunnuksen {domain} esto",
|
||||
"account.unblock": "Kumoa käyttäjän @{name} esto",
|
||||
"account.unblock_domain": "Kumoa verkkotunnuksen {domain} esto",
|
||||
"account.unblock_short": "Poista esto",
|
||||
"account.unendorse": "Älä pidä esillä profiilissa",
|
||||
"account.unendorse": "Kumoa suosittelu profiilissasi",
|
||||
"account.unfollow": "Lopeta seuraaminen",
|
||||
"account.unmute": "Poista käyttäjän @{name} mykistys",
|
||||
"account.unmute_notifications_short": "Poista ilmoitusten mykistys",
|
||||
@@ -75,7 +75,7 @@
|
||||
"account_note.placeholder": "Lisää muistiinpano napsauttamalla",
|
||||
"admin.dashboard.daily_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen päivittäin",
|
||||
"admin.dashboard.monthly_retention": "Käyttäjien pysyvyys rekisteröitymisen jälkeen kuukausittain",
|
||||
"admin.dashboard.retention.average": "Keskimäärin",
|
||||
"admin.dashboard.retention.average": "Keskiarvo",
|
||||
"admin.dashboard.retention.cohort": "Rekisteröitymis-kk.",
|
||||
"admin.dashboard.retention.cohort_size": "Uusia käyttäjiä",
|
||||
"admin.impact_report.instance_accounts": "Tilien profiilit, jotka tämä poistaisi",
|
||||
@@ -86,7 +86,7 @@
|
||||
"alert.rate_limited.title": "Pyyntömäärää rajoitettu",
|
||||
"alert.unexpected.message": "Tapahtui odottamaton virhe.",
|
||||
"alert.unexpected.title": "Hups!",
|
||||
"announcement.announcement": "Ilmoitus",
|
||||
"announcement.announcement": "Tiedote",
|
||||
"attachments_list.unprocessed": "(käsittelemätön)",
|
||||
"audio.hide": "Piilota ääni",
|
||||
"boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}",
|
||||
@@ -145,14 +145,12 @@
|
||||
"compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille rajaamasi julkaisut.",
|
||||
"compose_form.lock_disclaimer.lock": "lukittu",
|
||||
"compose_form.placeholder": "Mitä mietit?",
|
||||
"compose_form.poll.add_option": "Lisää vaihtoehto",
|
||||
"compose_form.poll.duration": "Äänestyksen kesto",
|
||||
"compose_form.poll.multiple": "Monivalinta",
|
||||
"compose_form.poll.option_placeholder": "Vaihtoehto {number}",
|
||||
"compose_form.poll.remove_option": "Poista tämä vaihtoehto",
|
||||
"compose_form.poll.single": "Valitse yksi",
|
||||
"compose_form.poll.switch_to_multiple": "Muuta äänestys monivalinnaksi",
|
||||
"compose_form.poll.switch_to_single": "Muuta äänestys sallimaan vain yksi valinta",
|
||||
"compose_form.poll.switch_to_multiple": "Muuta kysely monivalinnaksi",
|
||||
"compose_form.poll.switch_to_single": "Muuta kysely sallimaan vain yksi valinta",
|
||||
"compose_form.poll.type": "Tyyli",
|
||||
"compose_form.publish": "Julkaise",
|
||||
"compose_form.publish_form": "Uusi julkaisu",
|
||||
@@ -166,13 +164,13 @@
|
||||
"confirmations.block.confirm": "Estä",
|
||||
"confirmations.block.message": "Haluatko varmasti estää käyttäjän {name}?",
|
||||
"confirmations.cancel_follow_request.confirm": "Peruuta pyyntö",
|
||||
"confirmations.cancel_follow_request.message": "Haluatko varmasti peruuttaa pyyntösi seurata profiilia {name}?",
|
||||
"confirmations.cancel_follow_request.message": "Haluatko varmasti perua pyyntösi seurata käyttäjätiliä {name}?",
|
||||
"confirmations.delete.confirm": "Poista",
|
||||
"confirmations.delete.message": "Haluatko varmasti poistaa tämän julkaisun?",
|
||||
"confirmations.delete_list.confirm": "Poista",
|
||||
"confirmations.delete_list.message": "Haluatko varmasti poistaa tämän listan pysyvästi?",
|
||||
"confirmations.discard_edit_media.confirm": "Hylkää",
|
||||
"confirmations.discard_edit_media.message": "Sinulla on tallentamattomia muutoksia median kuvaukseen tai esikatseluun, hylätäänkö ne silti?",
|
||||
"confirmations.discard_edit_media.message": "Sinulla on tallentamattomia muutoksia median kuvaukseen tai esikatseluun. Hylätäänkö ne silti?",
|
||||
"confirmations.domain_block.confirm": "Estä koko verkkotunnus",
|
||||
"confirmations.domain_block.message": "Haluatko aivan varmasti estää koko verkkotunnuksen {domain}? Useimmiten muutama kohdistettu esto tai mykistys on riittävä ja suositeltava toimi. Et näe sisältöä tästä verkkotunnuksesta millään julkisilla aikajanoilla tai ilmoituksissa. Tähän verkkotunnukseen kuuluvat seuraajasi poistetaan.",
|
||||
"confirmations.edit.confirm": "Muokkaa",
|
||||
@@ -182,12 +180,12 @@
|
||||
"confirmations.mute.confirm": "Mykistä",
|
||||
"confirmations.mute.explanation": "Tämä toiminto piilottaa heidän julkaisunsa sinulta – mukaan lukien ne, joissa heidät mainitaan – sallien heidän yhä nähdä julkaisusi ja seurata sinua.",
|
||||
"confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?",
|
||||
"confirmations.redraft.confirm": "Poista & palauta muokattavaksi",
|
||||
"confirmations.redraft.confirm": "Poista ja palauta muokattavaksi",
|
||||
"confirmations.redraft.message": "Haluatko varmasti poistaa julkaisun ja tehdä siitä luonnoksen? Suosikit ja tehostukset menetetään, ja alkuperäisen julkaisun vastaukset jäävät orvoiksi.",
|
||||
"confirmations.reply.confirm": "Vastaa",
|
||||
"confirmations.reply.message": "Jos vastaat nyt, vastaus korvaa parhaillaan työstämäsi viestin. Haluatko varmasti jatkaa?",
|
||||
"confirmations.unfollow.confirm": "Lopeta seuraaminen",
|
||||
"confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta profiilia {name}?",
|
||||
"confirmations.unfollow.message": "Haluatko varmasti lopettaa profiilin {name} seuraamisen?",
|
||||
"conversation.delete": "Poista keskustelu",
|
||||
"conversation.mark_as_read": "Merkitse luetuksi",
|
||||
"conversation.open": "Näytä keskustelu",
|
||||
@@ -201,10 +199,10 @@
|
||||
"directory.recently_active": "Hiljattain aktiiviset",
|
||||
"disabled_account_banner.account_settings": "Tilin asetukset",
|
||||
"disabled_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä.",
|
||||
"dismissable_banner.community_timeline": "Nämä ovat viimeisimpiä julkaisuja käyttäjiltä, joiden tili sijaitsee palvelimella {domain}.",
|
||||
"dismissable_banner.community_timeline": "Nämä ovat tuoreimpia julkaisuja käyttäjiltä, joiden tili on palvelimella {domain}.",
|
||||
"dismissable_banner.dismiss": "Hylkää",
|
||||
"dismissable_banner.explore_links": "Näitä uutisia jaetaan tänään sosiaalisessa verkossa eniten. Uusimmat ja eri käyttäjien eniten lähettämät uutiset nousevat listauksessa korkeimmalle.",
|
||||
"dismissable_banner.explore_statuses": "Nämä sosiaalisen verkon julkaisut keräävät tänään eniten huomiota. Uusimmat, tehostetuimmat ja suosikiksi lisätyimmät nousevat listauksessa korkeimmalle.",
|
||||
"dismissable_banner.explore_statuses": "Tänään nämä sosiaalisen verkon julkaisut keräävät eniten huomiota. Uusimmat, tehostetuimmat ja suosikeiksi lisätyimmät julkaisut nousevat listauksessa korkeammalle.",
|
||||
"dismissable_banner.explore_tags": "Nämä sosiaalisen verkon aihetunnisteet keräävät tänään eniten huomiota. Useimman käyttäjän käyttämät aihetunnisteet nousevat listauksessa korkeimmalle.",
|
||||
"dismissable_banner.public_timeline": "Nämä ovat viimeisimpiä julkaisuja sosiaalisen verkon käyttäjiltä, joita seurataan palvelimella {domain}.",
|
||||
"embed.instructions": "Upota julkaisu verkkosivullesi kopioimalla alla oleva koodi.",
|
||||
@@ -216,18 +214,18 @@
|
||||
"emoji_button.food": "Ruoka ja juoma",
|
||||
"emoji_button.label": "Lisää emoji",
|
||||
"emoji_button.nature": "Luonto",
|
||||
"emoji_button.not_found": "Vastaavia emojeja ei löytynyt",
|
||||
"emoji_button.not_found": "Vastaavia emojeita ei löytynyt",
|
||||
"emoji_button.objects": "Esineet",
|
||||
"emoji_button.people": "Ihmiset",
|
||||
"emoji_button.recent": "Usein käytetyt",
|
||||
"emoji_button.search": "Hae...",
|
||||
"emoji_button.search": "Etsi...",
|
||||
"emoji_button.search_results": "Hakutulokset",
|
||||
"emoji_button.symbols": "Symbolit",
|
||||
"emoji_button.travel": "Matkailu ja paikat",
|
||||
"empty_column.account_hides_collections": "Käyttäjä on päättänyt olla julkaisematta näitä tietoja",
|
||||
"empty_column.account_hides_collections": "Käyttäjä on päättänyt pitää nämä tiedot yksityisinä",
|
||||
"empty_column.account_suspended": "Tili jäädytetty",
|
||||
"empty_column.account_timeline": "Ei viestejä täällä.",
|
||||
"empty_column.account_unavailable": "Profiilia ei löydy",
|
||||
"empty_column.account_unavailable": "Profiilia ei ole saatavilla",
|
||||
"empty_column.blocks": "Et ole vielä estänyt käyttäjiä.",
|
||||
"empty_column.bookmarked_statuses": "Et ole vielä lisännyt julkaisuja kirjanmerkkeihisi. Kun lisäät yhden, se näkyy tässä.",
|
||||
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista, niin homma lähtee käyntiin!",
|
||||
@@ -238,17 +236,17 @@
|
||||
"empty_column.favourites": "Kukaan ei ole vielä lisännyt tätä julkaisua suosikkeihinsa. Kun joku tekee niin, tulee hän tähän näkyviin.",
|
||||
"empty_column.follow_requests": "Et ole vielä vastaanottanut seuraamispyyntöjä. Saamasi pyynnöt näkyvät täällä.",
|
||||
"empty_column.followed_tags": "Et seuraa vielä yhtäkään aihetunnistetta. Kun alat seurata, ne tulevat tähän näkyviin.",
|
||||
"empty_column.hashtag": "Tällä aihetunnisteella ei ole vielä mitään.",
|
||||
"empty_column.hashtag": "Tällä aihetunnisteella ei löydy vielä sisältöä.",
|
||||
"empty_column.home": "Kotiaikajanasi on tyhjä! Seuraa useampia henkilöjä, niin näet enemmän sisältöä.",
|
||||
"empty_column.list": "Tällä listalla ei ole vielä mitään. Kun tämän listan jäsenet lähettävät uusia julkaisuja, ne näkyvät tässä.",
|
||||
"empty_column.lists": "Sinulla ei ole vielä yhtään listaa. Kun luot sellaisen, näkyy se tässä.",
|
||||
"empty_column.mutes": "Et ole mykistänyt vielä yhtään käyttäjää.",
|
||||
"empty_column.notifications": "Sinulla ei ole vielä ilmoituksia. Kun keskustelet muille, näet sen täällä.",
|
||||
"empty_column.public": "Täällä ei ole mitään! Kirjoita jotain julkisesti. Voit myös seurata muiden palvelimien käyttäjiä",
|
||||
"error.unexpected_crash.explanation": "Sivua ei voi näyttää oikein, johtuen bugista tai ongelmasta selaimen yhteensopivuudessa.",
|
||||
"error.unexpected_crash.explanation": "Sivua ei voida näyttää oikein ohjelmointivirheen tai selaimen yhteensopivuusvajeen vuoksi.",
|
||||
"error.unexpected_crash.explanation_addons": "Sivua ei voitu näyttää oikein. Tämä virhe johtuu todennäköisesti selaimen lisäosasta tai automaattisista käännöstyökaluista.",
|
||||
"error.unexpected_crash.next_steps": "Kokeile päivittää sivu. Jos se ei auta, voi Mastodonin käyttö ehkä onnistua eri selaimella tai natiivisovelluksella.",
|
||||
"error.unexpected_crash.next_steps_addons": "Yritä poistaa ne käytöstä ja päivittää sivu. Jos se ei auta, voit silti käyttää Mastodonia eri selaimen tai sovelluksen kautta.",
|
||||
"error.unexpected_crash.next_steps_addons": "Yritä poistaa ne käytöstä, ja virkistä sitten sivunlataus. Mikäli ongelma jatkuu, voit mahdollisesti käyttää Mastodonia eri selaimella tai natiivilla sovelluksella.",
|
||||
"errors.unexpected_crash.copy_stacktrace": "Kopioi pinon jäljitys leikepöydälle",
|
||||
"errors.unexpected_crash.report_issue": "Ilmoita ongelmasta",
|
||||
"explore.search_results": "Hakutulokset",
|
||||
@@ -257,13 +255,13 @@
|
||||
"explore.trending_links": "Uutiset",
|
||||
"explore.trending_statuses": "Julkaisut",
|
||||
"explore.trending_tags": "Aihetunnisteet",
|
||||
"filter_modal.added.context_mismatch_explanation": "Tämä suodatinluokka ei koske kontekstia, jossa olet tarkastellut tätä julkaisua. Jos haluat, että julkaisu suodatetaan myös tässä kontekstissa, sinun pitää muokata suodatinta.",
|
||||
"filter_modal.added.context_mismatch_title": "Konteksti ei täsmää!",
|
||||
"filter_modal.added.expired_explanation": "Tämä suodatinluokka on vanhentunut, joten sinun on muutettava viimeistä voimassaolopäivää, jotta suodatin on voimassa.",
|
||||
"filter_modal.added.context_mismatch_explanation": "Tämä suodatinluokka ei koske asiayhteyttä, jossa olet tarkastellut tätä julkaisua. Jos haluat julkaisun suodatettavan myös tässä asiayhteydessä, muokkaa suodatinta.",
|
||||
"filter_modal.added.context_mismatch_title": "Asiayhteys ei täsmää!",
|
||||
"filter_modal.added.expired_explanation": "Tämä suodatinluokka on vanhentunut, joten sinun on muutettava viimeistä voimassaolopäivää, jotta suodatusta käytettäisiin.",
|
||||
"filter_modal.added.expired_title": "Vanhentunut suodatin!",
|
||||
"filter_modal.added.review_and_configure": "Voit tarkastella tätä suodatinluokkaa ja määrittää sen tarkemmin kohdassa {settings_link}.",
|
||||
"filter_modal.added.review_and_configure": "Voit tarkastella tätä suodatinluokkaa ja määrittää sen tarkemmin {settings_link}.",
|
||||
"filter_modal.added.review_and_configure_title": "Suodattimen asetukset",
|
||||
"filter_modal.added.settings_link": "asetukset-sivulle",
|
||||
"filter_modal.added.settings_link": "asetussivulla",
|
||||
"filter_modal.added.short_explanation": "Tämä julkaisu on lisätty seuraavaan suodatinluokkaan: {title}.",
|
||||
"filter_modal.added.title": "Suodatin lisätty!",
|
||||
"filter_modal.select_filter.context_mismatch": "ei sovellu tähän kontekstiin",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Valtuuta",
|
||||
"follow_request.reject": "Hylkää",
|
||||
"follow_requests.unlocked_explanation": "Vaikkei tiliäsi ole lukittu, palvelimen {domain} ylläpito on arvioinut, että saatat olla halukas tarkistamaan nämä seuraamispyynnöt erikseen.",
|
||||
"follow_suggestions.curated_suggestion": "Ylläpidon valinta",
|
||||
"follow_suggestions.dismiss": "Älä näytä uudelleen",
|
||||
"follow_suggestions.hints.featured": "Tämän profiilin on valinnut palvelimen {domain} tiimi.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Tämä profiili on suosittu seuraamiesi henkilöiden parissa.",
|
||||
"follow_suggestions.hints.most_followed": "Tämä profiili on yksi seuratuimmista palvelimella {domain}.",
|
||||
"follow_suggestions.hints.most_interactions": "Tämä profiili on viime aikoina saanut paljon huomiota palvelimella {domain}.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Tämä profiili on samankaltainen kuin profiilit, joita olet viimeksi seurannut.",
|
||||
"follow_suggestions.personalized_suggestion": "Personoitu ehdotus",
|
||||
"follow_suggestions.popular_suggestion": "Suosittu ehdotus",
|
||||
"follow_suggestions.view_all": "Näytä kaikki",
|
||||
"follow_suggestions.who_to_follow": "Ehdotuksia seurattavaksi",
|
||||
"followed_tags": "Seuratut aihetunnisteet",
|
||||
"footer.about": "Tietoja",
|
||||
"footer.directory": "Profiilihakemisto",
|
||||
@@ -305,15 +314,11 @@
|
||||
"hashtag.follow": "Seuraa aihetunnistetta",
|
||||
"hashtag.unfollow": "Lopeta aihetunnisteen seuraaminen",
|
||||
"hashtags.and_other": "…ja {count, plural, other {# lisää}}",
|
||||
"home.actions.go_to_explore": "Katso, mikä on suosittua",
|
||||
"home.actions.go_to_suggestions": "Löydä seurattavia käyttäjiä",
|
||||
"home.column_settings.basic": "Perusasetukset",
|
||||
"home.column_settings.show_reblogs": "Näytä tehostukset",
|
||||
"home.column_settings.show_replies": "Näytä vastaukset",
|
||||
"home.explore_prompt.body": "Kotisyötteesi on sekoitus seuraamiasi aihetunnisteita ja käyttäjiä sekä heidän tehostamiaan julkaisuja. Jos se tuntuu liian hiljaiselta, saatat haluta:",
|
||||
"home.explore_prompt.title": "Tämä on tukikohtasi Mastodonissa.",
|
||||
"home.hide_announcements": "Piilota tiedotteet",
|
||||
"home.pending_critical_update.body": "Päivitäthän Mastodon-palvelimen mahdollisimman pian!",
|
||||
"home.pending_critical_update.body": "Päivitäthän Mastodon-palvelinohjelmistosi mahdollisimman pian!",
|
||||
"home.pending_critical_update.link": "Tutustu päivityssisältöihin",
|
||||
"home.pending_critical_update.title": "Kriittinen tietoturvapäivitys saatavilla!",
|
||||
"home.show_announcements": "Näytä tiedotteet",
|
||||
@@ -352,7 +357,7 @@
|
||||
"keyboard_shortcuts.hotkey": "Pikanäppäin",
|
||||
"keyboard_shortcuts.legend": "Näytä tämä ohje",
|
||||
"keyboard_shortcuts.local": "Avaa paikallinen aikajana",
|
||||
"keyboard_shortcuts.mention": "Mainitse kirjoittaja",
|
||||
"keyboard_shortcuts.mention": "Mainitse julkaisija",
|
||||
"keyboard_shortcuts.muted": "Avaa mykistettyjen käyttäjien luettelo",
|
||||
"keyboard_shortcuts.my_profile": "Avaa profiilisi",
|
||||
"keyboard_shortcuts.notifications": "Avaa ilmoitussarake",
|
||||
@@ -370,12 +375,12 @@
|
||||
"keyboard_shortcuts.unfocus": "Poistu teksti-/hakukentästä",
|
||||
"keyboard_shortcuts.up": "Siirry listassa ylöspäin",
|
||||
"lightbox.close": "Sulje",
|
||||
"lightbox.compress": "Pakkaa kuvan näkymälaatikko",
|
||||
"lightbox.expand": "Laajenna kuvan näkymälaatikko",
|
||||
"lightbox.compress": "Tiivis kuvankatselunäkymä",
|
||||
"lightbox.expand": "Laajennettu kuvankatselunäkymä",
|
||||
"lightbox.next": "Seuraava",
|
||||
"lightbox.previous": "Edellinen",
|
||||
"limited_account_hint.action": "Näytä profiili joka tapauksessa",
|
||||
"limited_account_hint.title": "Palvelun {domain} valvojat ovat piilottaneet tämän profiilin.",
|
||||
"limited_account_hint.title": "Palvelimen {domain} valvojat ovat piilottaneet tämän käyttäjätilin.",
|
||||
"link_preview.author": "Julkaissut {name}",
|
||||
"lists.account.add": "Lisää listalle",
|
||||
"lists.account.remove": "Poista listalta",
|
||||
@@ -389,21 +394,21 @@
|
||||
"lists.replies_policy.list": "Listan jäsenille",
|
||||
"lists.replies_policy.none": "Ei kellekään",
|
||||
"lists.replies_policy.title": "Näytä vastaukset:",
|
||||
"lists.search": "Etsi seuraamistasi henkilöistä",
|
||||
"lists.search": "Etsi seuraamiesi henkilöiden keskuudesta",
|
||||
"lists.subheading": "Omat listasi",
|
||||
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
|
||||
"loading_indicator.label": "Ladataan…",
|
||||
"media_gallery.toggle_visible": "{number, plural, one {Piilota kuva} other {Piilota kuvat}}",
|
||||
"moved_to_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä, koska teit siirron tiliin {movedToAccount}.",
|
||||
"mute_modal.duration": "Kesto",
|
||||
"mute_modal.hide_notifications": "Piilota tältä käyttäjältä tulevat ilmoitukset?",
|
||||
"mute_modal.hide_notifications": "Piilotetaanko tältä käyttäjältä tulevat ilmoitukset?",
|
||||
"mute_modal.indefinite": "Ikuisesti",
|
||||
"navigation_bar.about": "Tietoja",
|
||||
"navigation_bar.advanced_interface": "Avaa edistyneessä selainkäyttöliittymässä",
|
||||
"navigation_bar.blocks": "Estetyt käyttäjät",
|
||||
"navigation_bar.bookmarks": "Kirjanmerkit",
|
||||
"navigation_bar.community_timeline": "Paikallinen aikajana",
|
||||
"navigation_bar.compose": "Kirjoita uusi julkaisu",
|
||||
"navigation_bar.compose": "Luo uusi julkaisu",
|
||||
"navigation_bar.direct": "Yksityiset maininnat",
|
||||
"navigation_bar.discover": "Löydä uutta",
|
||||
"navigation_bar.domain_blocks": "Estetyt verkkotunnukset",
|
||||
@@ -428,10 +433,10 @@
|
||||
"notification.admin.sign_up": "{name} rekisteröityi",
|
||||
"notification.favourite": "{name} lisäsi julkaisusi suosikkeihinsa",
|
||||
"notification.follow": "{name} seurasi sinua",
|
||||
"notification.follow_request": "{name} haluaa seurata sinua",
|
||||
"notification.follow_request": "{name} on pyytänyt lupaa saada seurata sinua",
|
||||
"notification.mention": "{name} mainitsi sinut",
|
||||
"notification.own_poll": "Äänestyksesi on päättynyt",
|
||||
"notification.poll": "Äänestys, johon osallistuit, on päättynyt",
|
||||
"notification.poll": "Kysely, johon osallistuit, on päättynyt",
|
||||
"notification.reblog": "{name} tehosti julkaisuasi",
|
||||
"notification.status": "{name} julkaisi juuri",
|
||||
"notification.update": "{name} muokkasi julkaisua",
|
||||
@@ -478,7 +483,7 @@
|
||||
"onboarding.actions.go_to_home": "Siirry kotisyötteeseeni",
|
||||
"onboarding.compose.template": "Tervehdys #Mastodon!",
|
||||
"onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.",
|
||||
"onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!",
|
||||
"onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta – voit milloin tahansa myös lopettaa niiden seuraamisen:",
|
||||
"onboarding.follows.title": "Mukauta kotisyötettäsi",
|
||||
"onboarding.profile.discoverable": "Aseta profiilini löydettäväksi",
|
||||
"onboarding.profile.discoverable_hint": "Kun olet määrittänyt itsesi löydettäväksi Mastodonista, julkaisusi voivat näkyä hakutuloksissa ja suosituissa kohteissa. Lisäksi profiiliasi voidaan ehdottaa käyttäjille, jotka ovat kiinnostuneita kanssasi samoista aiheista.",
|
||||
@@ -506,7 +511,7 @@
|
||||
"onboarding.steps.setup_profile.title": "Mukauta profiiliasi",
|
||||
"onboarding.steps.share_profile.body": "Kerro kavereillesi, kuinka sinut löytää Mastodonista",
|
||||
"onboarding.steps.share_profile.title": "Jaa Mastodon-profiilisi",
|
||||
"onboarding.tips.2fa": "<strong>Tiesitkö?</strong> Voit suojata tilisi ottamalla kaksivaiheisen todennuksen käyttöön tilisi asetuksista. Se toimii millä tahansa TOTP-sovelluksella, eikä sen käyttö edellytä puhelinnumeroa!",
|
||||
"onboarding.tips.2fa": "<strong>Tiesitkö?</strong> Voit suojata tilisi ottamalla kaksivaiheisen todennuksen käyttöön tilisi asetuksista. Se toimii millä tahansa TOTP-sovelluksella, eikä sen käyttö edellytä puhelinnumeron antoa!",
|
||||
"onboarding.tips.accounts_from_other_servers": "<strong>Tiesitkö?</strong> Koska Mastodon on hajautettu, osa kohtaamistasi profiileista sijaitsee muilla kuin sinun palvelimellasi. Voit silti viestiä saumattomasti heidän kanssaan! Heidän palvelimensa mainitaan käyttäjänimen jälkiosassa!",
|
||||
"onboarding.tips.migration": "<strong>Tiesitkö?</strong> Jos koet, ettei {domain} ole jatkossa itsellesi hyvä palvelinvalinta, voit siirtyä toiselle Mastodon-palvelimelle menettämättä seuraajiasi. Voit jopa isännöidä omaa palvelintasi!",
|
||||
"onboarding.tips.verification": "<strong>Tiesitkö?</strong> Voit vahvistaa tilisi lisäämällä omalle verkkosivustollesi linkin Mastodon-profiiliisi ja lisäämällä sitten verkkosivustosi osoitteen Mastodon-profiilisi lisäkenttään. Tämä ei maksa mitään, eikä sinun tarvitse lähetellä asiakirjoja!",
|
||||
@@ -521,8 +526,8 @@
|
||||
"poll.vote": "Äänestä",
|
||||
"poll.voted": "Äänestit tätä vastausta",
|
||||
"poll.votes": "{votes, plural, one {# ääni} other {# ääntä}}",
|
||||
"poll_button.add_poll": "Lisää äänestys",
|
||||
"poll_button.remove_poll": "Poista äänestys",
|
||||
"poll_button.add_poll": "Lisää kysely",
|
||||
"poll_button.remove_poll": "Poista kysely",
|
||||
"privacy.change": "Muuta julkaisun näkyvyyttä",
|
||||
"privacy.direct.long": "Kaikki tässä julkaisussa mainitut",
|
||||
"privacy.direct.short": "Tietyt henkilöt",
|
||||
@@ -530,7 +535,9 @@
|
||||
"privacy.private.short": "Seuraajat",
|
||||
"privacy.public.long": "Kuka tahansa Mastodonissa ja sen ulkopuolella",
|
||||
"privacy.public.short": "Julkinen",
|
||||
"privacy.unlisted.additional": "Tämä toimii kuten julkinen, paitsi että julkaisu ei näy livesyötteissä, aihetunnisteissa, selaa-näkymässä tai Mastodon-haussa, vaikka olisit sallinut ne käyttäjätilin laajuisesti.",
|
||||
"privacy.unlisted.additional": "Tämä on muutoin kuin julkinen julkaisu, mutta sitä ei näytetä livesyöte-, aihetunniste- tai selailunäkymissä eikä Mastodon-hakutuloksissakaan, vaikka ne olisivat käyttäjätililläsi yleisesti sallittuina.",
|
||||
"privacy.unlisted.long": "Vähemmän algoritmiperusteista sisältöä",
|
||||
"privacy.unlisted.short": "Vaivihkaisesti julkinen",
|
||||
"privacy_policy.last_updated": "Viimeksi päivitetty {date}",
|
||||
"privacy_policy.title": "Tietosuojakäytäntö",
|
||||
"recommended": "Suositeltu",
|
||||
@@ -553,16 +560,16 @@
|
||||
"reply_indicator.poll": "Kysely",
|
||||
"report.block": "Estä",
|
||||
"report.block_explanation": "Et näe hänen viestejään, eikä hän voi nähdä viestejäsi tai seurata sinua. Hän näkee, että olet estänyt hänet.",
|
||||
"report.categories.legal": "Lakiasiat",
|
||||
"report.categories.legal": "Juridiset tiedot",
|
||||
"report.categories.other": "Muu",
|
||||
"report.categories.spam": "Roskaposti",
|
||||
"report.categories.violation": "Sisältö rikkoo yhtä tai useampaa palvelimen sääntöä",
|
||||
"report.categories.violation": "Sisältö rikkoo yhtä tai useampaa palvelimen säännöistä",
|
||||
"report.category.subtitle": "Valitse sopivin",
|
||||
"report.category.title": "Kerro meille, miksi tämä {type} pitää raportoida",
|
||||
"report.category.title_account": "profiili",
|
||||
"report.category.title_status": "julkaisu",
|
||||
"report.category.title_account": "profiilissa",
|
||||
"report.category.title_status": "julkaisussa",
|
||||
"report.close": "Valmis",
|
||||
"report.comment.title": "Olisiko jotain muuta, mitä meidän pitäisi tietää?",
|
||||
"report.comment.title": "Onko vielä jotain muuta, mitä meidän pitäisi tietää?",
|
||||
"report.forward": "Välitä kohteeseen {target}",
|
||||
"report.forward_hint": "Tämä tili on toisella palvelimella. Haluatko lähettää nimettömän raportin myös sinne?",
|
||||
"report.mute": "Mykistä",
|
||||
@@ -570,18 +577,18 @@
|
||||
"report.next": "Seuraava",
|
||||
"report.placeholder": "Lisäkommentit",
|
||||
"report.reasons.dislike": "En pidä siitä",
|
||||
"report.reasons.dislike_description": "Et halua nähdä sitä",
|
||||
"report.reasons.dislike_description": "Sisältö on sen tyyppistä, ettet halua nähdä sitä",
|
||||
"report.reasons.legal": "Se on laitonta",
|
||||
"report.reasons.legal_description": "Katsot sisällön rikkovan maasi tai palvelimen kotimaan lakeja",
|
||||
"report.reasons.other": "Jotain muuta",
|
||||
"report.reasons.other_description": "Ongelma ei sovi muihin kategorioihin",
|
||||
"report.reasons.other_description": "Muut raportointisyyt eivät kuvaa ongelmaa",
|
||||
"report.reasons.spam": "Se on roskapostia",
|
||||
"report.reasons.spam_description": "Haitalliset linkit, väärennetyt sitoutumiset tai toistuvat vastaukset",
|
||||
"report.reasons.spam_description": "Haitalliset linkit, henkilöväärennökset tai itseään toistavat vastaukset",
|
||||
"report.reasons.violation": "Se rikkoo palvelimen sääntöjä",
|
||||
"report.reasons.violation_description": "Tiedät, että se rikkoo tiettyjä sääntöjä",
|
||||
"report.reasons.violation_description": "Tiedät sisällön rikkovan tiettyjä sääntöjä",
|
||||
"report.rules.subtitle": "Valitse kaikki sopivat",
|
||||
"report.rules.title": "Mitä sääntöjä rikotaan?",
|
||||
"report.statuses.subtitle": "Valitse kaikki sopivat",
|
||||
"report.statuses.subtitle": "Valitse kaikki soveltuvat julkaisut",
|
||||
"report.statuses.title": "Onko julkaisuja, jotka tukevat tätä raporttia?",
|
||||
"report.submit": "Lähetä",
|
||||
"report.target": "Raportoidaan {target}",
|
||||
@@ -595,14 +602,14 @@
|
||||
"report_notification.categories.legal": "Laillinen",
|
||||
"report_notification.categories.other": "Muu",
|
||||
"report_notification.categories.spam": "Roskaposti",
|
||||
"report_notification.categories.violation": "Sääntöjen rikkominen",
|
||||
"report_notification.categories.violation": "Sääntörikkomus",
|
||||
"report_notification.open": "Avaa raportti",
|
||||
"search.no_recent_searches": "Ei viimeaikaisia hakuja",
|
||||
"search.placeholder": "Hae",
|
||||
"search.quick_action.account_search": "Profiilit haulla {x}",
|
||||
"search.quick_action.go_to_account": "Siirry profiiliin {x}",
|
||||
"search.quick_action.go_to_hashtag": "Siirry aihetunnisteeseen {x}",
|
||||
"search.quick_action.open_url": "Avaa URL-osoite Mastodonissa",
|
||||
"search.quick_action.open_url": "Avaa verkko-osoite Mastodonissa",
|
||||
"search.quick_action.status_search": "Julkaisut haulla {x}",
|
||||
"search.search_or_paste": "Hae tai liitä URL-osoite",
|
||||
"search_popout.full_text_search_disabled_message": "Ei saatavilla palvelimella {domain}.",
|
||||
@@ -611,16 +618,16 @@
|
||||
"search_popout.options": "Hakuvalinnat",
|
||||
"search_popout.quick_actions": "Pikatoiminnot",
|
||||
"search_popout.recent": "Viimeaikaiset haut",
|
||||
"search_popout.specific_date": "tarkka päiväys",
|
||||
"search_popout.specific_date": "tietty päivämäärä",
|
||||
"search_popout.user": "käyttäjä",
|
||||
"search_results.accounts": "Profiilit",
|
||||
"search_results.all": "Kaikki",
|
||||
"search_results.hashtags": "Aihetunnisteet",
|
||||
"search_results.nothing_found": "Näille hakusanoille ei löytynyt mitään",
|
||||
"search_results.nothing_found": "Hakusi ei tuottanut tuloksia",
|
||||
"search_results.see_all": "Näytä kaikki",
|
||||
"search_results.statuses": "Julkaisut",
|
||||
"search_results.title": "Hae {q}",
|
||||
"server_banner.about_active_users": "Palvelinta käyttäneet ihmiset viimeisen 30 päivän aikana (kuukauden aktiiviset käyttäjät)",
|
||||
"server_banner.about_active_users": "Palvelimen käyttäjät viimeisten 30 päivän ajalta (kuukauden aktiiviset käyttäjät)",
|
||||
"server_banner.active_users": "aktiivista käyttäjää",
|
||||
"server_banner.administered_by": "Ylläpitäjä:",
|
||||
"server_banner.introduction": "{domain} kuuluu hajautettuun sosiaaliseen verkostoon, jonka voimanlähde on {mastodon}.",
|
||||
@@ -657,7 +664,7 @@
|
||||
"status.media.show": "Napsauta näyttääksesi",
|
||||
"status.media_hidden": "Media piilotettu",
|
||||
"status.mention": "Mainitse @{name}",
|
||||
"status.more": "Lisää",
|
||||
"status.more": "Enemmän",
|
||||
"status.mute": "Mykistä @{name}",
|
||||
"status.mute_conversation": "Mykistä keskustelu",
|
||||
"status.open": "Laajenna julkaisu",
|
||||
@@ -679,14 +686,14 @@
|
||||
"status.show_filter_reason": "Näytä joka tapauksessa",
|
||||
"status.show_less": "Näytä vähemmän",
|
||||
"status.show_less_all": "Näytä kaikista vähemmän",
|
||||
"status.show_more": "Näytä lisää",
|
||||
"status.show_more": "Näytä enemmän",
|
||||
"status.show_more_all": "Näytä kaikista enemmän",
|
||||
"status.show_original": "Näytä alkuperäinen",
|
||||
"status.title.with_attachments": "{user} liitti {attachmentCount, plural, one {{attachmentCount} tiedoston} other {{attachmentCount} tiedostoa}}",
|
||||
"status.translate": "Käännä",
|
||||
"status.translated_from_with": "Käännetty kielestä {lang} käyttäen {provider}",
|
||||
"status.translated_from_with": "Käännetty kielestä {lang} käyttäen palvelua {provider}",
|
||||
"status.uncached_media_warning": "Esikatselu ei ole käytettävissä",
|
||||
"status.unmute_conversation": "Poista keskustelun mykistys",
|
||||
"status.unmute_conversation": "Kumoa keskustelun mykistys",
|
||||
"status.unpin": "Irrota profiilista",
|
||||
"subscribed_languages.lead": "Vain valituilla kielillä kirjoitetut julkaisut näkyvät koti- ja lista-aikajanoillasi muutoksen jälkeen. Älä valitse mitään, jos haluat nähdä julkaisuja kaikilla kielillä.",
|
||||
"subscribed_languages.save": "Tallenna muutokset",
|
||||
@@ -696,9 +703,9 @@
|
||||
"time_remaining.days": "{number, plural, one {# päivä} other {# päivää}} jäljellä",
|
||||
"time_remaining.hours": "{number, plural, one {# tunti} other {# tuntia}} jäljellä",
|
||||
"time_remaining.minutes": "{number, plural, one {# minuutti} other {# minuuttia}} jäljellä",
|
||||
"time_remaining.moments": "Hetki jäljellä",
|
||||
"time_remaining.moments": "Hetkiä jäljellä",
|
||||
"time_remaining.seconds": "{number, plural, one {# sekunti} other {# sekuntia}} jäljellä",
|
||||
"timeline_hint.remote_resource_not_displayed": "{resource} muilta palvelimilta ei näytetä.",
|
||||
"timeline_hint.remote_resource_not_displayed": "Muiden palvelinten {resource}-tietoa ei näytetä täällä.",
|
||||
"timeline_hint.resources.followers": "Seuraajat",
|
||||
"timeline_hint.resources.follows": "seurattua",
|
||||
"timeline_hint.resources.statuses": "Vanhemmat julkaisut",
|
||||
@@ -711,23 +718,23 @@
|
||||
"upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
|
||||
"upload_button.label": "Lisää kuvia, video tai äänitiedosto",
|
||||
"upload_error.limit": "Tiedostolatauksien rajoitus ylitetty.",
|
||||
"upload_error.poll": "Tiedoston lataaminen ei ole sallittua äänestyksissä.",
|
||||
"upload_error.poll": "Tiedostojen lisääminen ei ole sallittua kyselyjen ohessa.",
|
||||
"upload_form.audio_description": "Kuvaile sisältöä kuuroille ja kuulorajoitteisille",
|
||||
"upload_form.description": "Kuvaile sisältöä sokeille ja näkörajoitteisille",
|
||||
"upload_form.edit": "Muokkaa",
|
||||
"upload_form.thumbnail": "Vaihda pikkukuva",
|
||||
"upload_form.thumbnail": "Vaihda pienoiskuva",
|
||||
"upload_form.video_description": "Kuvaile sisältöä kuuroille, kuulorajoitteisille, sokeille tai näkörajoitteisille",
|
||||
"upload_modal.analyzing_picture": "Analysoidaan kuvaa…",
|
||||
"upload_modal.apply": "Käytä",
|
||||
"upload_modal.applying": "Asetetaan…",
|
||||
"upload_modal.applying": "Otetaan käyttöön…",
|
||||
"upload_modal.choose_image": "Valitse kuva",
|
||||
"upload_modal.description_placeholder": "Nopea ruskea kettu hyppää laiskan koiran yli",
|
||||
"upload_modal.detect_text": "Tunnista teksti kuvasta",
|
||||
"upload_modal.edit_media": "Muokkaa mediaa",
|
||||
"upload_modal.hint": "Klikkaa tai vedä ympyrä esikatselussa valitaksesi keskipiste, joka näkyy aina pienoiskuvissa.",
|
||||
"upload_modal.hint": "Napsauta tai vedä ympyrä esikatselussa valitaksesi keskipiste, joka näkyy aina pienoiskuvissa.",
|
||||
"upload_modal.preparing_ocr": "Valmistellaan tekstintunnistusta…",
|
||||
"upload_modal.preview_label": "Esikatselu ({ratio})",
|
||||
"upload_progress.label": "Ladataan...",
|
||||
"upload_progress.label": "Tallennetaan...",
|
||||
"upload_progress.processing": "Käsitellään…",
|
||||
"username.taken": "Käyttäjänimi on jo varattu. Kokeile toista",
|
||||
"video.close": "Sulje video",
|
||||
@@ -737,7 +744,7 @@
|
||||
"video.fullscreen": "Koko näyttö",
|
||||
"video.hide": "Piilota video",
|
||||
"video.mute": "Mykistä ääni",
|
||||
"video.pause": "Keskeytä",
|
||||
"video.pause": "Tauko",
|
||||
"video.play": "Toista",
|
||||
"video.unmute": "Palauta ääni"
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"account.featured_tags.last_status_never": "Walang mga post",
|
||||
"account.featured_tags.title": "Nakatampok na hashtag ni {name}",
|
||||
"account.follow": "Sundan",
|
||||
"account.follow_back": "Sundan pabalik",
|
||||
"account.followers": "Mga tagasunod",
|
||||
"account.followers.empty": "Wala pang sumusunod sa tagagamit na ito.",
|
||||
"account.following": "Sinusundan",
|
||||
@@ -41,6 +42,14 @@
|
||||
"account.media": "Medya",
|
||||
"account.mention": "Banggitin si @{name}",
|
||||
"account.moved_to": "Ipinahihiwatig ni {name} na ang kanilang bagong account ngayon ay:",
|
||||
"account.open_original_page": "Buksan ang pinagmulang pahina",
|
||||
"account.report": "I-ulat si/ang @{name}",
|
||||
"account.requested_follow": "Hinihiling ni {name} na sundan ka",
|
||||
"account.show_reblogs": "Ipakita ang mga pagpapalakas mula sa/kay {name}",
|
||||
"account.unendorse": "Huwag itampok sa profile",
|
||||
"admin.dashboard.retention.cohort_size": "Mga bagong tagagamit",
|
||||
"alert.rate_limited.message": "Mangyaring subukan muli pagkatapos ng {retry_time, time, medium}.",
|
||||
"audio.hide": "Itago ang tunog",
|
||||
"bundle_column_error.error.title": "Naku!",
|
||||
"bundle_column_error.network.body": "Nagkaroon ng kamalian habang sinusubukang i-karga ang pahinang ito. Maaaring dahil ito sa pansamantalang problema ng iyong koneksyon sa internet o ang server na ito.",
|
||||
"bundle_column_error.network.title": "Kamaliang network",
|
||||
@@ -91,6 +100,24 @@
|
||||
"compose_form.direct_message_warning_learn_more": "Matuto pa",
|
||||
"compose_form.encryption_warning": "Ang mga post sa Mastodon ay hindi naka-encrypt nang dulo-dulo. Huwag magbahagi ng anumang sensitibong impormasyon sa Mastodon.",
|
||||
"compose_form.hashtag_warning": "Hindi maililista ang post na ito sa anumang hashtag dahil hindi ito nakapubliko. Mga nakapublikong post lamang ang mahahanap ayon sa hashtag.",
|
||||
"compose_form.placeholder": "Anong nangyari?",
|
||||
"compose_form.poll.multiple": "Maraming pagpipilian",
|
||||
"compose_form.poll.single": "Piliin ang isa",
|
||||
"compose_form.reply": "Tumugon",
|
||||
"compose_form.spoiler.unmarked": "Idagdag ang babala sa nilalaman",
|
||||
"confirmation_modal.cancel": "Pagpaliban",
|
||||
"confirmations.block.block_and_report": "Harangan at i-ulat",
|
||||
"confirmations.block.confirm": "Harangan",
|
||||
"confirmations.block.message": "Sigurado ka bang gusto mong harangan si {name}?",
|
||||
"confirmations.cancel_follow_request.confirm": "Bawiin ang kahilingan",
|
||||
"confirmations.cancel_follow_request.message": "Sigurdo ka bang gusto mong bawiin ang kahilingang sundan si/ang {name}?",
|
||||
"confirmations.delete.message": "Sigurado ka bang gusto mong burahin ang post na ito?",
|
||||
"confirmations.delete_list.confirm": "Tanggalin",
|
||||
"confirmations.delete_list.message": "Sigurado ka bang gusto mong burahin ang listahang ito?",
|
||||
"confirmations.discard_edit_media.confirm": "Ipagpaliban",
|
||||
"confirmations.domain_block.confirm": "Harangan ang buong domain",
|
||||
"confirmations.edit.confirm": "Baguhin",
|
||||
"confirmations.reply.confirm": "Tumugon",
|
||||
"copy_icon_button.copied": "Sinipi sa clipboard",
|
||||
"copypaste.copied": "Sinipi",
|
||||
"copypaste.copy_to_clipboard": "I-sipi sa clipboard",
|
||||
@@ -140,5 +167,138 @@
|
||||
"empty_column.hashtag": "Wala pang laman ang hashtag na ito.",
|
||||
"empty_column.home": "Walang laman ang timeline ng tahanan mo! Sumunod sa marami pang tao para mapunan ito.",
|
||||
"empty_column.list": "Wala pang laman ang listahang ito. Kapag naglathala ng mga bagong post ang mga miyembro ng listahang ito, makikita iyon dito.",
|
||||
"empty_column.lists": "Wala ka pang mga listahan. Kapag gumawa ka ng isa, makikita yun dito."
|
||||
"empty_column.lists": "Wala ka pang mga listahan. Kapag gumawa ka ng isa, makikita yun dito.",
|
||||
"explore.search_results": "Mga resulta ng paghahanap",
|
||||
"firehose.all": "Lahat",
|
||||
"firehose.local": "Itong serbiro",
|
||||
"firehose.remote": "Ibang mga serbiro",
|
||||
"follow_request.authorize": "Tanggapin",
|
||||
"follow_request.reject": "Tanggihan",
|
||||
"follow_suggestions.dismiss": "Huwag nang ipakita muli",
|
||||
"follow_suggestions.view_all": "Tingnan lahat",
|
||||
"follow_suggestions.who_to_follow": "Sinong maaaring sundan",
|
||||
"footer.about": "Tungkol dito",
|
||||
"footer.get_app": "Kunin ang app",
|
||||
"generic.saved": "Nakaimbak",
|
||||
"hashtag.column_header.tag_mode.all": "at {additional}",
|
||||
"hashtag.column_header.tag_mode.any": "o {additional}",
|
||||
"home.pending_critical_update.body": "Mangyaring i-update ang iyong serbiro ng Mastodon sa lalong madaling panahon!",
|
||||
"interaction_modal.login.action": "Iuwi mo ako",
|
||||
"interaction_modal.no_account_yet": "Wala sa Mastodon?",
|
||||
"interaction_modal.on_another_server": "Sa ibang serbiro",
|
||||
"interaction_modal.on_this_server": "Sa serbirong ito",
|
||||
"interaction_modal.title.follow": "Sundan si {name}",
|
||||
"intervals.full.days": "{number, plural, one {# araw} other {# na araw}}",
|
||||
"intervals.full.hours": "{number, plural, one {# oras} other {# na oras}}",
|
||||
"intervals.full.minutes": "{number, plural, one {# minuto} other {# na minuto}}",
|
||||
"keyboard_shortcuts.description": "Paglalarawan",
|
||||
"keyboard_shortcuts.down": "Ilipat pababa sa talaan",
|
||||
"keyboard_shortcuts.mention": "Banggitin ang may-akda",
|
||||
"keyboard_shortcuts.requests": "Buksan ang talaan ng mga kahilingan sa pagsunod",
|
||||
"keyboard_shortcuts.up": "Ilipat pataas sa talaan",
|
||||
"lightbox.close": "Isara",
|
||||
"lightbox.next": "Susunod",
|
||||
"lightbox.previous": "Nakaraan",
|
||||
"link_preview.author": "Ni/ng {name}",
|
||||
"lists.account.add": "Idagdag sa talaan",
|
||||
"lists.account.remove": "Tanggalin mula sa talaan",
|
||||
"lists.new.create": "Idagdag sa talaan",
|
||||
"lists.new.title_placeholder": "Bagong pangalan ng talaan",
|
||||
"lists.replies_policy.title": "Ipakita ang mga tugon sa:",
|
||||
"lists.subheading": "Iyong mga talaan",
|
||||
"loading_indicator.label": "Kumakarga…",
|
||||
"navigation_bar.about": "Tungkol dito",
|
||||
"navigation_bar.blocks": "Nakaharang na mga tagagamit",
|
||||
"navigation_bar.direct": "Mga palihim na banggit",
|
||||
"navigation_bar.favourites": "Mga paborito",
|
||||
"navigation_bar.follows_and_followers": "Mga sinusundan at tagasunod",
|
||||
"navigation_bar.lists": "Mga listahan",
|
||||
"navigation_bar.search": "Maghanap",
|
||||
"notification.admin.report": "Iniulat ni {name} si {target}",
|
||||
"notification.follow": "Sinundan ka ni {name}",
|
||||
"notification.follow_request": "Hinihiling ni {name} na sundan ka",
|
||||
"notification.mention": "Binanggit ka ni {name}",
|
||||
"notifications.clear": "Burahin mga abiso",
|
||||
"notifications.column_settings.admin.report": "Mga bagong ulat:",
|
||||
"notifications.column_settings.favourite": "Mga paborito:",
|
||||
"notifications.column_settings.follow": "Mga bagong tagasunod:",
|
||||
"notifications.column_settings.unread_notifications.category": "Hindi Nabasang mga Abiso",
|
||||
"notifications.column_settings.update": "Mga pagbago:",
|
||||
"notifications.filter.all": "Lahat",
|
||||
"notifications.mark_as_read": "Markahan lahat ng abiso bilang nabasa na",
|
||||
"onboarding.action.back": "Ibalik mo ako",
|
||||
"onboarding.actions.back": "Ibalik mo ako",
|
||||
"onboarding.profile.note_hint": "Maaari mong @bangitin ang ibang mga tao o mga #hashtag…",
|
||||
"onboarding.profile.save_and_continue": "Iimbak at magpatuloy",
|
||||
"onboarding.share.next_steps": "Mga posibleng susunod na hakbang:",
|
||||
"poll.closed": "Sarado",
|
||||
"poll.reveal": "Ipakita ang mga resulta",
|
||||
"poll.voted": "Binoto mo para sa sagot na ito",
|
||||
"poll_button.remove_poll": "Tanggalin ang boto",
|
||||
"privacy.direct.long": "Lahat ng mga binanggit sa post",
|
||||
"privacy.private.long": "Mga tagasunod mo lamang",
|
||||
"privacy.private.short": "Mga tagasunod",
|
||||
"relative_time.days": "{number}a",
|
||||
"relative_time.full.days": "{number, plural, one {# araw} other {# na araw}} ang nakalipas",
|
||||
"relative_time.full.hours": "{number, plural, one {# oras} other {# na oras}} ang nakalipas",
|
||||
"relative_time.full.just_now": "ngayon lang",
|
||||
"relative_time.full.minutes": "{number, plural, one {# minuto} other {# na minuto}} ang nakalipas",
|
||||
"relative_time.full.seconds": "{number, plural, one {# segundo} other {# na segundo}} ang nakalipas",
|
||||
"relative_time.hours": "{number}o",
|
||||
"relative_time.just_now": "ngayon",
|
||||
"relative_time.minutes": "{number}m",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"reply_indicator.cancel": "Ipagpaliban",
|
||||
"report.block": "Harangan",
|
||||
"report.categories.other": "Iba pa",
|
||||
"report.category.title": "Sabihin mo sa amin kung anong nangyari sa {type} na ito",
|
||||
"report.close": "Tapos na",
|
||||
"report.next": "Sunod",
|
||||
"report.reasons.violation": "Lumalabag ito sa mga panuntunan ng serbiro",
|
||||
"report.reasons.violation_description": "Alam mo na lumalabag ito sa mga partikular na panuntunan",
|
||||
"report.rules.title": "Aling mga patakaran ang nilabag?",
|
||||
"report.submit": "Isumite",
|
||||
"report.target": "Iniulat si/ang {target}",
|
||||
"report.thanks.take_action_actionable": "Habang sinusuri namin ito, maaari kang gumawa ng aksyon laban kay/sa {name}:",
|
||||
"report.thanks.title": "Ayaw mo bang makita ito?",
|
||||
"report.thanks.title_actionable": "Salamat sa pag-uulat, titingnan namin ito.",
|
||||
"report_notification.categories.other": "Iba pa",
|
||||
"search_results.all": "Lahat",
|
||||
"search_results.see_all": "Ipakita lahat",
|
||||
"server_banner.learn_more": "Matuto nang higit pa",
|
||||
"server_banner.server_stats": "Katayuan ng serbiro:",
|
||||
"status.block": "Harangan si @{name}",
|
||||
"status.delete": "Tanggalin",
|
||||
"status.direct": "Palihim na banggitin si/ang @{name}",
|
||||
"status.direct_indicator": "Palihim na banggit",
|
||||
"status.edit": "Baguhin",
|
||||
"status.edited": "Binago noong {date}",
|
||||
"status.edited_x_times": "Binago {count, plural, one {{count} beses} other {{count} na beses}}",
|
||||
"status.history.created": "Nilikha ni/ng {name} {date}",
|
||||
"status.history.edited": "Binago ni/ng {name} {date}",
|
||||
"status.media.open": "Pindutin upang buksan",
|
||||
"status.media.show": "Pindutin upang ipakita",
|
||||
"status.mention": "Banggitin ang/si @{name}",
|
||||
"status.more": "Higit pa",
|
||||
"status.read_more": "Basahin ang higit pa",
|
||||
"status.reblogs.empty": "Wala pang nagpalakas ng post na ito. Kung may sinumang nagpalakas, makikita sila rito.",
|
||||
"status.reply": "Tumugon",
|
||||
"status.report": "I-ulat si/ang @{name}",
|
||||
"status.sensitive_warning": "Sensitibong nilalaman",
|
||||
"status.share": "Ibahagi",
|
||||
"status.show_less": "Magpakita ng mas kaunti",
|
||||
"status.show_less_all": "Magpakita ng mas kaunti para sa lahat",
|
||||
"status.show_more": "Magpakita ng higit pa",
|
||||
"status.show_more_all": "Magpakita ng higit pa para sa lahat",
|
||||
"status.translate": "Isalin",
|
||||
"status.translated_from_with": "Isalin mula sa {lang} gamit ang {provider}",
|
||||
"status.uncached_media_warning": "Hindi makuha ang paunang tigin",
|
||||
"tabs_bar.notifications": "Mga abiso",
|
||||
"time_remaining.days": "{number, plural, one {# araw} other {# na araw}} ang natitira",
|
||||
"time_remaining.hours": "{number, plural, one {# oras} other {# na oras}} ang natitira",
|
||||
"time_remaining.minutes": "{number, plural, one {# minuto} other {# na minuto}} ang natitira",
|
||||
"time_remaining.seconds": "{number, plural, one {# segundo} other {# na segundo}} ang natitira",
|
||||
"timeline_hint.remote_resource_not_displayed": "Hindi ipinapakita ang {resource} mula sa ibang mga serbiro.",
|
||||
"timeline_hint.resources.followers": "Mga tagasunod",
|
||||
"timeline_hint.resources.follows": "Mga sinusundan"
|
||||
}
|
||||
|
||||
@@ -145,11 +145,9 @@
|
||||
"compose_form.lock_disclaimer": "Kontoin hjá tær er ikki {locked}. Øll kunnu fylgja tær og lesa tað, tú bert letur fyljgarar lesa.",
|
||||
"compose_form.lock_disclaimer.lock": "læst",
|
||||
"compose_form.placeholder": "Hvat hevur tú í huga?",
|
||||
"compose_form.poll.add_option": "Legg valmøguleika afturat",
|
||||
"compose_form.poll.duration": "Atkvøðugreiðslutíð",
|
||||
"compose_form.poll.multiple": "Fleiri valmøguleikar",
|
||||
"compose_form.poll.option_placeholder": "Valmøguleiki {number}",
|
||||
"compose_form.poll.remove_option": "Strika hendan valmøguleikan",
|
||||
"compose_form.poll.single": "Vel ein",
|
||||
"compose_form.poll.switch_to_multiple": "Broyt atkvøðugreiðslu til at loyva fleiri svarum",
|
||||
"compose_form.poll.switch_to_single": "Broyt atkvøðugreiðslu til einstakt svar",
|
||||
@@ -279,6 +277,17 @@
|
||||
"follow_request.authorize": "Veit myndugleika",
|
||||
"follow_request.reject": "Nokta",
|
||||
"follow_requests.unlocked_explanation": "Sjálvt um konta tín ikki er læst, so hugsa {domain} starvsfólkini, at tú kanska hevur hug at kanna umbønir um at fylgja frá hesum kontum við hond.",
|
||||
"follow_suggestions.curated_suggestion": "Val hjá ábyrgdarfólki",
|
||||
"follow_suggestions.dismiss": "Lat vera við at vísa",
|
||||
"follow_suggestions.hints.featured": "Hesin vangin er úrvaldur av toyminum handan {domain}.",
|
||||
"follow_suggestions.hints.friends_of_friends": "Hesin vangin er vælumtóktur millum tey, tú fylgir.",
|
||||
"follow_suggestions.hints.most_followed": "Hesin vangin er ein av teimum, sum er mest fylgdur á {domain}.",
|
||||
"follow_suggestions.hints.most_interactions": "Nýliga hava nógv lagt merki til hendan vangan á {domain}.",
|
||||
"follow_suggestions.hints.similar_to_recently_followed": "Hesin vangin líkist teimum, sum tú nýliga hevur fylgt.",
|
||||
"follow_suggestions.personalized_suggestion": "Persónligt uppskot",
|
||||
"follow_suggestions.popular_suggestion": "Vælumtókt uppskot",
|
||||
"follow_suggestions.view_all": "Vís øll",
|
||||
"follow_suggestions.who_to_follow": "Hvørji tú átti at fylgt",
|
||||
"followed_tags": "Fylgd frámerki",
|
||||
"footer.about": "Um",
|
||||
"footer.directory": "Vangaskrá",
|
||||
@@ -305,13 +314,9 @@
|
||||
"hashtag.follow": "Fylg frámerki",
|
||||
"hashtag.unfollow": "Gevst at fylgja frámerki",
|
||||
"hashtags.and_other": "…og {count, plural, other {# afturat}}",
|
||||
"home.actions.go_to_explore": "Sí rákið",
|
||||
"home.actions.go_to_suggestions": "Finn fólk at fylgja",
|
||||
"home.column_settings.basic": "Grundleggjandi",
|
||||
"home.column_settings.show_reblogs": "Vís lyft",
|
||||
"home.column_settings.show_replies": "Vís svar",
|
||||
"home.explore_prompt.body": "Heimarásin fer at hava eitt bland av postum frá frámerkjunum, sum tú hevur valt at fylgja, brúkarunum, tú hevur valt at fylgja, og postunum, sum tey stimbra. Um tað kennist ov friðarligt, so kanst tú:",
|
||||
"home.explore_prompt.title": "Hetta er tín heimastøð í Mastodon.",
|
||||
"home.hide_announcements": "Fjal kunngerðir",
|
||||
"home.pending_critical_update.body": "Vinarliga dagfør Mastodon ambætaran hjá tær so skjótt sum møguligt!",
|
||||
"home.pending_critical_update.link": "Sí dagføringar",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user