Compare commits

...

75 Commits

Author SHA1 Message Date
David Yip
083f78b8fb Stub out Glitch::ApplyKeywordMutesService. #199.
This service will apply/unapply keyword mutes to home and mentions
timelines.  Maybe other timelines if I find a way to make it work.
2018-06-13 03:32:30 -05:00
David Yip
f1bfcb50f0 Merge pull request #531 from glitch-soc/454-allow-keyword-mutes-to-skip-mentions
Allow keyword mutes to skip mentions (#454)
2018-06-12 19:28:08 -05:00
David Yip
5cff053944 Merge branch 'master' into 454-allow-keyword-mutes-to-skip-mentions 2018-06-12 18:13:30 -05:00
David Yip
f6bb50b6ec Merge pull request #539 from glitch-soc/merge-upstream
Merge upstream
2018-06-12 18:12:29 -05:00
David Yip
99b2bc2668 keyword mute: Add missing scope for regex escape test 2018-06-12 17:48:38 -05:00
David Yip
fac6e392e9 Port emojimart 2.6.1 changes to glitch flavour
See also the following commits:

- 0c3ce41031
- 268d90e810
2018-06-12 17:43:50 -05:00
David Yip
908a770d2b keyword mute: use mentions scope in home feed filtering (#454)
If a status shows up in mentions because all keyword mutes that might
apply to it are marked as "don't apply to mentions", then it ought to
show up in the home feed also.
2018-06-12 17:14:35 -05:00
David Yip
e931cf656d Merge remote-tracking branch 'glitchsoc/master' into 454-allow-keyword-mutes-to-skip-mentions
Conflicts:
 	app/models/glitch/keyword_mute.rb
2018-06-12 16:39:30 -05:00
Jenkins
4d8d1fa129 Merge remote-tracking branch 'tootsuite/master' into glitchsoc/master 2018-06-12 13:17:21 +00:00
Shuhei Kitagawa
6151308c47 Add missing tests for admin/accounts_controller (#7791) 2018-06-12 21:24:46 +09:00
Eugen Rochko
0979d4275a Bump version to 2.4.1 2018-06-10 17:20:56 +02:00
Lynx Kotoura
7e27a3c225 Uniform media and video spoiler settings and fix them of the light theme (#7778) 2018-06-10 16:54:22 +02:00
Yamagishi Kazutoshi
01ee460ceb Weblate translations (2018-06-10) (#7779)
* Translated using Weblate (Galician)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/

* Translated using Weblate (Occitan)

Currently translated at 98.0% (609 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/oc/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/

* Translated using Weblate (Japanese)

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/

* Translated using Weblate (Japanese)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/

* Translated using Weblate (Catalan)

Currently translated at 99.8% (620 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/

* Translated using Weblate (Persian)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fa/

* Translated using Weblate (Galician)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (303 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (French)

Currently translated at 99.6% (303 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Slovak)

Currently translated at 95.4% (593 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/

* Translated using Weblate (Persian)

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fa/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (620 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/

* Translated using Weblate (Greek)

Currently translated at 66.3% (412 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/el/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Korean)

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ko/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Slovak)

Currently translated at 95.9% (596 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/

* yarn manage:translations && i18n-tasks normalize && i18n-tasks remove-unused
2018-06-10 16:53:49 +02:00
kedama
a99179d31f Control the focus when clicking the "CW" button. (#7776)
* Focus to the spoiler text when CW turns on.
* Focus back to the textarea when CW turns off.
2018-06-10 16:13:30 +02:00
Renato "Lond" Cerqueira
268d90e810 Rename emoji sheet to avoid caching issue (#7777) 2018-06-10 16:12:47 +02:00
Eugen Rochko
35ae960122 Bump version to 2.4.1rc4 2018-06-10 00:39:56 +02:00
nightpool
6310dd233a Migration to cleanup blocked users that are still following (#7773)
* Migration to cleanup blocked users that are still following

* use follow directly, commit schema
2018-06-10 00:38:17 +02:00
Shuhei Kitagawa
7086aa598b Add tests for intents_controller (#7763) 2018-06-09 22:47:50 +02:00
Eugen Rochko
10f51c9886 Fix domain hiding logic (#7765)
* Send rejections to followers when user hides domain they're on

* Use account domain blocks for "authorized followers" action

Replace soft-blocking (block & unblock) behaviour with follow rejection

* Split sync and async work of account domain blocking

Do not create domain block when removing followers by domain, that
is probably unexpected from the user's perspective.

* Adjust confirmation message for domain block

* yarn manage:translations
2018-06-09 22:46:54 +02:00
Lynx Kotoura
91e5d9f8af Fix background color of emoji-mart-bar in light theme (#7768)
* Fix background color of emoji-mart-bar

* Uniform emoji-mart-search background color in light theme as default
2018-06-09 22:21:37 +02:00
Lynx Kotoura
3df8c40508 Adjust emoji-mart-anchor-bar for environments that use display scaling (#7772) 2018-06-09 22:20:57 +02:00
Eugen Rochko
17dc07f667 Fix has_one association on Web::PushSubscription (#7767)
* Fix has_one association on Web::PushSubscription

* Fix code style issues
2018-06-09 21:11:14 +02:00
Eugen Rochko
a043f8d277 Ensure emoji-mart dependency is updated (#7771)
Regression from 85470ec since version string was not updated
2018-06-09 21:10:53 +02:00
David Yip
34f1fd2a62 Merge pull request #538 from ThibG/glitch-soc/fixes/obsolote-constants
Delete references to removed constants (fixes #537)
2018-06-09 11:42:56 -05:00
Thibaut Girka
7d3c0e4cb4 Delete references to removed constants (fixes #537) 2018-06-09 18:14:23 +02:00
David Yip
f9eb4ea80a Merge pull request #506 from ThibG/glitch-soc/fixes/static-500
Hardcode default skin/theme in error layout (fixes #373)
2018-06-09 10:39:55 -05:00
SerCom_KC
fc132915ec Update Chinese (Simplified) translations (#7769)
* i18n: (zh-CN) #7718

* i18n: (zh-CN) #7735

* i18n: (zh-CN) #7676
2018-06-09 17:07:23 +02:00
Eugen Rochko
18e1de6a16 Migrate old web push subscriptions to ensure deliveries (#7764) 2018-06-09 13:33:04 +02:00
Renato "Lond" Cerqueira
85470ec872 Fix issues with updated emoji mart (#7761)
* Changes behavior from search light to keep custom search
The new version of emoji-mart needs the search function to constantly
receive the custom emoji array. This changes the behavior back to the
previous one in the search light method to keep the emoji autocomplete
as before

* Change test order
The order was breaking the tests

* Fix codeclimate issues

* Update to emoji mart to version without issue in picker

Fixes #7760
2018-06-08 13:28:04 +02:00
David Yip
a9515f3186 Merge pull request #535 from glitch-soc/merge-upstream
Merge upstream
2018-06-08 00:33:09 -05:00
Yamagishi Kazutoshi
6671297e7a Weblate translations (2018-06-08) (#7759)
* Translated using Weblate (Galician)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/nl/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/nl/

* Translated using Weblate (Occitan)

Currently translated at 98.0% (609 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/oc/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/

* Translated using Weblate (Japanese)

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ja/

* Translated using Weblate (Japanese)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ja/

* Translated using Weblate (Catalan)

Currently translated at 99.8% (620 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/ca/

* Translated using Weblate (Catalan)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/ca/

* Translated using Weblate (Persian)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fa/

* Translated using Weblate (Galician)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/gl/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (303 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (French)

Currently translated at 99.6% (303 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/fr/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Slovak)

Currently translated at 95.4% (593 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/

* Translated using Weblate (Persian)

Currently translated at 99.6% (619 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/fa/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/pt_BR/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (620 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/pt_BR/

* Translated using Weblate (Greek)

Currently translated at 66.3% (412 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/el/

* Translated using Weblate (Slovak)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (304 of 304 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* yarn manage:translations && i18n-tasks normalize && i18n-tasks remove-unused
2018-06-08 04:50:52 +02:00
Eugen Rochko
6ba7d9d0d9 Do not accept ActivityPub follow requests from blocked user (#7756)
* Do not accept ActivityPub follow requests from blocked user

Fix #7745

* Deliver auto-rejection immediately when follow-requested by blocked account

* Fix trailing whitespace
2018-06-08 00:14:06 +02:00
Eugen Rochko
9b9e96eae5 Add "Edit profile" link to public profile page, increase bottom padding (#7754) 2018-06-07 22:40:55 +02:00
Renato "Lond" Cerqueira
0c3ce41031 Update to emojimart 2.6.1 (#7746)
* Update to emojimart 2.6.1
WIP using local updated version. Sheet comes from emoji-data@4.0.4,
file sheet_twitter_32_indexed_256.png.

* Update to 2.6.1 and uncompress data if needed

* Remove changes that were not needed

* Fix yarn lock file

* Match emojiToShowFilter behavior to new version of emoji-mart

* Fix codeclimate issue

* Match custom emoji behavior to new version of emoji-mart

* Replace emoji without shortcode in tests

* Fix code climate issues
2018-06-07 19:40:23 +02:00
David Yip
8142bd2553 Merge remote-tracking branch 'tootsuite/master' into merge-upstream
Conflicts:
 	app/models/status.rb

The conflict in the Status model was due to
5bf5003384.
It was resolved by accepting tootsuite's changes.
2018-06-07 05:13:49 -05:00
David Yip
f8d50a4070 Merge pull request #509 from ThibG/glitch-soc/fixes/router-history-navigation
Use history.state to decide whether we should goBack() or go to / (fixes #247)
2018-06-06 23:56:48 -05:00
Marcin Mikołajczak
2304d52599 🌍🇵🇱 (#7753)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2018-06-07 13:37:43 +09:00
Eugen Rochko
158cd7ee74 Bump version to 2.4.1rc3 2018-06-06 21:27:06 +02:00
Eugen Rochko
59b42188a7 Filter out blocked/muted people from profile timelines (#7747)
Fix #7741
2018-06-06 21:13:30 +02:00
Yamagishi Kazutoshi
683707839f Fix fetch of remote image with multiple Content-Type headers (#7749) 2018-06-06 20:50:07 +02:00
Eugen Rochko
c75493755f Preserve newlines in delete & redraft and desktop notifications (#7750)
Fix #7748
2018-06-06 20:49:53 +02:00
Yamagishi Kazutoshi
b7b331ad0d Add missing dot for remote image (#7751) 2018-06-06 20:49:39 +02:00
David Yip
68373e799b Merge pull request #534 from glitch-soc/restructure-kw-as-word-lists
Escape metacharacters in non-whole-word keyword mutes (#463, #533)
2018-06-05 21:38:04 -05:00
Shuhei Kitagawa
12fa2500c4 Add missing tests for sessions controller (#7744) 2018-06-06 10:23:22 +09:00
Renato "Lond" Cerqueira
d8b4f39007 Weblate translations 20180605 (#7743)
* Translated using Weblate (Basque)

Currently translated at 100.0% (66 of 66 strings)

Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (76 of 76 strings)

Translation: Mastodon/Doorkeeper
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/doorkeeper/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (66 of 66 strings)

Translation: Mastodon/Preferences
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/simple_form/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (303 of 303 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Translated using Weblate (Basque)

Currently translated at 100.0% (621 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/eu/

* Translated using Weblate (Slovak)

Currently translated at 95.4% (593 of 621 strings)

Translation: Mastodon/Backend
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/backend/sk/

* Translated using Weblate (Basque)

Currently translated at 100.0% (303 of 303 strings)

Translation: Mastodon/React
Translate-URL: https://weblate.joinmastodon.org/projects/mastodon/frontend/eu/

* Normalize translations
ran yarn build:development && i18n-tasks normalize && yarn
manage:translations && i18n-tasks remove-unused
2018-06-05 20:28:29 +02:00
Renato "Lond" Cerqueira
aa177bdca7 Add missing locale strings (#7742)
ran yarn build:development && i18n-tasks normalize && yarn
    manage:translations && i18n-tasks remove-unused
2018-06-06 03:11:03 +09:00
Eugen Rochko
fab65fb7e5 Bump version to 2.4.1rc2 2018-06-05 11:53:30 +00:00
Eugen Rochko
bd0791d800 Add redraft function (#7735)
* Add redraft function

Fix #7010

* Add explicit confirmation

* Add explicit confirmation message
2018-06-05 00:17:38 +02:00
David Yip
f009fef40b Merge pull request #530 from glitch-soc/restructure-kw-as-word-lists
keyword mute: Store keywords in a list, not a regex
2018-06-04 15:58:23 -05:00
nightpool
5fb013878f Fix context performance by partially reverting #7083 (#7734)
* Fix context performance by partially reverting #7083

* Fix code style issue

* fix off-by-1 error in thread limits

* code style fix
2018-06-04 22:20:12 +02:00
Yamagishi Kazutoshi
dc73241bd9 Detect extname from Content-Type (#7733) 2018-06-04 18:58:36 +02:00
Chikahiro Tokoro
1637d24af4 fix RuboCop error (#7442)
* fix RuboCop error

RuboCop doesn't work by following error.

```
$ rubocop
Error: The `Style/TrailingCommaInLiteral` cop no longer exists. Please use `Style/TrailingCommaInArrayLiteral` and/or `Style/TrailingCommaInHashLiteral` instead.
(obsolete configuration found in .rubocop.yml, please update it)
```

it comes from RuboCop 0.53.0 [\[Fix #3394\] Separate Array & Hash Literal Comma configuration by garettarrowood · Pull Request #5307 · bbatsov/rubocop](https://github.com/bbatsov/rubocop/pull/5307)

* ci(CodeClimate): specify RuboCop version 0.54

 * https://docs.codeclimate.com/docs/rubocop#section-using-rubocop-s-newer-versions
 * [RuboCop 0.55.0 is not available yet](https://github.com/codeclimate/codeclimate-rubocop/issues/121) on CodeClimate rubocop channel
2018-06-04 14:49:10 +02:00
Yamagishi Kazutoshi
e3fb528d12 Skip processing when HEAD method returns 501 (#7730) 2018-06-04 13:42:53 +02:00
Yamagishi Kazutoshi
e0354aba7c Add vendor prefix for background-clip (#7727) 2018-06-04 13:24:20 +02:00
Lynx Kotoura
bb0edbd988 Change border color of activity-stream (#7724) 2018-06-04 13:13:31 +02:00
Yamagishi Kazutoshi
64d7a63f18 Submit report using meta key (#7729) 2018-06-04 13:09:52 +02:00
Yamagishi Kazutoshi
c0fc4e9935 Remove unnecessary underline on accounts table (#7728) 2018-06-04 13:09:36 +02:00
David Yip
97d2df77aa Add apply-to-mentions option to keyword mute UI. #454. 2018-06-04 02:51:28 -05:00
David Yip
cf28049f0a Add a FeedManager example demonstrating non-mention keywords. #454. 2018-06-03 23:04:00 -05:00
David Yip
a40e322f4b Fix spacing in some FeedManager examples. 2018-06-03 23:02:01 -05:00
David Yip
26573ad7e6 Thread scopes through #matches?. #454.
Also add an apply_to_mentions attribute on Glitch::KeywordMute, which is
used to calculate scope.  Next up: additions to the test suite to
demonstrate how scoping works.
2018-06-03 23:00:50 -05:00
Eugen Rochko
1bbe81030c Display numbers in account header using shortNumberFormat for consistency (#7723) 2018-06-04 05:15:50 +02:00
Akihiko Odaki
5bf5003384 Do not mark remote status sensitive even if spoiler text is present (#7395)
Old statuses and statuses from Pawoo, which runs a modified version of
Mastodon, may not have been marked sensitive even if spoiler text is
present.

Such statuses are still not marked sensitve if they are local or
arrived before version upgrade. Marking recently fetched remote status
sensitive contradicts the behavior.

Considering what people expected when they authored such statuses, this
change removes the sensitivity enforcement.
2018-06-04 04:46:14 +02:00
Lynx Kotoura
73923ea6c4 Fix activity-stream-tabs colors and set text variables for text colors (#7722) 2018-06-04 04:39:42 +02:00
Eugen Rochko
c7405fda11 Fix missing column in select in mastodon:feeds:build task (#7720) 2018-06-04 04:21:15 +02:00
Eugen Rochko
e18390cfe6 Fix bug in order of conversations in web UI (#7721) 2018-06-04 04:19:16 +02:00
Shuhei Kitagawa
22caa32ba2 Add tests for embeds controller (#7719)
* Small refactoring of status_finder_spec

* Add tests for embeds_controller
2018-06-04 10:35:56 +09:00
Eugen Rochko
6b2f4f8c09 "Show" instead of "return to" after (remote)-following (#7718)
Resolve #6326
2018-06-04 03:00:36 +02:00
David Yip
c55263027a Merge remote-tracking branch 'origin/master' into gs-master 2018-06-03 19:44:05 -05:00
Eugen Rochko
0deb9fa6b9 Remove trending hashtags (#7711)
* Delete trends_controller.rb

* Update routes.rb

* Update trending_tags.rb

* Update index.js

* Update index.js

* Update search_results.js

* Update async-components.js

* Update index.js

* Delete trends.js

* Delete trends.js

* Delete trends_container.js

* Delete trends.js

* Update search_results.js

* Update search_results_container.js
2018-06-04 02:18:18 +02:00
David Yip
0f979c3460 Merge pull request #529 from glitch-soc/tweak-491
Note that favourite confirmation applies to Glitch flavour only (#491)
2018-06-03 04:22:20 -05:00
David Yip
d757c8a644 prefs: Note that favourite confirmation applies to Glitch flavour only (#491) 2018-06-03 03:40:27 -05:00
Thibaut Girka
cc396f085d Use history.state to decide whether we should goBack() or go to / (fixes #247)
So far, glitch-soc used history.length to decide whether to call `goBack()` or
go to / in order to not leave the webUI. This made clicking the “Back” button
go to the “Getting started” column instead of going back in the browser's
history when such an action would leave the web UI, but also when:
- The WebUI is refreshed (F5)
- A tab is restored
- The history length reaches its maximum (e.g., 50 in Firefox)

This commit fixes these shortcomings by checking `window.history.state`.
Indeed, we only want to go back in the browser's history when the current
location has been reached from within the WebUI, which only happens via
`pushState` as far as I know. Since browser store the serialized state in
the browser history, this also survives page reload and session restoration.
2018-05-31 14:39:02 +02:00
Thibaut Girka
f86d280fd6 Use props.router instead of context.router, as we are using withRouter 2018-05-31 14:39:02 +02:00
Thibaut Girka
e8a9627f66 Hardcode default skin/theme in error layout (fixes #373)
This is a bit hackish. The best way would simply to somehow
use Mastodon's ApplicationController with `use_pack 'error'` from
the Rake task, but I'm not sure how to do that.
2018-05-31 14:38:48 +02:00
160 changed files with 1481 additions and 718 deletions

View File

@@ -30,6 +30,7 @@ plugins:
channel: eslint-4
rubocop:
enabled: true
channel: rubocop-0-54
scss-lint:
enabled: true
exclude_patterns:

View File

@@ -107,5 +107,8 @@ Style/RegexpLiteral:
Style/SymbolArray:
Enabled: false
Style/TrailingCommaInLiteral:
Style/TrailingCommaInArrayLiteral:
EnforcedStyleForMultiline: 'comma'
Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: 'comma'

View File

@@ -15,7 +15,8 @@ class Api::V1::DomainBlocksController < Api::BaseController
end
def create
BlockDomainFromAccountService.new.call(current_account, domain_block_params[:domain])
current_account.block_domain!(domain_block_params[:domain])
AfterAccountDomainBlockWorker.perform_async(current_account.id, domain_block_params[:domain])
render_empty
end

View File

@@ -1,17 +0,0 @@
# frozen_string_literal: true
class Api::V1::TrendsController < Api::BaseController
before_action :set_tags
respond_to :json
def index
render json: @tags, each_serializer: REST::TagSerializer
end
private
def set_tags
@tags = TrendingTags.get(limit_param(10))
end
end

View File

@@ -1,9 +1,10 @@
# frozen_string_literal: true
class IntentsController < ApplicationController
def show
uri = Addressable::URI.parse(params[:uri])
before_action :check_uri
rescue_from Addressable::URI::InvalidURIError, with: :handle_invalid_uri
def show
if uri.scheme == 'web+mastodon'
case uri.host
when 'follow'
@@ -15,4 +16,18 @@ class IntentsController < ApplicationController
not_found
end
private
def check_uri
not_found if uri.blank?
end
def handle_invalid_uri
not_found
end
def uri
@uri ||= Addressable::URI.parse(params[:uri])
end
end

View File

@@ -11,7 +11,7 @@ class Settings::FollowerDomainsController < Settings::BaseController
def update
domains = bulk_params[:select] || []
SoftBlockDomainFollowersWorker.push_bulk(domains) do |domain|
AfterAccountDomainBlockWorker.push_bulk(domains) do |domain|
[current_account.id, domain]
end

View File

@@ -15,6 +15,7 @@ class Settings::KeywordMutesController < Settings::BaseController
@keyword_mute = keyword_mutes_for_account.create(keyword_mute_params)
if @keyword_mute.persisted?
Glitch::ApplyKeywordMutesWorker.perform_async(current_account.id)
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
else
render :new
@@ -23,6 +24,7 @@ class Settings::KeywordMutesController < Settings::BaseController
def update
if @keyword_mute.update(keyword_mute_params)
Glitch::ApplyKeywordMutesWorker.perform_async(current_account.id)
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
else
render :edit
@@ -32,12 +34,14 @@ class Settings::KeywordMutesController < Settings::BaseController
def destroy
@keyword_mute.destroy!
Glitch::ApplyKeywordMutesWorker.perform_async(current_account.id)
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
end
def destroy_all
keyword_mutes_for_account.delete_all
Glitch::ApplyKeywordMutesWorker.perform_async(current_account.id)
redirect_to settings_keyword_mutes_path, notice: I18n.t('generic.changes_saved_msg')
end
@@ -52,7 +56,7 @@ class Settings::KeywordMutesController < Settings::BaseController
end
def keyword_mute_params
params.require(:keyword_mute).permit(:keyword, :whole_word)
params.require(:keyword_mute).permit(:keyword, :whole_word, :apply_to_mentions)
end
def paginated_keyword_mutes_for_account

View File

@@ -10,10 +10,10 @@ export default class ColumnBackButton extends React.PureComponent {
handleClick = () => {
// if history is exhausted, or we would leave mastodon, just go to root.
if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) {
this.context.router.history.push('/');
} else {
if (window.history.state) {
this.context.router.history.goBack();
} else {
this.context.router.history.push('/');
}
}

View File

@@ -10,10 +10,10 @@ export default class ColumnBackButtonSlim extends React.PureComponent {
handleClick = () => {
// if history is exhausted, or we would leave mastodon, just go to root.
if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) {
this.context.router.history.push('/');
} else {
if (window.history.state) {
this.context.router.history.goBack();
} else {
this.context.router.history.push('/');
}
}

View File

@@ -66,10 +66,10 @@ export default class ColumnHeader extends React.PureComponent {
handleBackClick = () => {
// if history is exhausted, or we would leave mastodon, just go to root.
if (window.history && (window.history.length === 1 || window.history.length === window._mastoInitialHistoryLen)) {
this.context.router.history.push('/');
} else {
if (window.history.state) {
this.context.router.history.goBack();
} else {
this.context.router.history.push('/');
}
}

View File

@@ -107,7 +107,7 @@ const mapDispatchToProps = (dispatch, { onPickEmoji }) => ({
const assetHost = process.env.CDN_HOST || '';
let EmojiPicker, Emoji; // load asynchronously
const backgroundImageFn = () => `${assetHost}/emoji/sheet.png`;
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
const categoriesSort = [

View File

@@ -99,10 +99,6 @@ const keyMap = {
@withRouter
export default class UI extends React.Component {
static contextTypes = {
router: PropTypes.object.isRequired,
};
static propTypes = {
dispatch: PropTypes.func.isRequired,
children: PropTypes.node,
@@ -113,6 +109,7 @@ export default class UI extends React.Component {
isComposing: PropTypes.bool,
hasComposingText: PropTypes.bool,
location: PropTypes.object,
router: PropTypes.object,
intl: PropTypes.object.isRequired,
dropdownMenuIsOpen: PropTypes.bool,
};
@@ -200,7 +197,7 @@ export default class UI extends React.Component {
handleServiceWorkerPostMessage = ({ data }) => {
if (data.type === 'navigate') {
this.context.router.history.push(data.path);
this.props.router.history.push(data.path);
} else {
console.warn('Unknown message type:', data.type);
}
@@ -305,10 +302,11 @@ export default class UI extends React.Component {
}
handleHotkeyBack = () => {
if (window.history && window.history.length === 1) {
this.context.router.history.push('/');
} else {
// if history is exhausted, or we would leave mastodon, just go to root.
if (window.history.state) {
this.context.router.history.goBack();
} else {
this.context.router.history.push('/');
}
}
@@ -318,54 +316,54 @@ export default class UI extends React.Component {
handleHotkeyToggleHelp = () => {
if (this.props.location.pathname === '/keyboard-shortcuts') {
this.context.router.history.goBack();
this.props.router.history.goBack();
} else {
this.context.router.history.push('/keyboard-shortcuts');
this.props.router.history.push('/keyboard-shortcuts');
}
}
handleHotkeyGoToHome = () => {
this.context.router.history.push('/timelines/home');
this.props.router.history.push('/timelines/home');
}
handleHotkeyGoToNotifications = () => {
this.context.router.history.push('/notifications');
this.props.router.history.push('/notifications');
}
handleHotkeyGoToLocal = () => {
this.context.router.history.push('/timelines/public/local');
this.props.router.history.push('/timelines/public/local');
}
handleHotkeyGoToFederated = () => {
this.context.router.history.push('/timelines/public');
this.props.router.history.push('/timelines/public');
}
handleHotkeyGoToDirect = () => {
this.context.router.history.push('/timelines/direct');
this.props.router.history.push('/timelines/direct');
}
handleHotkeyGoToStart = () => {
this.context.router.history.push('/getting-started');
this.props.router.history.push('/getting-started');
}
handleHotkeyGoToFavourites = () => {
this.context.router.history.push('/favourites');
this.props.router.history.push('/favourites');
}
handleHotkeyGoToPinned = () => {
this.context.router.history.push('/pinned');
this.props.router.history.push('/pinned');
}
handleHotkeyGoToProfile = () => {
this.context.router.history.push(`/accounts/${me}`);
this.props.router.history.push(`/accounts/${me}`);
}
handleHotkeyGoToBlocked = () => {
this.context.router.history.push('/blocks');
this.props.router.history.push('/blocks');
}
handleHotkeyGoToMuted = () => {
this.context.router.history.push('/mutes');
this.props.router.history.push('/mutes');
}
render () {

View File

@@ -27,7 +27,6 @@ import {
FAVOURITES_FETCH_SUCCESS,
} from 'flavours/glitch/actions/interactions';
import {
TIMELINE_REFRESH_SUCCESS,
TIMELINE_UPDATE,
TIMELINE_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/timelines';
@@ -38,7 +37,6 @@ import {
import { SEARCH_FETCH_SUCCESS } from 'flavours/glitch/actions/search';
import {
NOTIFICATIONS_UPDATE,
NOTIFICATIONS_REFRESH_SUCCESS,
NOTIFICATIONS_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/notifications';
import {
@@ -144,11 +142,9 @@ export default function accounts(state = initialState, action) {
case LIST_ACCOUNTS_FETCH_SUCCESS:
case LIST_EDITOR_SUGGESTIONS_READY:
return action.accounts ? normalizeAccounts(state, action.accounts) : state;
case NOTIFICATIONS_REFRESH_SUCCESS:
case NOTIFICATIONS_EXPAND_SUCCESS:
case SEARCH_FETCH_SUCCESS:
return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses);
case TIMELINE_REFRESH_SUCCESS:
case TIMELINE_EXPAND_SUCCESS:
case CONTEXT_FETCH_SUCCESS:
case FAVOURITED_STATUSES_FETCH_SUCCESS:

View File

@@ -29,7 +29,6 @@ import {
FAVOURITES_FETCH_SUCCESS,
} from 'flavours/glitch/actions/interactions';
import {
TIMELINE_REFRESH_SUCCESS,
TIMELINE_UPDATE,
TIMELINE_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/timelines';
@@ -40,7 +39,6 @@ import {
import { SEARCH_FETCH_SUCCESS } from 'flavours/glitch/actions/search';
import {
NOTIFICATIONS_UPDATE,
NOTIFICATIONS_REFRESH_SUCCESS,
NOTIFICATIONS_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/notifications';
import {
@@ -119,11 +117,9 @@ export default function accountsCounters(state = initialState, action) {
case LIST_ACCOUNTS_FETCH_SUCCESS:
case LIST_EDITOR_SUGGESTIONS_READY:
return action.accounts ? normalizeAccounts(state, action.accounts) : state;
case NOTIFICATIONS_REFRESH_SUCCESS:
case NOTIFICATIONS_EXPAND_SUCCESS:
case SEARCH_FETCH_SUCCESS:
return normalizeAccountsFromStatuses(normalizeAccounts(state, action.accounts), action.statuses);
case TIMELINE_REFRESH_SUCCESS:
case TIMELINE_EXPAND_SUCCESS:
case CONTEXT_FETCH_SUCCESS:
case FAVOURITED_STATUSES_FETCH_SUCCESS:

View File

@@ -21,14 +21,12 @@ import {
STATUS_UNMUTE_SUCCESS,
} from 'flavours/glitch/actions/statuses';
import {
TIMELINE_REFRESH_SUCCESS,
TIMELINE_UPDATE,
TIMELINE_DELETE,
TIMELINE_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/timelines';
import {
NOTIFICATIONS_UPDATE,
NOTIFICATIONS_REFRESH_SUCCESS,
NOTIFICATIONS_EXPAND_SUCCESS,
} from 'flavours/glitch/actions/notifications';
import {
@@ -129,10 +127,8 @@ export default function statuses(state = initialState, action) {
return state.setIn([action.id, 'muted'], true);
case STATUS_UNMUTE_SUCCESS:
return state.setIn([action.id, 'muted'], false);
case TIMELINE_REFRESH_SUCCESS:
case TIMELINE_EXPAND_SUCCESS:
case CONTEXT_FETCH_SUCCESS:
case NOTIFICATIONS_REFRESH_SUCCESS:
case NOTIFICATIONS_EXPAND_SUCCESS:
case FAVOURITED_STATUSES_FETCH_SUCCESS:
case FAVOURITED_STATUSES_EXPAND_SUCCESS:

View File

@@ -9,7 +9,14 @@ const { unicodeToFilename } = require('./unicode_to_filename');
const { unicodeToUnifiedName } = require('./unicode_to_unified_name');
const emojiMap = require('./emoji_map.json');
const { emojiIndex } = require('emoji-mart');
const { default: emojiMartData } = require('emoji-mart/dist/data');
const { uncompress: emojiMartUncompress } = require('emoji-mart/dist/utils/data');
let data = require('emoji-mart/data/all.json');
if(data.compressed) {
data = emojiMartUncompress(data);
}
const emojiMartData = data;
const excluded = ['®', '©', '™'];
const skins = ['🏻', '🏼', '🏽', '🏾', '🏿'];
@@ -88,6 +95,6 @@ module.exports = JSON.parse(JSON.stringify([
shortCodesToEmojiData,
emojiMartData.skins,
emojiMartData.categories,
emojiMartData.short_names,
emojiMartData.aliases,
emojisWithoutShortCodes,
]));

View File

@@ -8,6 +8,7 @@ let originalPool = {};
let index = {};
let emojisList = {};
let emoticonsList = {};
let customEmojisList = [];
for (let emoji in data.emojis) {
let emojiData = data.emojis[emoji];
@@ -28,7 +29,18 @@ for (let emoji in data.emojis) {
originalPool[id] = emojiData;
}
function clearCustomEmojis(pool) {
customEmojisList.forEach((emoji) => {
let emojiId = emoji.id || emoji.short_names[0];
delete pool[emojiId];
delete emojisList[emojiId];
});
}
function addCustomToPool(custom, pool) {
if (customEmojisList.length) clearCustomEmojis(pool);
custom.forEach((emoji) => {
let emojiId = emoji.id || emoji.short_names[0];
@@ -37,10 +49,14 @@ function addCustomToPool(custom, pool) {
emojisList[emojiId] = getSanitizedData(emoji);
}
});
customEmojisList = custom;
index = {};
}
function search(value, { emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}) {
addCustomToPool(custom, originalPool);
if (customEmojisList !== custom)
addCustomToPool(custom, originalPool);
maxResults = maxResults || 75;
include = include || [];
@@ -143,7 +159,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
if (results) {
if (emojisToShowFilter) {
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id].unified));
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id]));
}
if (results && results.length > maxResults) {

View File

@@ -1,5 +1,5 @@
import Picker from 'emoji-mart/dist-es/components/picker';
import Emoji from 'emoji-mart/dist-es/components/emoji';
import Picker from 'emoji-mart/dist-es/components/picker/picker';
import Emoji from 'emoji-mart/dist-es/components/emoji/emoji';
export {
Picker,

View File

@@ -28,11 +28,6 @@ function main() {
store.dispatch(registerPushNotifications.register());
}
perf.stop('main()');
// remember the initial URL
if (window.history && typeof window._mastoInitialHistoryLen === 'undefined') {
window._mastoInitialHistoryLen = window.history.length;
}
});
}

View File

@@ -29,6 +29,8 @@ export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
export const STATUS_REVEAL = 'STATUS_REVEAL';
export const STATUS_HIDE = 'STATUS_HIDE';
export const REDRAFT = 'REDRAFT';
export function fetchStatusRequest(id, skipLoading) {
return {
type: STATUS_FETCH_REQUEST,
@@ -131,14 +133,27 @@ export function fetchStatusFail(id, error, skipLoading) {
};
};
export function deleteStatus(id) {
export function redraft(status) {
return {
type: REDRAFT,
status,
};
};
export function deleteStatus(id, withRedraft = false) {
return (dispatch, getState) => {
const status = getState().getIn(['statuses', id]);
dispatch(deleteStatusRequest(id));
api(getState).delete(`/api/v1/statuses/${id}`).then(() => {
evictStatus(id);
dispatch(deleteStatusSuccess(id));
dispatch(deleteFromTimelines(id));
if (withRedraft) {
dispatch(redraft(status));
}
}).catch(error => {
dispatch(deleteStatusFail(id, error));
});

View File

@@ -1,32 +0,0 @@
import api from '../api';
export const TRENDS_FETCH_REQUEST = 'TRENDS_FETCH_REQUEST';
export const TRENDS_FETCH_SUCCESS = 'TRENDS_FETCH_SUCCESS';
export const TRENDS_FETCH_FAIL = 'TRENDS_FETCH_FAIL';
export const fetchTrends = () => (dispatch, getState) => {
dispatch(fetchTrendsRequest());
api(getState)
.get('/api/v1/trends')
.then(({ data }) => dispatch(fetchTrendsSuccess(data)))
.catch(err => dispatch(fetchTrendsFail(err)));
};
export const fetchTrendsRequest = () => ({
type: TRENDS_FETCH_REQUEST,
skipLoading: true,
});
export const fetchTrendsSuccess = trends => ({
type: TRENDS_FETCH_SUCCESS,
trends,
skipLoading: true,
});
export const fetchTrendsFail = error => ({
type: TRENDS_FETCH_FAIL,
error,
skipLoading: true,
skipAlert: true,
});

View File

@@ -1,16 +1,9 @@
import React from 'react';
import { Sparklines, SparklinesCurve } from 'react-sparklines';
import { Link } from 'react-router-dom';
import { FormattedMessage, FormattedNumber } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
const shortNumberFormat = number => {
if (number < 1000) {
return <FormattedNumber value={number} />;
} else {
return <React.Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</React.Fragment>;
}
};
import { shortNumberFormat } from '../utils/numbers';
const Hashtag = ({ hashtag }) => (
<div className='trends__item'>

View File

@@ -9,6 +9,7 @@ import { me } from '../initial_state';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
@@ -88,6 +89,10 @@ export default class StatusActionBar extends ImmutablePureComponent {
this.props.onDelete(this.props.status);
}
handleRedraftClick = () => {
this.props.onDelete(this.props.status, true);
}
handlePinClick = () => {
this.props.onPin(this.props.status);
}
@@ -159,6 +164,7 @@ export default class StatusActionBar extends ImmutablePureComponent {
}
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
} else {
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });

View File

@@ -33,6 +33,8 @@ import { showAlertForError } from '../actions/alerts';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
});
@@ -91,14 +93,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
}));
},
onDelete (status) {
onDelete (status, withRedraft = false) {
if (!deleteModal) {
dispatch(deleteStatus(status.get('id')));
dispatch(deleteStatus(status.get('id'), withRedraft));
} else {
dispatch(openModal('CONFIRM', {
message: intl.formatMessage(messages.deleteMessage),
confirm: intl.formatMessage(messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'))),
message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
}));
}
},

View File

@@ -3,8 +3,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { Link } from 'react-router-dom';
import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { me } from '../../../initial_state';
import { shortNumberFormat } from '../../../utils/numbers';
const messages = defineMessages({
mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' },
@@ -146,17 +147,17 @@ export default class ActionBar extends React.PureComponent {
<div className='account__action-bar-links'>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`}>
<span><FormattedMessage id='account.posts' defaultMessage='Toots' /></span>
<strong><FormattedNumber value={account.get('statuses_count')} /></strong>
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
</Link>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`}>
<span><FormattedMessage id='account.follows' defaultMessage='Follows' /></span>
<strong><FormattedNumber value={account.get('following_count')} /></strong>
<strong>{shortNumberFormat(account.get('following_count'))}</strong>
</Link>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`}>
<span><FormattedMessage id='account.followers' defaultMessage='Followers' /></span>
<strong><FormattedNumber value={account.get('followers_count')} /></strong>
<strong>{shortNumberFormat(account.get('followers_count'))}</strong>
</Link>
</div>
</div>

View File

@@ -96,7 +96,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
onBlockDomain (domain) {
dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />,
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />,
confirm: intl.formatMessage(messages.blockDomainConfirm),
onConfirm: () => dispatch(blockDomain(domain)),
}));

View File

@@ -128,12 +128,24 @@ export default class ComposeForm extends ImmutablePureComponent {
} else if(prevProps.is_submitting && !this.props.is_submitting) {
this.autosuggestTextarea.textarea.focus();
}
if (this.props.spoiler !== prevProps.spoiler) {
if (this.props.spoiler) {
this.spoilerText.focus();
} else {
this.autosuggestTextarea.textarea.focus();
}
}
}
setAutosuggestTextarea = (c) => {
this.autosuggestTextarea = c;
}
setSpoilerText = (c) => {
this.spoilerText = c;
}
handleEmojiPick = (data) => {
const { text } = this.props;
const position = this.autosuggestTextarea.textarea.selectionStart;
@@ -164,7 +176,7 @@ export default class ComposeForm extends ImmutablePureComponent {
<div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}>
<label>
<span style={{ display: 'none' }}>{intl.formatMessage(messages.spoiler_placeholder)}</span>
<input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoiler_text} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} type='text' className='spoiler-input__input' id='cw-spoiler-input' />
<input placeholder={intl.formatMessage(messages.spoiler_placeholder)} value={this.props.spoiler_text} onChange={this.handleChangeSpoilerText} onKeyDown={this.handleKeyDown} type='text' className='spoiler-input__input' id='cw-spoiler-input' ref={this.setSpoilerText} />
</label>
</div>

View File

@@ -28,7 +28,7 @@ const messages = defineMessages({
const assetHost = process.env.CDN_HOST || '';
let EmojiPicker, Emoji; // load asynchronously
const backgroundImageFn = () => `${assetHost}/emoji/sheet.png`;
const backgroundImageFn = () => `${assetHost}/emoji/sheet_10.png`;
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
const categoriesSort = [

View File

@@ -1,5 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage } from 'react-intl';
import AccountContainer from '../../../containers/account_container';
@@ -11,36 +10,14 @@ export default class SearchResults extends ImmutablePureComponent {
static propTypes = {
results: ImmutablePropTypes.map.isRequired,
trends: ImmutablePropTypes.list,
fetchTrends: PropTypes.func.isRequired,
};
componentDidMount () {
const { fetchTrends } = this.props;
fetchTrends();
}
render () {
const { results, trends } = this.props;
const { results } = this.props;
let accounts, statuses, hashtags;
let count = 0;
if (results.isEmpty()) {
return (
<div className='search-results'>
<div className='trends'>
<div className='trends__header'>
<i className='fa fa-fire fa-fw' />
<FormattedMessage id='trends.header' defaultMessage='Trending now' />
</div>
{trends && trends.map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
</div>
</div>
);
}
if (results.get('accounts') && results.get('accounts').size > 0) {
count += results.get('accounts').size;
accounts = (

View File

@@ -1,14 +1,8 @@
import { connect } from 'react-redux';
import SearchResults from '../components/search_results';
import { fetchTrends } from '../../../actions/trends';
const mapStateToProps = state => ({
results: state.getIn(['search', 'results']),
trends: state.getIn(['trends', 'items']),
});
const mapDispatchToProps = dispatch => ({
fetchTrends: () => dispatch(fetchTrends()),
});
export default connect(mapStateToProps, mapDispatchToProps)(SearchResults);
export default connect(mapStateToProps)(SearchResults);

View File

@@ -51,7 +51,7 @@ describe('emoji', () => {
});
it('does an emoji that has no shortcode', () => {
expect(emojify('🕉️')).toEqual('<img draggable="false" class="emojione" alt="🕉️" title="" src="/emoji/1f549.svg" />');
expect(emojify('👁‍🗨')).toEqual('<img draggable="false" class="emojione" alt="👁‍🗨" title="" src="/emoji/1f441-200d-1f5e8.svg" />');
});
it('does an emoji whose filename is irregular', () => {

View File

@@ -44,6 +44,57 @@ describe('emoji_index', () => {
expect(emojiIndex.search('apple').map(trimEmojis)).toEqual(expected);
});
it('can include/exclude categories', () => {
expect(search('flag', { include: ['people'] })).toEqual([]);
expect(emojiIndex.search('flag', { include: ['people'] })).toEqual([]);
});
it('(different behavior from emoji-mart) do not erases custom emoji if not passed again', () => {
const custom = [
{
id: 'mastodon',
name: 'mastodon',
short_names: ['mastodon'],
text: '',
emoticons: [],
keywords: ['mastodon'],
imageUrl: 'http://example.com',
custom: true,
},
];
search('', { custom });
emojiIndex.search('', { custom });
const expected = [];
const lightExpected = [
{
id: 'mastodon',
custom: true,
},
];
expect(search('masto').map(trimEmojis)).toEqual(lightExpected);
expect(emojiIndex.search('masto').map(trimEmojis)).toEqual(expected);
});
it('(different behavior from emoji-mart) erases custom emoji if another is passed', () => {
const custom = [
{
id: 'mastodon',
name: 'mastodon',
short_names: ['mastodon'],
text: '',
emoticons: [],
keywords: ['mastodon'],
imageUrl: 'http://example.com',
custom: true,
},
];
search('', { custom });
emojiIndex.search('', { custom });
const expected = [];
expect(search('masto', { custom: [] }).map(trimEmojis)).toEqual(expected);
expect(emojiIndex.search('masto').map(trimEmojis)).toEqual(expected);
});
it('handles custom emoji', () => {
const custom = [
{
@@ -65,23 +116,18 @@ describe('emoji_index', () => {
custom: true,
},
];
expect(search('masto').map(trimEmojis)).toEqual(expected);
expect(emojiIndex.search('masto').map(trimEmojis)).toEqual(expected);
expect(search('masto', { custom }).map(trimEmojis)).toEqual(expected);
expect(emojiIndex.search('masto', { custom }).map(trimEmojis)).toEqual(expected);
});
it('should filter only emojis we care about, exclude pineapple', () => {
const emojisToShowFilter = unified => unified !== '1F34D';
const emojisToShowFilter = emoji => emoji.unified !== '1F34D';
expect(search('apple', { emojisToShowFilter }).map((obj) => obj.id))
.not.toContain('pineapple');
expect(emojiIndex.search('apple', { emojisToShowFilter }).map((obj) => obj.id))
.not.toContain('pineapple');
});
it('can include/exclude categories', () => {
expect(search('flag', { include: ['people'] })).toEqual([]);
expect(emojiIndex.search('flag', { include: ['people'] })).toEqual([]);
});
it('does an emoji whose unified name is irregular', () => {
const expected = [
{

View File

@@ -9,7 +9,13 @@ const { unicodeToFilename } = require('./unicode_to_filename');
const { unicodeToUnifiedName } = require('./unicode_to_unified_name');
const emojiMap = require('./emoji_map.json');
const { emojiIndex } = require('emoji-mart');
const { default: emojiMartData } = require('emoji-mart/dist/data');
const { uncompress: emojiMartUncompress } = require('emoji-mart/dist/utils/data');
let data = require('emoji-mart/data/all.json');
if(data.compressed) {
data = emojiMartUncompress(data);
}
const emojiMartData = data;
const excluded = ['®', '©', '™'];
const skins = ['🏻', '🏼', '🏽', '🏾', '🏿'];
@@ -88,6 +94,6 @@ module.exports = JSON.parse(JSON.stringify([
shortCodesToEmojiData,
emojiMartData.skins,
emojiMartData.categories,
emojiMartData.short_names,
emojiMartData.aliases,
emojisWithoutShortCodes,
]));

View File

@@ -8,6 +8,7 @@ let originalPool = {};
let index = {};
let emojisList = {};
let emoticonsList = {};
let customEmojisList = [];
for (let emoji in data.emojis) {
let emojiData = data.emojis[emoji];
@@ -28,7 +29,18 @@ for (let emoji in data.emojis) {
originalPool[id] = emojiData;
}
function clearCustomEmojis(pool) {
customEmojisList.forEach((emoji) => {
let emojiId = emoji.id || emoji.short_names[0];
delete pool[emojiId];
delete emojisList[emojiId];
});
}
function addCustomToPool(custom, pool) {
if (customEmojisList.length) clearCustomEmojis(pool);
custom.forEach((emoji) => {
let emojiId = emoji.id || emoji.short_names[0];
@@ -37,10 +49,18 @@ function addCustomToPool(custom, pool) {
emojisList[emojiId] = getSanitizedData(emoji);
}
});
customEmojisList = custom;
index = {};
}
function search(value, { emojisToShowFilter, maxResults, include, exclude, custom = [] } = {}) {
addCustomToPool(custom, originalPool);
function search(value, { emojisToShowFilter, maxResults, include, exclude, custom } = {}) {
if (custom !== undefined) {
if (customEmojisList !== custom)
addCustomToPool(custom, originalPool);
} else {
custom = [];
}
maxResults = maxResults || 75;
include = include || [];
@@ -143,7 +163,7 @@ function search(value, { emojisToShowFilter, maxResults, include, exclude, custo
if (results) {
if (emojisToShowFilter) {
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id].unified));
results = results.filter((result) => emojisToShowFilter(data.emojis[result.id]));
}
if (results && results.length > maxResults) {

View File

@@ -1,5 +1,5 @@
import Picker from 'emoji-mart/dist-es/components/picker';
import Emoji from 'emoji-mart/dist-es/components/emoji';
import Picker from 'emoji-mart/dist-es/components/picker/picker';
import Emoji from 'emoji-mart/dist-es/components/emoji/emoji';
export {
Picker,

View File

@@ -1,71 +0,0 @@
import classNames from 'classnames';
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { FormattedMessage, defineMessages } from 'react-intl';
import Hashtag from '../../../components/hashtag';
import { Link } from 'react-router-dom';
const messages = defineMessages({
refresh_trends: { id: 'trends.refresh', defaultMessage: 'Refresh' },
});
export default class Trends extends ImmutablePureComponent {
static defaultProps = {
loading: false,
};
static propTypes = {
trends: ImmutablePropTypes.list,
loading: PropTypes.bool.isRequired,
showTrends: PropTypes.bool.isRequired,
fetchTrends: PropTypes.func.isRequired,
toggleTrends: PropTypes.func.isRequired,
};
componentDidMount () {
setTimeout(() => this.props.fetchTrends(), 5000);
}
handleRefreshTrends = () => {
this.props.fetchTrends();
}
handleToggle = () => {
this.props.toggleTrends(!this.props.showTrends);
}
render () {
const { intl, trends, loading, showTrends } = this.props;
if (!trends || trends.size < 1) {
return null;
}
return (
<div className='getting-started__trends'>
<div className='column-header__wrapper'>
<h1 className='column-header'>
<button>
<i className='fa fa-fire fa-fw' />
<FormattedMessage id='trends.header' defaultMessage='Trending now' />
</button>
<div className='column-header__buttons'>
{showTrends && <button onClick={this.handleRefreshTrends} className='column-header__button' title={intl.formatMessage(messages.refresh_trends)} aria-label={intl.formatMessage(messages.refresh_trends)} disabled={loading}><i className={classNames('fa', 'fa-refresh', { 'fa-spin': loading })} /></button>}
<button onClick={this.handleToggle} className='column-header__button'><i className={classNames('fa', showTrends ? 'fa-chevron-down' : 'fa-chevron-up')} /></button>
</div>
</h1>
</div>
{showTrends && <div className='getting-started__scrollable'>
{trends.take(3).map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
<Link to='/trends' className='load-more'><FormattedMessage id='status.load_more' defaultMessage='Load more' /></Link>
</div>}
</div>
);
}
}

View File

@@ -1,18 +0,0 @@
import { connect } from 'react-redux';
import { injectIntl } from 'react-intl';
import { fetchTrends } from '../../../actions/trends';
import Trends from '../components/trends';
import { changeSetting } from '../../../actions/settings';
const mapStateToProps = state => ({
trends: state.getIn(['trends', 'items']),
loading: state.getIn(['trends', 'isLoading']),
showTrends: state.getIn(['settings', 'trends', 'show']),
});
const mapDispatchToProps = dispatch => ({
fetchTrends: () => dispatch(fetchTrends()),
toggleTrends: show => dispatch(changeSetting(['trends', 'show'], show)),
});
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Trends));

View File

@@ -12,7 +12,6 @@ import { fetchFollowRequests } from '../../actions/accounts';
import { List as ImmutableList } from 'immutable';
import { Link } from 'react-router-dom';
import NavigationBar from '../compose/components/navigation_bar';
import TrendsContainer from './containers/trends_container';
const messages = defineMessages({
home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
@@ -132,8 +131,6 @@ export default class GettingStarted extends ImmutablePureComponent {
{navItems}
</div>
{multiColumn && <TrendsContainer />}
{!multiColumn && <div className='flex-spacer' />}
<div className='getting-started getting-started__footer'>

View File

@@ -8,6 +8,7 @@ import { me } from '../../../initial_state';
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' },
@@ -67,6 +68,10 @@ export default class ActionBar extends React.PureComponent {
this.props.onDelete(this.props.status);
}
handleRedraftClick = () => {
this.props.onDelete(this.props.status, true);
}
handleDirectClick = () => {
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
}
@@ -132,6 +137,7 @@ export default class ActionBar extends React.PureComponent {
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
menu.push(null);
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
} else {
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });

View File

@@ -47,6 +47,8 @@ import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.' },
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
@@ -77,9 +79,12 @@ const makeMapStateToProps = () => {
let id = ids.shift();
const replies = state.getIn(['contexts', 'replies', id]);
if (status.get('id') !== id) {
mutable.push(id);
}
if (replies) {
replies.forEach(reply => {
mutable.push(reply);
replies.reverse().forEach(reply => {
ids.unshift(reply);
});
}
@@ -169,16 +174,16 @@ export default class Status extends ImmutablePureComponent {
}
}
handleDeleteClick = (status) => {
handleDeleteClick = (status, withRedraft = false) => {
const { dispatch, intl } = this.props;
if (!deleteModal) {
dispatch(deleteStatus(status.get('id')));
dispatch(deleteStatus(status.get('id'), withRedraft));
} else {
dispatch(openModal('CONFIRM', {
message: intl.formatMessage(messages.deleteMessage),
confirm: intl.formatMessage(messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'))),
message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
}));
}
}

View File

@@ -63,6 +63,12 @@ export default class ReportModal extends ImmutablePureComponent {
this.props.dispatch(submitReport());
}
handleKeyDown = e => {
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
this.handleSubmit();
}
}
componentDidMount () {
this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true }));
}
@@ -98,6 +104,7 @@ export default class ReportModal extends ImmutablePureComponent {
placeholder={intl.formatMessage(messages.placeholder)}
value={comment}
onChange={this.handleCommentChange}
onKeyDown={this.handleKeyDown}
disabled={isSubmitting}
/>

View File

@@ -42,7 +42,6 @@ import {
Mutes,
PinnedStatuses,
Lists,
Trends,
} from './util/async-components';
import { HotKeys } from 'react-hotkeys';
import { me } from '../../initial_state';
@@ -155,7 +154,6 @@ class SwitchingColumnsArea extends React.PureComponent {
<WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
<WrappedRoute path='/search' component={Compose} content={children} componentParams={{ isSearchPage: true }} />
<WrappedRoute path='/trends' component={Trends} content={children} />
<WrappedRoute path='/statuses/new' component={Compose} content={children} />
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />

View File

@@ -129,7 +129,3 @@ export function EmbedModal () {
export function ListEditor () {
return import(/* webpackChunkName: "features/list_editor" */'../../list_editor');
}
export function Trends () {
return import(/* webpackChunkName: "features/trends" */'../../trends');
}

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "متأكد من أنك تود حظر إسم النطاق {domain} بالكامل ؟ في غالب الأحيان يُستَحسَن كتم أو حظر بعض الحسابات بدلا من حظر نطاق بالكامل.",
"confirmations.mute.confirm": "أكتم",
"confirmations.mute.message": "هل أنت متأكد أنك تريد كتم {name} ؟",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "إلغاء المتابعة",
"confirmations.unfollow.message": "متأكد من أنك تريد إلغاء متابعة {name} ؟",
"embed.instructions": "يمكنكم إدماج هذه الحالة على موقعكم الإلكتروني عن طريق نسخ الشفرة أدناه.",
@@ -264,6 +266,7 @@
"status.reblog": "رَقِّي",
"status.reblog_private": "القيام بالترقية إلى الجمهور الأصلي",
"status.reblogged_by": "{name} رقى",
"status.redraft": "Delete & re-draft",
"status.reply": "ردّ",
"status.replyAll": "رُد على الخيط",
"status.report": "إبلِغ عن @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "سوف تفقد مسودتك إن تركت ماستدون.",
"upload_area.title": "إسحب ثم أفلت للرفع",
"upload_button.label": "إضافة وسائط",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Споделяне",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} сподели",
"status.redraft": "Delete & re-draft",
"status.reply": "Отговор",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Добави медия",

View File

@@ -60,7 +60,7 @@
"column_header.unpin": "No fixis",
"column_subheading.settings": "Configuració",
"compose_form.direct_message_warning": "Aquest toot només serà enviat als usuaris esmentats. De totes maneres, els operadors de la teva o de qualsevol de les instàncies receptores poden inspeccionar aquest missatge.",
"compose_form.direct_message_warning_learn_more": "Learn more",
"compose_form.direct_message_warning_learn_more": "Aprèn més",
"compose_form.hashtag_warning": "Aquest toot no es mostrarà en cap etiqueta ja que no està llistat. Només els toots públics poden ser cercats per etiqueta.",
"compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.",
"compose_form.lock_disclaimer.lock": "blocat",
@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Estàs realment, realment segur que vols blocar totalment {domain}? En la majoria dels casos blocar o silenciar uns pocs objectius és suficient i preferible.",
"confirmations.mute.confirm": "Silencia",
"confirmations.mute.message": "Estàs segur que vols silenciar {name}?",
"confirmations.redraft.confirm": "Esborrar i refer",
"confirmations.redraft.message": "Estàs segur que vols esborrar aquesta publicació i tornar a redactar-la? Perderàs totes les respostes, impulsos i favorits.",
"confirmations.unfollow.confirm": "Deixa de seguir",
"confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?",
"embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.",
@@ -114,7 +116,7 @@
"getting_started.documentation": "Documentation",
"getting_started.heading": "Començant",
"getting_started.open_source_notice": "Mastodon és un programari de codi obert. Pots contribuir o informar de problemes a GitHub a {github}.",
"getting_started.terms": "Terms of service",
"getting_started.terms": "Termes del servei",
"home.column_settings.advanced": "Avançat",
"home.column_settings.basic": "Bàsic",
"home.column_settings.filter_regex": "Filtrar per expressió regular",
@@ -158,7 +160,7 @@
"navigation_bar.blocks": "Usuaris bloquejats",
"navigation_bar.community_timeline": "Línia de temps Local",
"navigation_bar.direct": "Missatges directes",
"navigation_bar.discover": "Discover",
"navigation_bar.discover": "Descobreix",
"navigation_bar.domain_blocks": "Dominis ocults",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favorits",
@@ -172,7 +174,7 @@
"navigation_bar.pins": "Toots fixats",
"navigation_bar.preferences": "Preferències",
"navigation_bar.public_timeline": "Línia de temps federada",
"navigation_bar.security": "Security",
"navigation_bar.security": "Seguretat",
"notification.favourite": "{name} ha afavorit el teu estat",
"notification.follow": "{name} et segueix",
"notification.mention": "{name} t'ha esmentat",
@@ -188,7 +190,7 @@
"notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Mostrar en la columna",
"notifications.column_settings.sound": "Reproduïr so",
"notifications.group": "{count} notifications",
"notifications.group": "{count} notificacions",
"onboarding.done": "Fet",
"onboarding.next": "Següent",
"onboarding.page_five.public_timelines": "La línia de temps local mostra missatges públics de tothom de {domain}. La línia de temps federada mostra els missatges públics de tothom que la gent de {domain} segueix. Aquests són les línies de temps Públiques, una bona manera de descobrir noves persones.",
@@ -264,6 +266,7 @@
"status.reblog": "Impuls",
"status.reblog_private": "Impulsar a l'audiència original",
"status.reblogged_by": "{name} ha retootejat",
"status.redraft": "Esborrar i reescriure",
"status.reply": "Respondre",
"status.replyAll": "Respondre al tema",
"status.report": "Informar sobre @{name}",
@@ -283,9 +286,7 @@
"tabs_bar.search": "Cerca",
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"trends.count_by_accounts": "{count} {rawCount, plural, una {person} altres {people}} parlant",
"ui.beforeunload": "El vostre esborrany es perdrà si sortiu de Mastodon.",
"upload_area.title": "Arrossega i deixa anar per carregar",
"upload_button.label": "Afegir multimèdia",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Site sicuru·a che vulete piattà tuttu à {domain}? Saria forse abbastanza di bluccà ò piattà alcuni conti da quallà.",
"confirmations.mute.confirm": "Piattà",
"confirmations.mute.message": "Site sicuru·a che vulete piattà @{name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Disabbunassi",
"confirmations.unfollow.message": "Site sicuru·a ch'ùn vulete più siguità @{name}?",
"embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.",
@@ -264,6 +266,7 @@
"status.reblog": "Sparte",
"status.reblog_private": "Sparte à l'audienza uriginale",
"status.reblogged_by": "{name} hà spartutu",
"status.redraft": "Delete & re-draft",
"status.reply": "Risponde",
"status.replyAll": "Risponde à tutti",
"status.report": "Palisà @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "A bruttacopia sarà persa s'ellu hè chjosu Mastodon.",
"upload_area.title": "Drag & drop per caricà un fugliale",
"upload_button.label": "Aghjunghje un media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Bist du dir wirklich sicher, dass du die ganze Domain {domain} verbergen willst? In den meisten Fällen reichen ein paar gezielte Blocks aus.",
"confirmations.mute.confirm": "Stummschalten",
"confirmations.mute.message": "Bist du dir sicher, dass du {name} stummschalten möchtest?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Entfolgen",
"confirmations.unfollow.message": "Bist du dir sicher, dass du {name} entfolgen möchtest?",
"embed.instructions": "Du kannst diesen Beitrag auf deiner Webseite einbetten, indem du den folgenden Code einfügst.",
@@ -264,6 +266,7 @@
"status.reblog": "Teilen",
"status.reblog_private": "An das eigentliche Publikum teilen",
"status.reblogged_by": "{name} teilte",
"status.redraft": "Delete & re-draft",
"status.reply": "Antworten",
"status.replyAll": "Auf Thread antworten",
"status.report": "@{name} melden",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Dein Entwurf geht verloren, wenn du Mastodon verlässt.",
"upload_area.title": "Zum Hochladen hereinziehen",
"upload_button.label": "Mediendatei hinzufügen",

View File

@@ -219,6 +219,10 @@
"defaultMessage": "Delete",
"id": "status.delete"
},
{
"defaultMessage": "Delete & re-draft",
"id": "status.redraft"
},
{
"defaultMessage": "Direct message @{name}",
"id": "status.direct"
@@ -377,6 +381,14 @@
"defaultMessage": "Are you sure you want to delete this status?",
"id": "confirmations.delete.message"
},
{
"defaultMessage": "Delete & redraft",
"id": "confirmations.redraft.confirm"
},
{
"defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"id": "confirmations.redraft.message"
},
{
"defaultMessage": "Block",
"id": "confirmations.block.confirm"
@@ -437,7 +449,7 @@
"id": "confirmations.block.message"
},
{
"defaultMessage": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"defaultMessage": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"id": "confirmations.domain_block.message"
}
],
@@ -804,10 +816,6 @@
},
{
"descriptors": [
{
"defaultMessage": "Trending now",
"id": "trends.header"
},
{
"defaultMessage": "People",
"id": "search_results.accounts"
@@ -1036,23 +1044,6 @@
],
"path": "app/javascript/mastodon/features/follow_requests/index.json"
},
{
"descriptors": [
{
"defaultMessage": "Refresh",
"id": "trends.refresh"
},
{
"defaultMessage": "Trending now",
"id": "trends.header"
},
{
"defaultMessage": "Load more",
"id": "status.load_more"
}
],
"path": "app/javascript/mastodon/features/getting_started/components/trends.json"
},
{
"descriptors": [
{
@@ -1507,6 +1498,10 @@
"defaultMessage": "Delete",
"id": "status.delete"
},
{
"defaultMessage": "Delete & re-draft",
"id": "status.redraft"
},
{
"defaultMessage": "Direct message @{name}",
"id": "status.direct"
@@ -1588,6 +1583,14 @@
"defaultMessage": "Are you sure you want to delete this status?",
"id": "confirmations.delete.message"
},
{
"defaultMessage": "Delete & redraft",
"id": "confirmations.redraft.confirm"
},
{
"defaultMessage": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"id": "confirmations.redraft.message"
},
{
"defaultMessage": "Block",
"id": "confirmations.block.confirm"
@@ -1607,19 +1610,6 @@
],
"path": "app/javascript/mastodon/features/status/index.json"
},
{
"descriptors": [
{
"defaultMessage": "Trending now",
"id": "trends.header"
},
{
"defaultMessage": "Refresh trends",
"id": "trends.refresh"
}
],
"path": "app/javascript/mastodon/features/trends/index.json"
},
{
"descriptors": [
{

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Σίγουρα θες να μπλοκάρεις ολόκληρο το {domain}; Συνήθως μερικά εστιασμένα μπλοκ ή αποσιωπήσεις επαρκούν και προτιμούνται.",
"confirmations.mute.confirm": "Αποσιώπηση",
"confirmations.mute.message": "Σίγουρα θες να αποσιωπήσεις τον/την {name};",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Διακοπή παρακολούθησης",
"confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};",
"embed.instructions": "Ενσωματώστε αυτή την κατάσταση στην ιστοσελίδα σας αντιγράφοντας τον παρακάτω κώδικα.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.report": "Καταγγελία @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",

View File

@@ -84,9 +84,11 @@
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -269,6 +271,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
@@ -289,8 +292,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas.",
"confirmations.mute.confirm": "Silentigi",
"confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Ne plu sekvi",
"confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?",
"embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.",
@@ -264,6 +266,7 @@
"status.reblog": "Diskonigi",
"status.reblog_private": "Diskonigi al la originala atentaro",
"status.reblogged_by": "{name} diskonigis",
"status.redraft": "Delete & re-draft",
"status.reply": "Respondi",
"status.replyAll": "Respondi al la fadeno",
"status.report": "Signali @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Aŭdovidaĵoj",
"timeline.posts": "Mesaĝoj",
"trends.count_by_accounts": "{count} {rawCount, pluraj, unu {person} alia(j) {people}} parolas",
"trends.header": "Nun furoras",
"trends.refresh": "Aktualigi",
"ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.",
"upload_area.title": "Altreni kaj lasi por alŝuti",
"upload_button.label": "Aldoni aŭdovidaĵon",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "¿Seguro de que quieres bloquear al dominio entero? En algunos casos es preferible bloquear o silenciar objetivos determinados.",
"confirmations.mute.confirm": "Silenciar",
"confirmations.mute.message": "¿Estás seguro de que quieres silenciar a {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Dejar de seguir",
"confirmations.unfollow.message": "¿Estás seguro de que quieres dejar de seguir a {name}?",
"embed.instructions": "Añade este toot a tu sitio web con el siguiente código.",
@@ -264,6 +266,7 @@
"status.reblog": "Retootear",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "Retooteado por {name}",
"status.redraft": "Delete & re-draft",
"status.reply": "Responder",
"status.replyAll": "Responder al hilo",
"status.report": "Reportar",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Tu borrador se perderá si sales de Mastodon.",
"upload_area.title": "Arrastra y suelta para subir",
"upload_button.label": "Subir multimedia",

View File

@@ -10,17 +10,17 @@
"account.follow": "Jarraitu",
"account.followers": "Jarraitzaileak",
"account.follows": "Jarraitzen",
"account.follows_you": "Jarraitzen dizu",
"account.follows_you": "Jarraitzen zaitu",
"account.hide_reblogs": "Ezkutatu @{name}(r)en bultzadak",
"account.media": "Media",
"account.mention": "@{name} aipatu",
"account.mention": "Aipatu @{name}",
"account.moved_to": "{name} hona lekualdatu da:",
"account.mute": "Mututu @{name}",
"account.mute_notifications": "Mututu @{name}(r)en jakinarazpenak",
"account.muted": "Mutututa",
"account.posts": "Toot-ak",
"account.posts_with_replies": "Toot eta erantzunak",
"account.report": "@{name} salatu",
"account.report": "Salatu @{name}",
"account.requested": "Onarpenaren zain. Klikatu jarraitzeko eskaera ezeztatzeko",
"account.share": "@{name}(e)ren profila elkarbanatu",
"account.show_reblogs": "Erakutsi @{name}(r)en bultzadak",
@@ -42,7 +42,7 @@
"column.blocks": "Blokeatutako erabiltzaileak",
"column.community": "Denbora-lerro lokala",
"column.direct": "Mezu zuzenak",
"column.domain_blocks": "Domeinu ezkutuak",
"column.domain_blocks": "Ezkutatutako domeinuak",
"column.favourites": "Gogokoak",
"column.follow_requests": "Jarraitzeko eskariak",
"column.home": "Hasiera",
@@ -67,22 +67,24 @@
"compose_form.placeholder": "Zer duzu buruan?",
"compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Multimedia mingarri gisa markatu da",
"compose_form.sensitive.unmarked": "Multimedia ez da mingarri gisa markatu",
"compose_form.sensitive.marked": "Multimedia edukia hunkigarri gisa markatu da",
"compose_form.sensitive.unmarked": "Multimedia edukia ez da hunkigarri gisa markatu",
"compose_form.spoiler.marked": "Testua abisu batek ezkutatzen du",
"compose_form.spoiler.unmarked": "Testua ez dago ezkutatuta",
"compose_form.spoiler_placeholder": "Idatzi zure abisua hemen",
"confirmation_modal.cancel": "Utzi",
"confirmations.block.confirm": "Block",
"confirmations.block.message": "Ziur {name} blokeatu nahi duzula?",
"confirmations.delete.confirm": "Delete",
"confirmations.delete.confirm": "Ezabatu",
"confirmations.delete.message": "Ziur mezu hau ezabatu nahi duzula?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.confirm": "Ezabatu",
"confirmations.delete_list.message": "Ziur behin betiko ezabatu nahi duzula zerrenda hau?",
"confirmations.domain_block.confirm": "Ezkutatu domeinu osoa",
"confirmations.domain_block.message": "Ziur, erabat ziur, {domain} domeinu osoa blokeatu nahi duzula? Gehienetan gutxi batzuk blokeatu edo mututzearekin nahikoa da.",
"confirmations.mute.confirm": "Mututu",
"confirmations.mute.message": "Ziur {name} mututu nahi duzula?",
"confirmations.redraft.confirm": "Ezabatu eta berridatzi",
"confirmations.redraft.message": "Ziur mezu hau ezabatu eta berridatzi nahi duzula? Berari egindako erantzun, bultzada eta gogokoak galduko dira.",
"confirmations.unfollow.confirm": "Utzi jarraitzeari",
"confirmations.unfollow.message": "Ziur {name} jarraitzeari utzi nahi diozula?",
"embed.instructions": "Txertatu mezu hau zure webgunean beheko kodea kopatuz.",
@@ -112,7 +114,7 @@
"follow_request.authorize": "Baimendu",
"follow_request.reject": "Ukatu",
"getting_started.documentation": "Dokumentazioa",
"getting_started.heading": "Abiapuntua",
"getting_started.heading": "Menua",
"getting_started.open_source_notice": "Mastodon software librea da. Ekarpenak egin ditzakezu edo akatsen berri eman GitHub bidez: {github}.",
"getting_started.terms": "Erabilera baldintzak",
"home.column_settings.advanced": "Aurreratua",
@@ -144,7 +146,7 @@
"lightbox.previous": "Aurrekoa",
"lists.account.add": "Gehitu zerrendara",
"lists.account.remove": "Kendu zerrendatik",
"lists.delete": "Delete list",
"lists.delete": "Ezabatu zerrenda",
"lists.edit": "Editatu zerrenda",
"lists.new.create": "Gehitu zerrenda",
"lists.new.title_placeholder": "Zerrenda berriaren izena",
@@ -159,7 +161,7 @@
"navigation_bar.community_timeline": "Denbora-lerro lokala",
"navigation_bar.direct": "Mezu zuzenak",
"navigation_bar.discover": "Aurkitu",
"navigation_bar.domain_blocks": "Domeinu ezkutuak",
"navigation_bar.domain_blocks": "Ezkutatutako domeinuak",
"navigation_bar.edit_profile": "Aldatu profila",
"navigation_bar.favourites": "Gogokoak",
"navigation_bar.follow_requests": "Jarraitzeko eskariak",
@@ -248,7 +250,7 @@
"status.block": "Block @{name}",
"status.cancel_reblog_private": "Kendu bultzada",
"status.cannot_reblog": "Mezu honi ezin zaio bultzada eman",
"status.delete": "Delete",
"status.delete": "Ezabatu",
"status.direct": "Mezu zuzena @{name}(r)i",
"status.embed": "Txertatu",
"status.favourite": "Gogokoa",
@@ -264,11 +266,12 @@
"status.reblog": "Bultzada",
"status.reblog_private": "Bultzada jatorrizko hartzaileei",
"status.reblogged_by": "{name}(r)en bultzada",
"status.redraft": "Ezabatu eta berridatzi",
"status.reply": "Erantzun",
"status.replyAll": "Erantzun harian",
"status.report": "Salatu @{name}",
"status.sensitive_toggle": "Egin klik ikusteko",
"status.sensitive_warning": "Eduki mingarria",
"status.sensitive_warning": "Eduki hunkigarria",
"status.share": "Partekatu",
"status.show_less": "Erakutsi gutxiago",
"status.show_less_all": "Erakutsi denetarik gutxiago",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toot-ak",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} hitz egiten",
"trends.header": "Joera orain",
"trends.refresh": "Freskatu",
"ui.beforeunload": "Zure zirriborroa galduko da Mastodon uzten baduzu.",
"upload_area.title": "Arrastatu eta jaregin igotzeko",
"upload_button.label": "Gehitu multimedia",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "آیا جدی جدی می‌خواهید کل دامین {domain} را مسدود کنید؟ بیشتر وقت‌ها مسدودکردن یا بی‌صداکردن چند حساب کاربری خاص کافی است و توصیه می‌شود.",
"confirmations.mute.confirm": "بی‌صدا کن",
"confirmations.mute.message": "آیا واقعاً می‌خواهید {name} را بی‌صدا کنید؟",
"confirmations.redraft.confirm": "پاک‌کردن و بازنویسی",
"confirmations.redraft.message": "آیا واقعاً می‌خواهید این نوشته را پاک کنید و آن را از نو بنویسید؟ با این کار همهٔ پاسخ‌ها، بازبوق‌ها، و پسندیده‌شدن‌های آن از دست می‌رود.",
"confirmations.unfollow.confirm": "لغو پیگیری",
"confirmations.unfollow.message": "آیا واقعاً می‌خواهید به پیگیری از {name} پایان دهید؟",
"embed.instructions": "برای جاگذاری این نوشته در سایت خودتان، کد زیر را کپی کنید.",
@@ -264,6 +266,7 @@
"status.reblog": "بازبوقیدن",
"status.reblog_private": "بازبوق به مخاطبان اولیه",
"status.reblogged_by": "{name} بازبوقید",
"status.redraft": "پاک‌کردن و بازنویسی",
"status.reply": "پاسخ",
"status.replyAll": "به نوشته پاسخ دهید",
"status.report": "گزارش دادن @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "عکس و ویدیو",
"timeline.posts": "بوق‌ها",
"trends.count_by_accounts": "{count} {rawCount, plural, one {نفر نوشته است} other {نفر نوشته‌اند}}",
"trends.header": "موضوعات داغ",
"trends.refresh": "به‌روزرسانی",
"ui.beforeunload": "اگر از ماستدون خارج شوید پیش‌نویس شما پاک خواهد شد.",
"upload_area.title": "برای بارگذاری به این‌جا بکشید",
"upload_button.label": "افزودن تصویر",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Haluatko aivan varmasti estää koko verkko-osoitteen {domain}? Useimmiten jokunen kohdistettu esto ja mykistys riittää, ja se on suositeltavampi tapa toimia.",
"confirmations.mute.confirm": "Mykistä",
"confirmations.mute.message": "Haluatko varmasti mykistää käyttäjän {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Lakkaa seuraamasta",
"confirmations.unfollow.message": "Haluatko varmasti lakata seuraamasta käyttäjää {name}?",
"embed.instructions": "Upota statuspäivitys sivullesi kopioimalla alla oleva koodi.",
@@ -264,6 +266,7 @@
"status.reblog": "Buustaa",
"status.reblog_private": "Buustaa alkuperäiselle yleisölle",
"status.reblogged_by": "{name} buustasi",
"status.redraft": "Delete & re-draft",
"status.reply": "Vastaa",
"status.replyAll": "Vastaa ketjuun",
"status.report": "Raportoi @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.",
"upload_area.title": "Lataa raahaamalla ja pudottamalla tähän",
"upload_button.label": "Lisää mediaa",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
"confirmations.mute.confirm": "Masquer",
"confirmations.mute.message": "Confirmez-vous le masquage de {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Ne plus suivre",
"confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name}?",
"embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.",
@@ -114,7 +116,7 @@
"getting_started.documentation": "Documentation",
"getting_started.heading": "Pour commencer",
"getting_started.open_source_notice": "Mastodon est un logiciel libre. Vous pouvez contribuer et envoyer vos commentaires et rapports de bogues via {github} sur GitHub.",
"getting_started.terms": "Terms of service",
"getting_started.terms": "Conditions dutilisation",
"home.column_settings.advanced": "Avancé",
"home.column_settings.basic": "Basique",
"home.column_settings.filter_regex": "Filtrer avec une expression rationnelle",
@@ -158,7 +160,7 @@
"navigation_bar.blocks": "Comptes bloqués",
"navigation_bar.community_timeline": "Fil public local",
"navigation_bar.direct": "Messages directs",
"navigation_bar.discover": "Discover",
"navigation_bar.discover": "Découvrir",
"navigation_bar.domain_blocks": "Domaines cachés",
"navigation_bar.edit_profile": "Modifier le profil",
"navigation_bar.favourites": "Favoris",
@@ -172,7 +174,7 @@
"navigation_bar.pins": "Pouets épinglés",
"navigation_bar.preferences": "Préférences",
"navigation_bar.public_timeline": "Fil public global",
"navigation_bar.security": "Security",
"navigation_bar.security": "Sécurité",
"notification.favourite": "{name} a ajouté à ses favoris:",
"notification.follow": "{name} vous suit",
"notification.mention": "{name} vous a mentionné⋅e:",
@@ -264,6 +266,7 @@
"status.reblog": "Partager",
"status.reblog_private": "Booster vers l'audience originale",
"status.reblogged_by": "{name} a partagé:",
"status.redraft": "Delete & re-draft",
"status.reply": "Répondre",
"status.replyAll": "Répondre au fil",
"status.report": "Signaler @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Pouets",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
"upload_area.title": "Glissez et déposez pour envoyer",
"upload_button.label": "Joindre un média",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Realmente está segura de que quere bloquear por completo o dominio {domain}? Normalmente é suficiente, e preferible, bloquear de xeito selectivo varios elementos.",
"confirmations.mute.confirm": "Acalar",
"confirmations.mute.message": "Está segura de que quere acalar a {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "Quere deixar de seguir a {name}?",
"embed.instructions": "Copie o código inferior para incrustar no seu sitio web este estado.",
@@ -264,6 +266,7 @@
"status.reblog": "Promover",
"status.reblog_private": "Promover a audiencia orixinal",
"status.reblogged_by": "{name} promoveu",
"status.redraft": "Delete & re-draft",
"status.reply": "Resposta",
"status.replyAll": "Resposta a conversa",
"status.report": "Informar @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "O borrador perderase se sae de Mastodon.",
"upload_area.title": "Arrastre e solte para subir",
"upload_button.label": "Engadir medios",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "באמת באמת לחסום את כל קהילת {domain}? ברב המקרים השתקות נבחרות של מספר משתמשים מסויימים צריכה להספיק.",
"confirmations.mute.confirm": "להשתיק",
"confirmations.mute.message": "להשתיק את {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "להפסיק מעקב",
"confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?",
"embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.",
@@ -264,6 +266,7 @@
"status.reblog": "הדהוד",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "הודהד על ידי {name}",
"status.redraft": "Delete & re-draft",
"status.reply": "תגובה",
"status.replyAll": "תגובה לכולם",
"status.report": "דיווח על @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.",
"upload_area.title": "ניתן להעלות על ידי Drag & drop",
"upload_button.label": "הוספת מדיה",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Jesi li zaista, zaista siguran da želiš potpuno blokirati {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Utišaj",
"confirmations.mute.message": "Jesi li siguran da želiš utišati {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Podigni",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} je podigao",
"status.redraft": "Delete & re-draft",
"status.reply": "Odgovori",
"status.replyAll": "Odgovori na temu",
"status.report": "Prijavi @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Povuci i spusti kako bi uploadao",
"upload_button.label": "Dodaj media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Nagyon biztos abban, hogy le szeretné tiltani az egész {domain}-t? A legtöbb esetben néhány célszerű tiltás vagy némítás elegendő és kívánatosabb megoldás.",
"confirmations.mute.confirm": "Némít",
"confirmations.mute.message": "Biztos benne, hogy némítani szeretné {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Követés visszavonása",
"confirmations.unfollow.message": "Biztos benne, hogy vissza szeretné vonni {name} követését?",
"embed.instructions": "Ágyazza be ezen státuszt weboldalába az alábbi kód másolásával.",
@@ -264,6 +266,7 @@
"status.reblog": "Reblog",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} reblogolta",
"status.redraft": "Delete & re-draft",
"status.reply": "Válasz",
"status.replyAll": "Válaszolj a beszélgetésre",
"status.report": "Report @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "A piszkozata el fog vesztődni ha elhagyja Mastodon-t.",
"upload_area.title": "Húzza ide a feltöltéshez",
"upload_button.label": "Média hozzáadása",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Հաստատ֊հաստա՞տ վստահ ես, որ ուզում ես արգելափակել ամբողջ {domain} տիրույթը։ Սովորաբար մի երկու թիրախավորված արգելափակում կամ լռեցում բավական է ու նախընտրելի։",
"confirmations.mute.confirm": "Լռեցնել",
"confirmations.mute.message": "Վստա՞հ ես, որ ուզում ես {name}֊ին լռեցնել։",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Ապահետեւել",
"confirmations.unfollow.message": "Վստա՞հ ես, որ ուզում ես այլեւս չհետեւել {name}֊ին։",
"embed.instructions": "Այս թութը քո կայքում ներդնելու համար կարող ես պատճենել ներքոհիշյալ կոդը։",
@@ -264,6 +266,7 @@
"status.reblog": "Տարածել",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} տարածել է",
"status.redraft": "Delete & re-draft",
"status.reply": "Պատասխանել",
"status.replyAll": "Պատասխանել թելին",
"status.report": "Բողոքել @{name}֊ից",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Քո սեւագիրը կկորի, եթե լքես Մաստոդոնը։",
"upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
"upload_button.label": "Ավելացնել մեդիա",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Apakah anda benar benar yakin untuk memblokir keseluruhan {domain}? Dalam kasus tertentu beberapa pemblokiran atau penyembunyian lebih baik.",
"confirmations.mute.confirm": "Bisukan",
"confirmations.mute.message": "Apa anda yakin ingin membisukan {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Berhenti mengikuti",
"confirmations.unfollow.message": "Apakah anda ingin berhenti mengikuti {name}?",
"embed.instructions": "Sematkan status ini di website anda dengan menyalin kode di bawah ini.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "di-boost {name}",
"status.redraft": "Delete & re-draft",
"status.reply": "Balas",
"status.replyAll": "Balas ke semua",
"status.report": "Laporkan @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Naskah anda akan hilang jika anda keluar dari Mastodon.",
"upload_area.title": "Seret & lepaskan untuk mengunggah",
"upload_button.label": "Tambahkan media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Repetar",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} repetita",
"status.redraft": "Delete & re-draft",
"status.reply": "Respondar",
"status.replyAll": "Respondar a filo",
"status.report": "Denuncar @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Tranar faligar por kargar",
"upload_button.label": "Adjuntar kontenajo",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Sei davvero sicuro che vuoi bloccare l'intero {domain}? Nella maggior parte dei casi, pochi blocchi o silenziamenti mirati sono sufficienti e preferibili.",
"confirmations.mute.confirm": "Silenzia",
"confirmations.mute.message": "Sei sicuro di voler silenziare {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Smetti di seguire",
"confirmations.unfollow.message": "Sei sicuro che non vuoi più seguire {name}?",
"embed.instructions": "Inserisci questo status nel tuo sito copiando il codice qui sotto.",
@@ -264,6 +266,7 @@
"status.reblog": "Condividi",
"status.reblog_private": "Condividi con i destinatari iniziali",
"status.reblogged_by": "{name} ha condiviso",
"status.redraft": "Delete & re-draft",
"status.reply": "Rispondi",
"status.replyAll": "Rispondi alla conversazione",
"status.report": "Segnala @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "La bozza andrà persa se esci da Mastodon.",
"upload_area.title": "Trascina per caricare",
"upload_button.label": "Aggiungi file multimediale",

View File

@@ -87,6 +87,8 @@
"confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。",
"confirmations.mute.confirm": "ミュート",
"confirmations.mute.message": "本当に{name}さんをミュートしますか?",
"confirmations.redraft.confirm": "削除し下書きに戻す",
"confirmations.redraft.message": "本当にこのトゥートを削除し下書きに戻しますか?このトゥートへの全ての返信やブースト、お気に入り登録を失うことになります。",
"confirmations.unfollow.confirm": "フォロー解除",
"confirmations.unfollow.message": "本当に{name}さんのフォローを解除しますか?",
"embed.instructions": "下記のコードをコピーしてウェブサイトに埋め込みます。",
@@ -269,6 +271,7 @@
"status.reblog": "ブースト",
"status.reblog_private": "ブースト",
"status.reblogged_by": "{name}さんがブースト",
"status.redraft": "削除し下書きに戻す",
"status.reply": "返信",
"status.replyAll": "全員に返信",
"status.report": "@{name}さんを通報",
@@ -289,8 +292,6 @@
"timeline.media": "メディア",
"timeline.posts": "投稿",
"trends.count_by_accounts": "{count} {rawCount, plural, one {人} other {人}} がトゥート",
"trends.header": "トレンドタグ",
"trends.refresh": "更新",
"ui.beforeunload": "Mastodonから離れると送信前の投稿は失われます。",
"upload_area.title": "ドラッグ&ドロップでアップロード",
"upload_button.label": "メディアを追加",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "정말로 {domain} 전체를 숨기시겠습니까? 대부분의 경우 개별 차단이나 뮤트로 충분합니다.",
"confirmations.mute.confirm": "뮤트",
"confirmations.mute.message": "정말로 {name}를 뮤트하시겠습니까?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "언팔로우",
"confirmations.unfollow.message": "정말로 {name}를 언팔로우하시겠습니까?",
"embed.instructions": "아래의 코드를 복사하여 대화를 원하는 곳으로 공유하세요.",
@@ -264,6 +266,7 @@
"status.reblog": "부스트",
"status.reblog_private": "원래의 수신자들에게 부스트",
"status.reblogged_by": "{name}님이 부스트 했습니다",
"status.redraft": "Delete & re-draft",
"status.reply": "답장",
"status.replyAll": "전원에게 답장",
"status.report": "신고",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.",
"upload_area.title": "드래그 & 드롭으로 업로드",
"upload_button.label": "미디어 추가",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Weet je het echt heel erg zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gepaster.",
"confirmations.mute.confirm": "Negeren",
"confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?",
"confirmations.redraft.confirm": "Verwijderen en herschrijven",
"confirmations.redraft.message": "Weet je zeker dat je deze toot wilt verwijderen en herschrijven? Je verliest wel alle reacties, boosts en favorieten.",
"confirmations.unfollow.confirm": "Ontvolgen",
"confirmations.unfollow.message": "Weet je het zeker dat je {name} wilt ontvolgen?",
"embed.instructions": "Embed deze toot op jouw website, door de onderstaande code te kopiëren.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost naar oorspronkelijke ontvangers",
"status.reblogged_by": "{name} boostte",
"status.redraft": "Verwijderen en herschrijven",
"status.reply": "Reageren",
"status.replyAll": "Reageer op iedereen",
"status.report": "Rapporteer @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {persoon praat} other {mensen praten}} hierover",
"trends.header": "Trends",
"trends.refresh": "Vernieuwen",
"ui.beforeunload": "Je concept zal verloren gaan als je Mastodon verlaat.",
"upload_area.title": "Hierin slepen om te uploaden",
"upload_button.label": "Media toevoegen",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Er du sikker på at du vil skjule hele domenet {domain}? I de fleste tilfeller er det bedre med målrettet blokkering eller demping.",
"confirmations.mute.confirm": "Demp",
"confirmations.mute.message": "Er du sikker på at du vil dempe {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Slutt å følge",
"confirmations.unfollow.message": "Er du sikker på at du vil slutte å følge {name}?",
"embed.instructions": "Kopier koden under for å bygge inn denne statusen på hjemmesiden din.",
@@ -264,6 +266,7 @@
"status.reblog": "Fremhev",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "Fremhevd av {name}",
"status.redraft": "Delete & re-draft",
"status.reply": "Svar",
"status.replyAll": "Svar til samtale",
"status.report": "Rapporter @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Din kladd vil bli forkastet om du forlater Mastodon.",
"upload_area.title": "Dra og slipp for å laste opp",
"upload_button.label": "Legg til media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Volètz vertadièrament blocar complètament {domain}? De còps cal pas que blocar o rescondre unas personas solament.",
"confirmations.mute.confirm": "Rescondre",
"confirmations.mute.message": "Sètz segur de voler rescondre {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Quitar de sègre",
"confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name}?",
"embed.instructions": "Embarcar aqueste estatut per lo far veire sus un site Internet en copiar lo còdi çai-jos.",
@@ -264,6 +266,7 @@
"status.reblog": "Partejar",
"status.reblog_private": "Partejar a laudiéncia dorigina",
"status.reblogged_by": "{name} a partejat",
"status.redraft": "Delete & re-draft",
"status.reply": "Respondre",
"status.replyAll": "Respondre a la conversacion",
"status.report": "Senhalar @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Tuts",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} ne charra other {people}} ne charran",
"trends.header": "Tendéncia actuala",
"trends.refresh": "Actualizar",
"ui.beforeunload": "Vòstre brolhon serà perdut se quitatz Mastodon.",
"upload_area.title": "Lisatz e depausatz per mandar",
"upload_button.label": "Ajustar un mèdia",

View File

@@ -87,6 +87,8 @@
"confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.",
"confirmations.mute.confirm": "Wycisz",
"confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?",
"confirmations.redraft.confirm": "Usuń i przeredaguj",
"confirmations.redraft.message": "Czy na pewno chcesz usunąć i przeredagować ten wpis? Utracisz wszystkie odpowiedzi, podbicia i polubienia dotyczące go.",
"confirmations.unfollow.confirm": "Przestań śledzić",
"confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?",
"embed.instructions": "Osadź ten wpis na swojej stronie wklejając poniższy kod.",
@@ -269,6 +271,7 @@
"status.reblog": "Podbij",
"status.reblog_private": "Podbij dla odbiorców oryginalnego wpisu",
"status.reblogged_by": "{name} podbił",
"status.redraft": "Usuń i przeredaguj",
"status.reply": "Odpowiedz",
"status.replyAll": "Odpowiedz na wątek",
"status.report": "Zgłoś @{name}",
@@ -289,8 +292,6 @@
"timeline.media": "Zawartość multimedialna",
"timeline.posts": "Wpisy",
"trends.count_by_accounts": "{count} {rawCount, plural, one {osoba rozmawia} few {osoby rozmawiają} other {osób rozmawia}} o tym",
"trends.header": "Na czasie",
"trends.refresh": "Odśwież",
"ui.beforeunload": "Utracisz tworzony wpis, jeżeli opuścisz Mastodona.",
"upload_area.title": "Przeciągnij i upuść aby wysłać",
"upload_button.label": "Dodaj zawartość multimedialną",

View File

@@ -59,7 +59,7 @@
"column_header.show_settings": "Mostrar configurações",
"column_header.unpin": "Desafixar",
"column_subheading.settings": "Configurações",
"compose_form.direct_message_warning": "Este toot só será enviado aos usuários mencionados. A mensagem não é encriptada e será armazenada nos servidores dos usuários mencionados.",
"compose_form.direct_message_warning": "Este toot só será enviado aos usuários mencionados.",
"compose_form.direct_message_warning_learn_more": "Saber mais",
"compose_form.hashtag_warning": "Esse toot não será listado em nenhuma hashtag por ser não listado. Somente toots públicos podem ser pesquisados por hashtag.",
"compose_form.lock_disclaimer": "A sua conta não está {locked}. Qualquer pessoa pode te seguir e visualizar postagens direcionadas a apenas seguidores.",
@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Você quer mesmo bloquear {domain} inteiro? Na maioria dos casos, silenciar ou bloquear alguns usuários é o suficiente e o recomendado.",
"confirmations.mute.confirm": "Silenciar",
"confirmations.mute.message": "Você tem certeza de que quer silenciar {name}?",
"confirmations.redraft.confirm": "Apagar & usar como rascunho",
"confirmations.redraft.message": "Você tem certeza que deseja apagar esse status e usá-lo como rascunho? Você vai perder todas as respostas, compartilhamentos e favoritos relacionados a ele.",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "Você tem certeza de que quer deixar de seguir {name}?",
"embed.instructions": "Incorpore esta postagem em seu site copiando o código abaixo.",
@@ -246,10 +248,10 @@
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Dê uma espiada...",
"status.block": "Block @{name}",
"status.cancel_reblog_private": "Retirar o compartilhamento",
"status.cancel_reblog_private": "Desfazer compartilhamento",
"status.cannot_reblog": "Esta postagem não pode ser compartilhada",
"status.delete": "Excluir",
"status.direct": "Enviar mensagem direta à @{name}",
"status.direct": "Enviar mensagem direta a @{name}",
"status.embed": "Incorporar",
"status.favourite": "Adicionar aos favoritos",
"status.load_more": "Carregar mais",
@@ -264,6 +266,7 @@
"status.reblog": "Compartilhar",
"status.reblog_private": "Compartilhar com a audiência original",
"status.reblogged_by": "{name} compartilhou",
"status.redraft": "Apagar & usar como rascunho",
"status.reply": "Responder",
"status.replyAll": "Responder à sequência",
"status.report": "Denunciar @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {pessoa} other {pessoas}} falando sobre",
"trends.header": "Hashtags do momento",
"trends.refresh": "Atualizar",
"ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "De certeza que queres bloquear por completo o domínio {domain}? Na maioria dos casos, silenciar ou bloquear alguns utilizadores é o suficiente e o recomendado.",
"confirmations.mute.confirm": "Silenciar",
"confirmations.mute.message": "De certeza que queres silenciar {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.message": "De certeza que queres deixar de seguir {name}?",
"embed.instructions": "Publicar este post num outro site copiando o código abaixo.",
@@ -264,6 +266,7 @@
"status.reblog": "Partilhar",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} partilhou",
"status.redraft": "Delete & re-draft",
"status.reply": "Responder",
"status.replyAll": "Responder à conversa",
"status.report": "Denunciar @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "O teu rascunho vai ser perdido se abandonares o Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Вы на самом деле уверены, что хотите блокировать весь {domain}? В большинстве случаев нескольких отдельных блокировок или глушений достаточно.",
"confirmations.mute.confirm": "Заглушить",
"confirmations.mute.message": "Вы уверены, что хотите заглушить {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Отписаться",
"confirmations.unfollow.message": "Вы уверены, что хотите отписаться от {name}?",
"embed.instructions": "Встройте этот статус на Вашем сайте, скопировав код внизу.",
@@ -264,6 +266,7 @@
"status.reblog": "Продвинуть",
"status.reblog_private": "Продвинуть для своей аудитории",
"status.reblogged_by": "{name} продвинул(а)",
"status.redraft": "Delete & re-draft",
"status.reply": "Ответить",
"status.replyAll": "Ответить на тред",
"status.report": "Пожаловаться",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Ваш черновик будет утерян, если вы покинете Mastodon.",
"upload_area.title": "Перетащите сюда, чтобы загрузить",
"upload_button.label": "Добавить медиаконтент",

View File

@@ -1,7 +1,7 @@
{
"account.badges.bot": "Bot",
"account.block": "Blokovať @{name}",
"account.block_domain": "Ukryť všetko z {domain}",
"account.block": "Blokuj @{name}",
"account.block_domain": "Ukry všetko z {domain}",
"account.blocked": "Blokovaný/á",
"account.direct": "Súkromná správa pre @{name}",
"account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.",
@@ -16,7 +16,7 @@
"account.mention": "Spomeň @{name}",
"account.moved_to": "{name} sa presunul/a na:",
"account.mute": "Ignorovať @{name}",
"account.mute_notifications": "Stĺmiť notifikácie od @{name}",
"account.mute_notifications": "Stĺmiť oznámenia od @{name}",
"account.muted": "Utíšený/á",
"account.posts": "Hlášky",
"account.posts_with_replies": "Príspevky s odpoveďami",
@@ -48,7 +48,7 @@
"column.home": "Domov",
"column.lists": "Zoznamy",
"column.mutes": "Ignorovaní užívatelia",
"column.notifications": "Notifikácie",
"column.notifications": "Oznámenia",
"column.pins": "Pripnuté tooty",
"column.public": "Federovaná časová os",
"column_back_button.label": "Späť",
@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Ste si naozaj istý, že chcete blokovať celú {domain}? Vo väčšine prípadov stačí blokovať alebo ignorovať daných používateľov, čiže to sa doporučuje.",
"confirmations.mute.confirm": "Ignoruj",
"confirmations.mute.message": "Naozaj chcete ignorovať {name}?",
"confirmations.redraft.confirm": "Vyčistiť a prepísať",
"confirmations.redraft.message": "Si si istý/á, že chceš vymazať a prepísať tento príspevok? Stratíš všetky jeho nadobudnuté odpovede, povýšenia a obľúbenia.",
"confirmations.unfollow.confirm": "Nesledovať",
"confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?",
"embed.instructions": "Umiestni kód uvedený nižšie pre pridanie tohto statusu na tvoju web stránku.",
@@ -107,11 +109,11 @@
"empty_column.home": "Vaša lokálna osa je zatiaľ prázdna! Pre začiatok pozrite {public} alebo použite vyhľadávanie a nájdite tak ostatných používateľov.",
"empty_column.home.public_timeline": "verejná časová os",
"empty_column.list": "Tento zoznam je ešte prázdny. Keď ale členovia tohoto zoznamu napíšu nové správy, tak tie sa objavia priamo tu.",
"empty_column.notifications": "Nemáte ešte žiadne notifikácie. Napíšte niekomu, následujte niekoho a komunikujte s ostatnými aby diskusia mohla začať.",
"empty_column.public": "Ešte tu nič nie je. Napíšte niečo verejne alebo začnite sledovať používateľov z iných Mastodon serverov aby tu niečo pribudlo",
"empty_column.notifications": "Nemáš ešte žiadne oznámenia. Zapoj sa s niekym do debaty a komunikuj s ostatnými aby diskusia mohla začať.",
"empty_column.public": "Ešte tu nič nie je. Napíš niečo verejne alebo začnite sledovať používateľov z iných Mastodon serverov aby tu niečo pribudlo",
"follow_request.authorize": "Povoľ prístup",
"follow_request.reject": "Odmietni",
"getting_started.documentation": "Documentation",
"getting_started.documentation": "Dokumentácia",
"getting_started.heading": "Začni tu",
"getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispieť môžeš na GitHube v {github}.",
"getting_started.terms": "Podmienky prevozu",
@@ -166,9 +168,9 @@
"navigation_bar.info": "O tomto Mastodon serveri",
"navigation_bar.keyboard_shortcuts": "Klávesové skratky",
"navigation_bar.lists": "Zoznamy",
"navigation_bar.logout": "Odhlás",
"navigation_bar.logout": "Odhlás sa",
"navigation_bar.mutes": "Ignorovaní užívatelia",
"navigation_bar.personal": "Personal",
"navigation_bar.personal": "Osobné",
"navigation_bar.pins": "Pripnuté tooty",
"navigation_bar.preferences": "Voľby",
"navigation_bar.public_timeline": "Federovaná časová os",
@@ -246,7 +248,7 @@
"search_results.total": "{count, number} {count, plural, jeden {výsledok} ostatné {výsledky}}",
"standalone.public_title": "Náhľad dovnútra...",
"status.block": "Blokovať @{name}",
"status.cancel_reblog_private": "Unboost",
"status.cancel_reblog_private": "Nezdieľaj",
"status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
"status.delete": "Zmazať",
"status.direct": "Súkromná správa @{name}",
@@ -264,6 +266,7 @@
"status.reblog": "Povýšiť",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} povýšil/a",
"status.redraft": "Vymaž a prepíš",
"status.reply": "Odpovedať",
"status.replyAll": "Odpovedať na diskusiu",
"status.report": "Nahlásiť @{name}",
@@ -281,13 +284,11 @@
"tabs_bar.local_timeline": "Lokálna",
"tabs_bar.notifications": "Notifikácie",
"tabs_bar.search": "Hľadaj",
"timeline.media": "Media",
"timeline.media": "Médiá",
"timeline.posts": "Príspevky",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Čo máte rozpísané sa stratí, ak opustíte Mastodon.",
"upload_area.title": "Ťahaj a pusti pre nahratie",
"trends.count_by_accounts": "{count} {rawCount, viacerí, jeden {person} iní {people}} diskutujú",
"ui.beforeunload": "Čo máš rozpísané sa stratí, ak opustíš Mastodon.",
"upload_area.title": "Pretiahni a pusť pre nahratie",
"upload_button.label": "Pridať médiá",
"upload_form.description": "Opis pre slabo vidiacich",
"upload_form.focus": "Vystrihni",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Ali ste res, res prepričani, da želite blokirati celotno {domain}? V večini primerov je nekaj ciljnih blokiranj ali utišanj dovolj in boljše.",
"confirmations.mute.confirm": "Utišanje",
"confirmations.mute.message": "Ali ste prepričani, da želite utišati {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Prenehaj slediti",
"confirmations.unfollow.message": "Ali ste prepričani, da ne želite več slediti {name}?",
"embed.instructions": "Vstavi ta status na svojo spletno stran tako, da kopirate spodnjo kodo.",
@@ -264,6 +266,7 @@
"status.reblog": "Suni",
"status.reblog_private": "Suni v prvotno občinstvo",
"status.reblogged_by": "{name} sunjen",
"status.redraft": "Delete & re-draft",
"status.reply": "Odgovori",
"status.replyAll": "Odgovori na objavo",
"status.report": "Prijavi @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Vaš osnutek bo izgubljen, če zapustite Mastodona.",
"upload_area.title": "Povlecite in spustite za pošiljanje",
"upload_button.label": "Dodaj medij",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Da li ste stvarno, stvarno sigurno da želite da blokirate ceo domen {domain}? U većini slučajeva, par dobrih blokiranja ili ućutkavanja su dovoljna i preporučljiva.",
"confirmations.mute.confirm": "Ućutkaj",
"confirmations.mute.message": "Da li stvarno želite da ućutkate korisnika {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Otprati",
"confirmations.unfollow.message": "Da li ste sigurni da želite da otpratite korisnika {name}?",
"embed.instructions": "Ugradi ovaj status na Vaš veb sajt kopiranjem koda ispod.",
@@ -264,6 +266,7 @@
"status.reblog": "Podrži",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} podržao(la)",
"status.redraft": "Delete & re-draft",
"status.reply": "Odgovori",
"status.replyAll": "Odgovori na diskusiju",
"status.report": "Prijavi korisnika @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Ako napustite Mastodont, izgubićete napisani nacrt.",
"upload_area.title": "Prevucite ovde da otpremite",
"upload_button.label": "Dodaj multimediju",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Да ли сте стварно, стварно сигурно да желите да блокирате цео домен {domain}? У већини случајева, пар добрих блокирања или ућуткавања су довољна и препоручљива.",
"confirmations.mute.confirm": "Ућуткај",
"confirmations.mute.message": "Да ли стварно желите да ућуткате корисника {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Отпрати",
"confirmations.unfollow.message": "Да ли сте сигурни да желите да отпратите корисника {name}?",
"embed.instructions": "Угради овај статус на Ваш веб сајт копирањем кода испод.",
@@ -264,6 +266,7 @@
"status.reblog": "Подржи",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} подржао(ла)",
"status.redraft": "Delete & re-draft",
"status.reply": "Одговори",
"status.replyAll": "Одговори на дискусију",
"status.report": "Пријави корисника @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Ако напустите Мастодонт, изгубићете написани нацрт.",
"upload_area.title": "Превуците овде да отпремите",
"upload_button.label": "Додај мултимедију",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Är du verkligen, verkligen säker på att du vill blockera hela {domain}? I de flesta fall är några riktade blockeringar eller nedtystade tillräckligt och föredras.",
"confirmations.mute.confirm": "Tysta",
"confirmations.mute.message": "Är du säker du vill tysta ner {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Sluta följa",
"confirmations.unfollow.message": "Är du säker på att du vill sluta följa {name}?",
"embed.instructions": "Bädda in den här statusen på din webbplats genom att kopiera koden nedan.",
@@ -264,6 +266,7 @@
"status.reblog": "Knuff",
"status.reblog_private": "Knuffa till de ursprungliga åhörarna",
"status.reblogged_by": "{name} knuffade",
"status.redraft": "Delete & re-draft",
"status.reply": "Svara",
"status.replyAll": "Svara på tråden",
"status.report": "Rapportera @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Ditt utkast kommer att förloras om du lämnar Mastodon.",
"upload_area.title": "Dra & släpp för att ladda upp",
"upload_button.label": "Lägg till media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boosted",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Sessize al",
"confirmations.mute.message": "{name} kullanıcısını sessize almak istiyor musunuz?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Boost'la",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} boost etti",
"status.redraft": "Delete & re-draft",
"status.reply": "Cevapla",
"status.replyAll": "Konuşmayı cevapla",
"status.report": "@{name}'i raporla",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Upload için sürükle bırak yapınız",
"upload_button.label": "Görsel ekle",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "Ви точно, точно впевнені, що хочете заблокувати весь домен {domain}? У більшості випадків для нормальної роботи краще заблокувати/заглушити лише деяких користувачів.",
"confirmations.mute.confirm": "Заглушити",
"confirmations.mute.message": "Ви впевнені, що хочете заглушити {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
@@ -264,6 +266,7 @@
"status.reblog": "Передмухнути",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} передмухнув(-ла)",
"status.redraft": "Delete & re-draft",
"status.reply": "Відповісти",
"status.replyAll": "Відповісти на тред",
"status.report": "Поскаржитися",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Перетягніть сюди, щоб завантажити",
"upload_button.label": "Додати медіаконтент",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "你真的确定要隐藏所有来自 {domain} 的内容吗?多数情况下,屏蔽或隐藏几个特定的用户应该就能满足你的需要了。",
"confirmations.mute.confirm": "隐藏",
"confirmations.mute.message": "你确定要隐藏 {name} 吗?",
"confirmations.redraft.confirm": "删除并重新编辑",
"confirmations.redraft.message": "你确定要删除这条嘟文并重新编辑它吗?所有相关的回复、转嘟和收藏都会被清除。",
"confirmations.unfollow.confirm": "取消关注",
"confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
"embed.instructions": "要在你的网站上嵌入这条嘟文,请复制以下代码。",
@@ -111,10 +113,10 @@
"empty_column.public": "这里神马都没有!写一些公开的嘟文,或者关注其他实例的用户后,这里就会有嘟文出现了哦!",
"follow_request.authorize": "同意",
"follow_request.reject": "拒绝",
"getting_started.documentation": "Documentation",
"getting_started.documentation": "文档",
"getting_started.heading": "开始使用",
"getting_started.open_source_notice": "Mastodon 是一个开源软件。欢迎前往 GitHub{github})贡献代码或反馈问题。",
"getting_started.terms": "Terms of service",
"getting_started.terms": "使用条款",
"home.column_settings.advanced": "高级设置",
"home.column_settings.basic": "基本设置",
"home.column_settings.filter_regex": "使用正则表达式regex过滤",
@@ -158,7 +160,7 @@
"navigation_bar.blocks": "已屏蔽的用户",
"navigation_bar.community_timeline": "本站时间轴",
"navigation_bar.direct": "私信",
"navigation_bar.discover": "Discover",
"navigation_bar.discover": "发现",
"navigation_bar.domain_blocks": "已屏蔽的网站",
"navigation_bar.edit_profile": "修改个人资料",
"navigation_bar.favourites": "收藏的内容",
@@ -168,11 +170,11 @@
"navigation_bar.lists": "列表",
"navigation_bar.logout": "注销",
"navigation_bar.mutes": "已隐藏的用户",
"navigation_bar.personal": "Personal",
"navigation_bar.personal": "个人",
"navigation_bar.pins": "置顶嘟文",
"navigation_bar.preferences": "首选项",
"navigation_bar.public_timeline": "跨站公共时间轴",
"navigation_bar.security": "Security",
"navigation_bar.security": "安全",
"notification.favourite": "{name} 收藏了你的嘟文",
"notification.follow": "{name} 开始关注你",
"notification.mention": "{name} 提及你",
@@ -264,6 +266,7 @@
"status.reblog": "转嘟",
"status.reblog_private": "转嘟给原有关注者",
"status.reblogged_by": "{name} 转嘟了",
"status.redraft": "删除并重新编辑",
"status.reply": "回复",
"status.replyAll": "回复所有人",
"status.report": "举报 @{name}",
@@ -283,9 +286,7 @@
"tabs_bar.search": "搜索",
"timeline.media": "媒体",
"timeline.posts": "嘟文",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"trends.count_by_accounts": "{count} 人正在讨论",
"ui.beforeunload": "如果你现在离开 Mastodon你的草稿内容将会被丢弃。",
"upload_area.title": "将文件拖放到此处开始上传",
"upload_button.label": "上传媒体文件",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或靜音幾個特定目標就好。",
"confirmations.mute.confirm": "靜音",
"confirmations.mute.message": "你確定要將{name}靜音嗎?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "取消關注",
"confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?",
"embed.instructions": "要內嵌此文章,請將以下代碼貼進你的網站。",
@@ -264,6 +266,7 @@
"status.reblog": "轉推",
"status.reblog_private": "轉推到原讀者",
"status.reblogged_by": "{name} 轉推",
"status.redraft": "Delete & re-draft",
"status.reply": "回應",
"status.replyAll": "回應所有人",
"status.report": "舉報 @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "文章",
"trends.count_by_accounts": "{count} 位用戶在討論",
"trends.header": "現時趨勢",
"trends.refresh": "重新載入",
"ui.beforeunload": "如果你現在離開 Mastodon你的草稿內容將會被丟棄。",
"upload_area.title": "將檔案拖放至此上載",
"upload_button.label": "上載媒體檔案",

View File

@@ -83,6 +83,8 @@
"confirmations.domain_block.message": "你真的真的確定要隱藏整個 {domain} ?多數情況下,比較推薦封鎖或消音幾個特定目標就好。",
"confirmations.mute.confirm": "消音",
"confirmations.mute.message": "你確定要消音 {name} ",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "取消關注",
"confirmations.unfollow.message": "真的不要繼續關注 {name} 了嗎?",
"embed.instructions": "要內嵌此貼文,請將以下代碼貼進你的網站。",
@@ -264,6 +266,7 @@
"status.reblog": "轉推",
"status.reblog_private": "Boost to original audience",
"status.reblogged_by": "{name} 轉推了",
"status.redraft": "Delete & re-draft",
"status.reply": "回應",
"status.replyAll": "回應這串",
"status.report": "通報 @{name}",
@@ -284,8 +287,6 @@
"timeline.media": "Media",
"timeline.posts": "Toots",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"trends.header": "Trending now",
"trends.refresh": "Refresh",
"ui.beforeunload": "如果離開 Mastodon你的草稿將會不見。",
"upload_area.title": "拖放來上傳",
"upload_button.label": "增加媒體",

View File

@@ -32,9 +32,11 @@ import {
} from '../actions/compose';
import { TIMELINE_DELETE } from '../actions/timelines';
import { STORE_HYDRATE } from '../actions/store';
import { REDRAFT } from '../actions/statuses';
import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet, fromJS } from 'immutable';
import uuid from '../uuid';
import { me } from '../initial_state';
import { unescapeHTML } from '../utils/html';
const initialState = ImmutableMap({
mounted: 0,
@@ -170,6 +172,18 @@ const hydrate = (state, hydratedState) => {
return state;
};
const domParser = new DOMParser();
const expandMentions = status => {
const fragment = domParser.parseFromString(status.get('content'), 'text/html').documentElement;
status.get('mentions').forEach(mention => {
fragment.querySelector(`a[href="${mention.get('url')}"]`).textContent = `@${mention.get('acct')}`;
});
return fragment.innerHTML;
};
export default function compose(state = initialState, action) {
switch(action.type) {
case STORE_HYDRATE:
@@ -301,6 +315,24 @@ export default function compose(state = initialState, action) {
return item;
}));
case REDRAFT:
return state.withMutations(map => {
map.set('text', unescapeHTML(expandMentions(action.status)));
map.set('in_reply_to', action.status.get('in_reply_to_id'));
map.set('privacy', action.status.get('visibility'));
map.set('media_attachments', action.status.get('media_attachments'));
map.set('focusDate', new Date());
map.set('caretPosition', null);
map.set('idempotencyKey', uuid());
if (action.status.get('spoiler_text').length > 0) {
map.set('spoiler', true);
map.set('spoiler_text', action.status.get('spoiler_text'));
} else {
map.set('spoiler', false);
map.set('spoiler_text', '');
}
});
default:
return state;
}

View File

@@ -26,7 +26,6 @@ import height_cache from './height_cache';
import custom_emojis from './custom_emojis';
import lists from './lists';
import listEditor from './list_editor';
import trends from './trends';
const reducers = {
dropdown_menu,
@@ -56,7 +55,6 @@ const reducers = {
custom_emojis,
lists,
listEditor,
trends,
};
export default combineReducers(reducers);

View File

@@ -1,23 +0,0 @@
import { TRENDS_FETCH_REQUEST, TRENDS_FETCH_SUCCESS, TRENDS_FETCH_FAIL } from '../actions/trends';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
const initialState = ImmutableMap({
items: ImmutableList(),
isLoading: false,
});
export default function trendsReducer(state = initialState, action) {
switch(action.type) {
case TRENDS_FETCH_REQUEST:
return state.set('isLoading', true);
case TRENDS_FETCH_SUCCESS:
return state.withMutations(map => {
map.set('items', fromJS(action.trends));
map.set('isLoading', false);
});
case TRENDS_FETCH_FAIL:
return state.set('isLoading', false);
default:
return state;
}
};

View File

@@ -1,6 +1,5 @@
export const unescapeHTML = (html) => {
const wrapper = document.createElement('div');
html = html.replace(/<br \/>|<br>|\n/g, ' ');
wrapper.innerHTML = html;
wrapper.innerHTML = html.replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n').replace(/<[^>]*>/g, '');
return wrapper.textContent;
};

View File

@@ -0,0 +1,10 @@
import React, { Fragment } from 'react';
import { FormattedNumber } from 'react-intl';
export const shortNumberFormat = number => {
if (number < 1000) {
return <FormattedNumber value={number} />;
} else {
return <Fragment><FormattedNumber value={number / 1000} maximumFractionDigits={1} />K</Fragment>;
}
};

View File

@@ -26,20 +26,20 @@
}
.compose-form .compose-form__modifiers .compose-form__upload__actions .icon-button {
color: $ui-base-color;
color: lighten($white, 7%);
&:active,
&:focus,
&:hover {
color: darken($ui-base-color, 7%);
color: $white;
}
}
.compose-form .compose-form__modifiers .compose-form__upload-description input {
color: $ui-base-color;
color: lighten($white, 7%);
&::placeholder {
color: $ui-base-color;
color: lighten($white, 7%);
}
}
@@ -47,6 +47,19 @@
background: darken($ui-base-color, 6%);
}
.emoji-mart-bar {
border-color: lighten($ui-base-color, 8%);
&:first-child {
background: $ui-base-color;
}
}
.emoji-mart-search input {
background: rgba($ui-base-color, 0.3);
border-color: $ui-base-color;
}
.focusable:focus {
background: $ui-base-color;
}
@@ -74,6 +87,17 @@
}
}
// Change the background colors of media and video spoiler
.media-spoiler,
.video-player__spoiler {
background: $ui-base-color;
}
.account-gallery__item a {
background-color: $ui-base-color;
}
// Change the colors used in the dropdown menu
.dropdown-menu {
background: $ui-base-color;
@@ -100,7 +124,7 @@
.dropdown-menu__item {
a {
background: $ui-base-color;
color: $ui-secondary-color;
color: $darker-text-color;
}
}
@@ -189,17 +213,18 @@
// Change the default colors used on some parts of the profile pages
.activity-stream-tabs {
background: $account-background-color;
a {
&.active {
color: $ui-primary-color;
}
}
border-bottom-color: lighten($ui-base-color, 8%);
}
.activity-stream {
.entry {
background: $account-background-color;
.detailed-status.light,
.more.light,
.status.light {
border-bottom-color: lighten($ui-base-color, 8%);
}
}
.status.light {
@@ -219,7 +244,7 @@
.account-grid-card {
.controls {
.icon-button {
color: $ui-secondary-color;
color: $darker-text-color;
}
}
@@ -230,7 +255,7 @@
}
.username {
color: $ui-secondary-color;
color: $darker-text-color;
}
.account__header__content {

View File

@@ -4555,7 +4555,7 @@ a.status-card {
height: 100%;
z-index: 4;
border: 0;
background: $base-shadow-color;
background: $base-overlay-background;
color: $darker-text-color;
transition: none;
pointer-events: none;

View File

@@ -62,16 +62,16 @@
}
.emoji-mart-anchor-bar {
bottom: 0;
bottom: -1px;
}
}
.emoji-mart-anchor-bar {
position: absolute;
bottom: -3px;
bottom: -5px;
left: 0;
width: 100%;
height: 3px;
height: 4px;
background-color: $highlight-text-color;
}

View File

@@ -1,6 +1,7 @@
.footer {
text-align: center;
margin-top: 30px;
padding-bottom: 60px;
font-size: 12px;
color: $darker-text-color;

View File

@@ -195,6 +195,7 @@ a.table-action-link {
font-weight: 700;
background: linear-gradient(to right, orange , yellow, green, cyan, blue, violet,orange , yellow, green, cyan, blue, violet);
background-size: 200% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: Swag 2s linear 0s infinite;

View File

@@ -6,6 +6,11 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.requested?(target_account)
if target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain)
reject_follow_request!(target_account)
return
end
# Fast-forward repeat follow requests
if @account.following?(target_account)
AuthorizeFollowService.new.call(@account, target_account, skip_follow_request: true)
@@ -21,4 +26,9 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
NotifyService.new.call(target_account, ::Follow.find_by(account: @account, target_account: target_account))
end
end
def reject_follow_request!(target_account)
json = Oj.dump(ActivityPub::LinkedDataSignature.new(ActiveModelSerializers::SerializableResource.new(FollowRequest.new(account: @account, target_account: target_account, uri: @json['id']), serializer: ActivityPub::RejectFollowSerializer, adapter: ActivityPub::Adapter).as_json).sign!(target_account))
ActivityPub::DeliveryWorker.perform_async(json, target_account.id, @account.inbox_url)
end
end

View File

@@ -153,7 +153,7 @@ class FeedManager
def filter_from_home?(status, receiver_id)
return false if receiver_id == status.account_id
return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
return true if keyword_filter?(status, receiver_id)
return true if keyword_filter_from_home?(status, receiver_id)
check_for_mutes = [status.account_id]
check_for_mutes.concat(status.mentions.pluck(:account_id))
@@ -182,8 +182,24 @@ class FeedManager
false
end
def keyword_filter?(status, receiver_id)
Glitch::KeywordMuteHelper.new(receiver_id).matches?(status)
def keyword_filter_from_home?(status, receiver_id)
# If this status mentions the receiver, use the mentions scope: it's
# possible that the status will show up in the receiver's mentions, which
# means it ought to show up in the home feed as well.
#
# If it doesn't mention the receiver but is still headed for the home feed,
# use the home feed scope.
scope = if status.mentions.pluck(:account_id).include?(receiver_id)
Glitch::KeywordMute::Scopes::Mentions
else
Glitch::KeywordMute::Scopes::HomeFeed
end
return true if keyword_filter?(status, receiver_id, scope)
end
def keyword_filter?(status, receiver_id, scope)
Glitch::KeywordMuteHelper.new(receiver_id).matches?(status, scope)
end
def filter_from_mentions?(status, receiver_id)
@@ -197,7 +213,7 @@ class FeedManager
should_filter = blocks_or_mutes?(receiver_id, check_for_blocks, :mentions) # Filter if it's from someone I blocked, in reply to someone I blocked, or mentioning someone I blocked (or muted)
should_filter ||= (status.account.silenced? && !Follow.where(account_id: receiver_id, target_account_id: status.account_id).exists?) # of if the account is silenced and I'm not following them
should_filter ||= keyword_filter?(status, receiver_id) # or if the mention contains a muted keyword
should_filter ||= keyword_filter?(status, receiver_id, Glitch::KeywordMute::Scopes::Mentions) # or if the mention contains a muted keyword
should_filter
end

View File

@@ -3,11 +3,11 @@
#
# Table name: bookmarks
#
# id :integer not null, primary key
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# status_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
# account_id :integer not null
# status_id :integer not null
#
class Bookmark < ApplicationRecord

View File

@@ -24,14 +24,17 @@ module Remotable
Request.new(:get, url).perform do |response|
next if response.code != 200
matches = response.headers['content-disposition']&.match(/filename="([^"]*)"/)
filename = matches.nil? ? parsed_url.path.split('/').last : matches[1]
content_type = parse_content_type(response.headers.get('content-type').last)
extname = detect_extname_from_content_type(content_type)
if extname.nil?
disposition = response.headers.get('content-disposition').last
matches = disposition&.match(/filename="([^"]*)"/)
filename = matches.nil? ? parsed_url.path.split('/').last : matches[1]
extname = filename.nil? ? '' : File.extname(filename)
end
basename = SecureRandom.hex(8)
extname = if filename.nil?
''
else
File.extname(filename)
end
send("#{attachment_name}=", StringIO.new(response.body_with_limit(limit)))
send("#{attachment_name}_file_name=", basename + extname)
@@ -57,4 +60,26 @@ module Remotable
end
end
end
private
def detect_extname_from_content_type(content_type)
return if content_type.nil?
type = MIME::Types[content_type].first
return if type.nil?
extname = type.extensions.first
return if extname.nil?
".#{extname}"
end
def parse_content_type(content_type)
return if content_type.nil?
content_type.split(/\s*;\s*/).first
end
end

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