Merge remote-tracking branch 'upstream/main'
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
Dalite 2023-11-19 02:41:47 +01:00
commit 2c4f8b71cb
305 changed files with 5080 additions and 2949 deletions

View file

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

13
.github/codecov.yml vendored Normal file
View file

@ -0,0 +1,13 @@
coverage:
status:
project:
default:
# Github status check is not blocking
informational: true
patch:
default:
# Github status check is not blocking
informational: true
comment:
# Only write a comment in PR if there are changes
require_changes: true

View file

@ -94,7 +94,7 @@ jobs:
DB_HOST: localhost DB_HOST: localhost
DB_USER: postgres DB_USER: postgres
DB_PASS: postgres DB_PASS: postgres
DISABLE_SIMPLECOV: true DISABLE_SIMPLECOV: ${{ matrix.ruby-version != '.ruby-version' }}
RAILS_ENV: test RAILS_ENV: test
ALLOW_NOPAM: true ALLOW_NOPAM: true
PAM_ENABLED: true PAM_ENABLED: true
@ -137,6 +137,12 @@ jobs:
- run: bin/rspec - run: bin/rspec
- name: Upload coverage reports to Codecov
if: matrix.ruby-version == '.ruby-version'
uses: codecov/codecov-action@v3
with:
files: coverage/lcov/mastodon.lcov
test-e2e: test-e2e:
name: End to End testing name: End to End testing
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -221,7 +227,7 @@ jobs:
path: tmp/screenshots/ path: tmp/screenshots/
test-search: test-search:
name: Testing search name: Elastic Search integration testing
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
@ -308,7 +314,7 @@ jobs:
- name: Load database schema - name: Load database schema
run: './bin/rails db:create db:schema:load db:seed' run: './bin/rails db:create db:schema:load db:seed'
- run: bundle exec rake spec:search - run: bin/rspec --tag search
- name: Archive logs - name: Archive logs
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

View file

@ -41,23 +41,6 @@ Metrics/CyclomaticComplexity:
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 27 Max: 27
RSpec/AnyInstance:
Exclude:
- 'spec/controllers/activitypub/inboxes_controller_spec.rb'
- 'spec/controllers/admin/accounts_controller_spec.rb'
- 'spec/controllers/admin/resets_controller_spec.rb'
- 'spec/controllers/auth/sessions_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb'
- 'spec/controllers/settings/two_factor_authentication/recovery_codes_controller_spec.rb'
- 'spec/lib/request_spec.rb'
- 'spec/lib/status_filter_spec.rb'
- 'spec/models/account_spec.rb'
- 'spec/models/setting_spec.rb'
- 'spec/services/activitypub/process_collection_service_spec.rb'
- 'spec/validators/follow_limit_validator_spec.rb'
- 'spec/workers/activitypub/delivery_worker_spec.rb'
- 'spec/workers/web/push_notification_worker_spec.rb'
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
Max: 22 Max: 22

22
.simplecov Normal file
View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
if ENV['CI']
require 'simplecov-lcov'
SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
else
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
end
SimpleCov.start 'rails' do
enable_coverage :branch
add_filter 'lib/linter'
add_group 'Libraries', 'lib'
add_group 'Policies', 'app/policies'
add_group 'Presenters', 'app/presenters'
add_group 'Serializers', 'app/serializers'
add_group 'Services', 'app/services'
add_group 'Validators', 'app/validators'
end

3
.watchmanconfig Normal file
View file

@ -0,0 +1,3 @@
{
"ignore_dirs": ["node_modules/", "public/"]
}

View file

@ -38,6 +38,7 @@ RUN apt-get update && \
corepack enable corepack enable
COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/ COPY Gemfile* package.json yarn.lock .yarnrc.yml /opt/mastodon/
COPY streaming/package.json /opt/mastodon/streaming/
COPY .yarn /opt/mastodon/.yarn COPY .yarn /opt/mastodon/.yarn
RUN bundle install -j"$(nproc)" RUN bundle install -j"$(nproc)"

View file

@ -109,6 +109,9 @@ group :test do
# RSpec progress bar formatter # RSpec progress bar formatter
gem 'fuubar', '~> 2.5' gem 'fuubar', '~> 2.5'
# RSpec helpers for email specs
gem 'email_spec'
# Extra RSpec extenion methods and helpers for sidekiq # Extra RSpec extenion methods and helpers for sidekiq
gem 'rspec-sidekiq', '~> 4.0' gem 'rspec-sidekiq', '~> 4.0'
@ -139,6 +142,7 @@ group :test do
# Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false # Coverage formatter for RSpec test if DISABLE_SIMPLECOV is false
gem 'simplecov', '~> 0.22', require: false gem 'simplecov', '~> 0.22', require: false
gem 'simplecov-lcov', '~> 0.8', require: false
# Stub web requests for specs # Stub web requests for specs
gem 'webmock', '~> 3.18' gem 'webmock', '~> 3.18'

View file

@ -39,50 +39,51 @@ GIT
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.1.1) actioncable (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6) zeitwerk (~> 2.6)
actionmailbox (7.1.1) actionmailbox (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
activejob (= 7.1.1) activejob (= 7.1.2)
activerecord (= 7.1.1) activerecord (= 7.1.2)
activestorage (= 7.1.1) activestorage (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.1.1) actionmailer (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
actionview (= 7.1.1) actionview (= 7.1.2)
activejob (= 7.1.1) activejob (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
actionpack (7.1.1) actionpack (7.1.2)
actionview (= 7.1.1) actionview (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4) rack (>= 2.2.4)
rack-session (>= 1.0.1) rack-session (>= 1.0.1)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6) rails-html-sanitizer (~> 1.6)
actiontext (7.1.1) actiontext (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
activerecord (= 7.1.1) activerecord (= 7.1.2)
activestorage (= 7.1.1) activestorage (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.1.1) actionview (7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.11) erubi (~> 1.11)
rails-dom-testing (~> 2.2) rails-dom-testing (~> 2.2)
@ -92,22 +93,22 @@ GEM
activemodel (>= 4.1) activemodel (>= 4.1)
case_transform (>= 0.2) case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.3) jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
activejob (7.1.1) activejob (7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.1.1) activemodel (7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
activerecord (7.1.1) activerecord (7.1.2)
activemodel (= 7.1.1) activemodel (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
timeout (>= 0.4.0) timeout (>= 0.4.0)
activestorage (7.1.1) activestorage (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
activejob (= 7.1.1) activejob (= 7.1.2)
activerecord (= 7.1.1) activerecord (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
marcel (~> 1.0) marcel (~> 1.0)
activesupport (7.1.1) activesupport (7.1.2)
base64 base64
bigdecimal bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
@ -218,7 +219,7 @@ GEM
activerecord (>= 5.a) activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0) database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1) database_cleaner-core (2.0.1)
date (3.3.3) date (3.3.4)
debug_inspector (1.1.0) debug_inspector (1.1.0)
devise (4.9.3) devise (4.9.3)
bcrypt (~> 3.0) bcrypt (~> 3.0)
@ -259,6 +260,10 @@ GEM
elasticsearch-transport (7.13.3) elasticsearch-transport (7.13.3)
faraday (~> 1) faraday (~> 1)
multi_json multi_json
email_spec (2.2.2)
htmlentities (~> 4.3.3)
launchy (~> 2.1)
mail (~> 2.7)
encryptor (3.0.0) encryptor (3.0.0)
erubi (1.12.0) erubi (1.12.0)
et-orbi (1.2.7) et-orbi (1.2.7)
@ -369,7 +374,7 @@ GEM
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
idn-ruby (0.1.5) idn-ruby (0.1.5)
io-console (0.6.0) io-console (0.6.0)
irb (1.8.1) irb (1.8.3)
rdoc rdoc
reline (>= 0.3.8) reline (>= 0.3.8)
jmespath (1.6.2) jmespath (1.6.2)
@ -462,13 +467,13 @@ GEM
uri uri
net-http-persistent (4.0.2) net-http-persistent (4.0.2)
connection_pool (~> 2.2) connection_pool (~> 2.2)
net-imap (0.4.1) net-imap (0.4.4)
date date
net-protocol net-protocol
net-ldap (0.18.0) net-ldap (0.18.0)
net-pop (0.1.2) net-pop (0.1.2)
net-protocol net-protocol
net-protocol (0.2.1) net-protocol (0.2.2)
timeout timeout
net-smtp (0.4.0) net-smtp (0.4.0)
net-protocol net-protocol
@ -526,7 +531,7 @@ GEM
net-smtp net-smtp
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
private_address_check (0.5.0) private_address_check (0.5.0)
psych (5.1.1) psych (5.1.1.1)
stringio stringio
public_suffix (5.0.3) public_suffix (5.0.3)
puma (6.4.0) puma (6.4.0)
@ -557,20 +562,20 @@ GEM
rackup (1.0.0) rackup (1.0.0)
rack (< 3) rack (< 3)
webrick webrick
rails (7.1.1) rails (7.1.2)
actioncable (= 7.1.1) actioncable (= 7.1.2)
actionmailbox (= 7.1.1) actionmailbox (= 7.1.2)
actionmailer (= 7.1.1) actionmailer (= 7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
actiontext (= 7.1.1) actiontext (= 7.1.2)
actionview (= 7.1.1) actionview (= 7.1.2)
activejob (= 7.1.1) activejob (= 7.1.2)
activemodel (= 7.1.1) activemodel (= 7.1.2)
activerecord (= 7.1.1) activerecord (= 7.1.2)
activestorage (= 7.1.1) activestorage (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.1.1) railties (= 7.1.2)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
@ -585,9 +590,9 @@ GEM
rails-i18n (7.0.8) rails-i18n (7.0.8)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8) railties (>= 6.0.0, < 8)
railties (7.1.1) railties (7.1.2)
actionpack (= 7.1.1) actionpack (= 7.1.2)
activesupport (= 7.1.1) activesupport (= 7.1.2)
irb irb
rackup (>= 1.0.0) rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
@ -724,6 +729,7 @@ GEM
simplecov-html (~> 0.11) simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1) simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3) simplecov-html (0.12.3)
simplecov-lcov (0.8.0)
simplecov_json_formatter (0.1.4) simplecov_json_formatter (0.1.4)
smart_properties (1.17.0) smart_properties (1.17.0)
sprockets (3.7.2) sprockets (3.7.2)
@ -737,7 +743,7 @@ GEM
statsd-ruby (1.5.0) statsd-ruby (1.5.0)
stoplight (3.0.2) stoplight (3.0.2)
redlock (~> 1.0) redlock (~> 1.0)
stringio (3.0.8) stringio (3.0.9)
strong_migrations (1.6.4) strong_migrations (1.6.4)
activerecord (>= 5.2) activerecord (>= 5.2)
swd (1.3.0) swd (1.3.0)
@ -753,7 +759,7 @@ GEM
test-prof (1.2.3) test-prof (1.2.3)
thor (1.3.0) thor (1.3.0)
tilt (2.3.0) tilt (2.3.0)
timeout (0.4.0) timeout (0.4.1)
tpm-key_attestation (0.12.0) tpm-key_attestation (0.12.0)
bindata (~> 2.4) bindata (~> 2.4)
openssl (> 2.0) openssl (> 2.0)
@ -851,6 +857,7 @@ DEPENDENCIES
doorkeeper (~> 5.6) doorkeeper (~> 5.6)
dotenv-rails (~> 2.8) dotenv-rails (~> 2.8)
ed25519 (~> 1.3) ed25519 (~> 1.3)
email_spec
fabrication (~> 2.30) fabrication (~> 2.30)
faker (~> 3.2) faker (~> 3.2)
fast_blank (~> 1.0) fast_blank (~> 1.0)
@ -935,6 +942,7 @@ DEPENDENCIES
simple-navigation (~> 4.4) simple-navigation (~> 4.4)
simple_form (~> 5.2) simple_form (~> 5.2)
simplecov (~> 0.22) simplecov (~> 0.22)
simplecov-lcov (~> 0.8)
sprockets (~> 3.7.2) sprockets (~> 3.7.2)
sprockets-rails (~> 3.4) sprockets-rails (~> 3.4)
stackprof stackprof

View file

@ -1,4 +1,4 @@
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn run start stream: env PORT=4000 yarn workspace @mastodon/streaming start
webpack: bin/webpack-dev-server webpack: bin/webpack-dev-server

View file

@ -53,7 +53,7 @@ class PublicStatusesIndex < Chewy::Index
index_scope ::Status.unscoped index_scope ::Status.unscoped
.kept .kept
.indexable .indexable
.includes(:media_attachments, :preloadable_poll, :preview_cards, :tags) .includes(:media_attachments, :preloadable_poll, :tags, preview_cards_status: :preview_card)
root date_detection: false do root date_detection: false do
field(:id, type: 'long') field(:id, type: 'long')

View file

@ -50,7 +50,7 @@ class StatusesIndex < Chewy::Index
}, },
} }
index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :preview_cards, :local_mentioned, :local_favorited, :local_reblogged, :local_bookmarked, :tags, preloadable_poll: :local_voters), delete_if: ->(status) { status.searchable_by.empty? } index_scope ::Status.unscoped.kept.without_reblogs.includes(:media_attachments, :local_mentioned, :local_favorited, :local_reblogged, :local_bookmarked, :tags, preview_cards_status: :preview_card, preloadable_poll: :local_voters), delete_if: ->(status) { status.searchable_by.empty? }
root date_detection: false do root date_detection: false do
field(:id, type: 'long') field(:id, type: 'long')

View file

@ -7,6 +7,7 @@ class Api::BaseController < ApplicationController
include RateLimitHeaders include RateLimitHeaders
include AccessTokenTrackingConcern include AccessTokenTrackingConcern
include ApiCachingConcern include ApiCachingConcern
include Api::ContentSecurityPolicy
skip_before_action :require_functional!, unless: :limited_federation_mode? skip_before_action :require_functional!, unless: :limited_federation_mode?
@ -17,26 +18,6 @@ class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session protect_from_forgery with: :null_session
content_security_policy do |p|
# Set every directive that does not have a fallback
p.default_src :none
p.frame_ancestors :none
p.form_action :none
# Disable every directive with a fallback to cut on response size
p.base_uri false
p.font_src false
p.img_src false
p.style_src false
p.media_src false
p.frame_src false
p.manifest_src false
p.connect_src false
p.script_src false
p.child_src false
p.worker_src false
end
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e| rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422 render json: { error: e.to_s }, status: 422
end end

View file

@ -16,6 +16,8 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
current_user.update(user_params) if user_params current_user.update(user_params) if user_params
ActivityPub::UpdateDistributionWorker.perform_async(@account.id) ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
render json: @account, serializer: REST::CredentialAccountSerializer render json: @account, serializer: REST::CredentialAccountSerializer
rescue ActiveRecord::RecordInvalid => e
render json: ValidationErrorFormatter.new(e).as_json, status: 422
end end
private private

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::AccountsController < Api::BaseController class Api::V1::AccountsController < Api::BaseController
include RegistrationHelper
before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :remove_from_followers, :block, :unblock, :mute, :unmute] before_action -> { authorize_if_got_token! :read, :'read:accounts' }, except: [:create, :follow, :unfollow, :remove_from_followers, :block, :unblock, :mute, :unmute]
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers] before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow, :remove_from_followers]
before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute] before_action -> { doorkeeper_authorize! :follow, :write, :'write:mutes' }, only: [:mute, :unmute]
@ -90,18 +92,14 @@ class Api::V1::AccountsController < Api::BaseController
end end
def account_params def account_params
params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone) params.permit(:username, :email, :password, :agreement, :locale, :reason, :time_zone, :invite_code)
end
def invite
Invite.find_by(code: params[:invite_code]) if params[:invite_code].present?
end end
def check_enabled_registrations def check_enabled_registrations
forbidden if single_user_mode? || omniauth_only? || !allowed_registrations? forbidden unless allowed_registration?(request.remote_ip, invite)
end
def allowed_registrations?
Setting.registrations_mode != 'none'
end
def omniauth_only?
ENV['OMNIAUTH_ONLY'] == 'true'
end end
end end

View file

@ -41,10 +41,10 @@ class Api::V1::ConversationsController < Api::BaseController
account: :account_stat, account: :account_stat,
last_status: [ last_status: [
:media_attachments, :media_attachments,
:preview_cards,
:status_stat, :status_stat,
:tags, :tags,
{ {
preview_cards_status: :preview_card,
active_mentions: [account: :account_stat], active_mentions: [account: :account_stat],
account: :account_stat, account: :account_stat,
}, },

View file

@ -13,7 +13,7 @@ class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseContr
cache_if_unauthenticated! cache_if_unauthenticated!
end end
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?)) render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: show_rationale_in_response?
end end
private private
@ -25,4 +25,16 @@ class Api::V1::Instances::DomainBlocksController < Api::V1::Instances::BaseContr
def set_domain_blocks def set_domain_blocks
@domain_blocks = DomainBlock.with_user_facing_limitations.by_severity @domain_blocks = DomainBlock.with_user_facing_limitations.by_severity
end end
def show_rationale_in_response?
always_show_rationale? || show_rationale_for_user?
end
def always_show_rationale?
Setting.show_domain_blocks_rationale == 'all'
end
def show_rationale_for_user?
Setting.show_domain_blocks_rationale == 'users' && user_signed_in?
end
end end

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
class Api::V1::InvitesController < Api::BaseController
include RegistrationHelper
skip_before_action :require_authenticated_user!
skip_around_action :set_locale
before_action :set_invite
before_action :check_enabled_registrations!
# Override `current_user` to avoid reading session cookies
def current_user; end
def show
render json: { invite_code: params[:invite_code], instance_api_url: api_v2_instance_url }, status: 200
end
private
def set_invite
@invite = Invite.find_by!(code: params[:invite_code])
end
def check_enabled_registrations!
return render json: { error: I18n.t('invites.invalid') }, status: 401 unless @invite.valid_for_use?
raise Mastodon::NotPermittedError unless allowed_registration?(request.remote_ip, @invite)
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
class Api::V1::Statuses::BaseController < Api::BaseController
include Authorization
before_action :set_status
private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
end

View file

@ -1,11 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::BookmarksController < Api::BaseController class Api::V1::Statuses::BookmarksController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' } before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' }
before_action :require_user! before_action :require_user!
before_action :set_status, only: [:create] skip_before_action :set_status, only: [:destroy]
def create def create
current_account.bookmarks.find_or_create_by!(account: current_account, status: @status) current_account.bookmarks.find_or_create_by!(account: current_account, status: @status)
@ -28,13 +26,4 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
not_found not_found
end end
private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
end end

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController class Api::V1::Statuses::FavouritedByAccountsController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { authorize_if_got_token! :read, :'read:accounts' } before_action -> { authorize_if_got_token! :read, :'read:accounts' }
before_action :set_status
after_action :insert_pagination_headers after_action :insert_pagination_headers
def index def index
@ -61,13 +58,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end end
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def pagination_params(core_params) def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params) params.slice(:limit).permit(:limit).merge(core_params)
end end

View file

@ -1,11 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::FavouritesController < Api::BaseController class Api::V1::Statuses::FavouritesController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:favourites' } before_action -> { doorkeeper_authorize! :write, :'write:favourites' }
before_action :require_user! before_action :require_user!
before_action :set_status, only: [:create] skip_before_action :set_status, only: [:destroy]
def create def create
FavouriteService.new.call(current_account, @status) FavouriteService.new.call(current_account, @status)
@ -30,13 +28,4 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
not_found not_found
end end
private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
end end

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::HistoriesController < Api::BaseController class Api::V1::Statuses::HistoriesController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { authorize_if_got_token! :read, :'read:statuses' } before_action -> { authorize_if_got_token! :read, :'read:statuses' }
before_action :set_status
def show def show
cache_if_unauthenticated! cache_if_unauthenticated!
@ -16,11 +13,4 @@ class Api::V1::Statuses::HistoriesController < Api::BaseController
def status_edits def status_edits
@status.edits.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)] @status.edits.includes(:account, status: [:account]).to_a.presence || [@status.build_snapshot(at_time: @status.edited_at || @status.created_at)]
end end
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
end end

View file

@ -1,11 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::MutesController < Api::BaseController class Api::V1::Statuses::MutesController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:mutes' } before_action -> { doorkeeper_authorize! :write, :'write:mutes' }
before_action :require_user! before_action :require_user!
before_action :set_status
before_action :set_conversation before_action :set_conversation
def create def create
@ -24,13 +21,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController
private private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def set_conversation def set_conversation
@conversation = @status.conversation @conversation = @status.conversation
raise Mastodon::ValidationError if @conversation.nil? raise Mastodon::ValidationError if @conversation.nil?

View file

@ -1,11 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::PinsController < Api::BaseController class Api::V1::Statuses::PinsController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write, :'write:accounts' } before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
before_action :require_user! before_action :require_user!
before_action :set_status
def create def create
StatusPin.create!(account: current_account, status: @status) StatusPin.create!(account: current_account, status: @status)
@ -26,10 +23,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController
private private
def set_status
@status = Status.find(params[:status_id])
end
def distribute_add_activity! def distribute_add_activity!
json = ActiveModelSerializers::SerializableResource.new( json = ActiveModelSerializers::SerializableResource.new(
@status, @status,

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { authorize_if_got_token! :read, :'read:accounts' } before_action -> { authorize_if_got_token! :read, :'read:accounts' }
before_action :set_status
after_action :insert_pagination_headers after_action :insert_pagination_headers
def index def index
@ -57,13 +54,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT) @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end end
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def pagination_params(core_params) def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params) params.slice(:limit).permit(:limit).merge(core_params)
end end

View file

@ -1,13 +1,13 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::ReblogsController < Api::BaseController class Api::V1::Statuses::ReblogsController < Api::V1::Statuses::BaseController
include Authorization
include Redisable include Redisable
include Lockable include Lockable
before_action -> { doorkeeper_authorize! :write, :'write:statuses' } before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
before_action :require_user! before_action :require_user!
before_action :set_reblog, only: [:create] before_action :set_reblog, only: [:create]
skip_before_action :set_status
override_rate_limit_headers :create, family: :statuses override_rate_limit_headers :create, family: :statuses

View file

@ -1,21 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::SourcesController < Api::BaseController class Api::V1::Statuses::SourcesController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :read, :'read:statuses' } before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
before_action :set_status
def show def show
render json: @status, serializer: REST::StatusSourceSerializer render json: @status, serializer: REST::StatusSourceSerializer
end end
private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
end end

View file

@ -1,10 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Statuses::TranslationsController < Api::BaseController class Api::V1::Statuses::TranslationsController < Api::V1::Statuses::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :read, :'read:statuses' } before_action -> { doorkeeper_authorize! :read, :'read:statuses' }
before_action :set_status
before_action :set_translation before_action :set_translation
rescue_from TranslationService::NotConfiguredError, with: :not_found rescue_from TranslationService::NotConfiguredError, with: :not_found
@ -24,13 +21,6 @@ class Api::V1::Statuses::TranslationsController < Api::BaseController
private private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def set_translation def set_translation
@translation = TranslateStatusService.new.call(@status, content_locale) @translation = TranslateStatusService.new.call(@status, content_locale)
end end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
class Api::V1::Timelines::BaseController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
private
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
def next_path_params
permitted_params.merge(max_id: pagination_max_id)
end
def prev_path_params
permitted_params.merge(min_id: pagination_since_id)
end
def permitted_params
params
.slice(*self.class::PERMITTED_PARAMS)
.permit(*self.class::PERMITTED_PARAMS)
end
end

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::HomeController < Api::BaseController class Api::V1::Timelines::HomeController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show] before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: [:show]
before_action :require_user!, only: [:show] before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local limit).freeze
def show def show
with_read_replica do with_read_replica do
@ -40,27 +41,11 @@ class Api::V1::Timelines::HomeController < Api::BaseController
HomeFeed.new(current_account) HomeFeed.new(current_account)
end end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :limit).permit(:local, :limit).merge(core_params)
end
def next_path def next_path
api_v1_timelines_home_url pagination_params(max_id: pagination_max_id) api_v1_timelines_home_url next_path_params
end end
def prev_path def prev_path
api_v1_timelines_home_url pagination_params(min_id: pagination_since_id) api_v1_timelines_home_url prev_path_params
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end end
end end

View file

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::ListController < Api::BaseController class Api::V1::Timelines::ListController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:lists' } before_action -> { doorkeeper_authorize! :read, :'read:lists' }
before_action :require_user! before_action :require_user!
before_action :set_list before_action :set_list
before_action :set_statuses before_action :set_statuses
after_action :insert_pagination_headers, unless: -> { @statuses.empty? } PERMITTED_PARAMS = %i(limit).freeze
def show def show
render json: @statuses, render json: @statuses,
@ -41,27 +41,11 @@ class Api::V1::Timelines::ListController < Api::BaseController
ListFeed.new(@list) ListFeed.new(@list)
end end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path def next_path
api_v1_timelines_list_url params[:id], pagination_params(max_id: pagination_max_id) api_v1_timelines_list_url params[:id], next_path_params
end end
def prev_path def prev_path
api_v1_timelines_list_url params[:id], pagination_params(min_id: pagination_since_id) api_v1_timelines_list_url params[:id], prev_path_params
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end end
end end

View file

@ -1,8 +1,9 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::PublicController < Api::BaseController class Api::V1::Timelines::PublicController < Api::V1::Timelines::BaseController
before_action :require_user!, only: [:show], if: :require_auth? before_action :require_user!, only: [:show], if: :require_auth?
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local remote limit only_media).freeze
def show def show
cache_if_unauthenticated! cache_if_unauthenticated!
@ -42,27 +43,11 @@ class Api::V1::Timelines::PublicController < Api::BaseController
) )
end end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :remote, :limit, :only_media).permit(:local, :remote, :limit, :only_media).merge(core_params)
end
def next_path def next_path
api_v1_timelines_public_url pagination_params(max_id: pagination_max_id) api_v1_timelines_public_url next_path_params
end end
def prev_path def prev_path
api_v1_timelines_public_url pagination_params(min_id: pagination_since_id) api_v1_timelines_public_url prev_path_params
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end end
end end

View file

@ -1,9 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class Api::V1::Timelines::TagController < Api::BaseController class Api::V1::Timelines::TagController < Api::V1::Timelines::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth? before_action -> { doorkeeper_authorize! :read, :'read:statuses' }, only: :show, if: :require_auth?
before_action :load_tag before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
PERMITTED_PARAMS = %i(local limit only_media).freeze
def show def show
cache_if_unauthenticated! cache_if_unauthenticated!
@ -51,27 +52,11 @@ class Api::V1::Timelines::TagController < Api::BaseController
) )
end end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.slice(:local, :limit, :only_media).permit(:local, :limit, :only_media).merge(core_params)
end
def next_path def next_path
api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id) api_v1_timelines_tag_url params[:id], next_path_params
end end
def prev_path def prev_path
api_v1_timelines_tag_url params[:id], pagination_params(min_id: pagination_since_id) api_v1_timelines_tag_url params[:id], prev_path_params
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end end
end end

View file

@ -3,37 +3,13 @@
class Api::Web::PushSubscriptionsController < Api::Web::BaseController class Api::Web::PushSubscriptionsController < Api::Web::BaseController
before_action :require_user! before_action :require_user!
before_action :set_push_subscription, only: :update before_action :set_push_subscription, only: :update
before_action :destroy_previous_subscriptions, only: :create, if: :prior_subscriptions?
after_action :update_session_with_subscription, only: :create
def create def create
active_session = current_session @push_subscription = ::Web::PushSubscription.create!(web_push_subscription_params)
unless active_session.web_push_subscription.nil? render json: @push_subscription, serializer: REST::WebPushSubscriptionSerializer
active_session.web_push_subscription.destroy!
active_session.update!(web_push_subscription: nil)
end
# Mobile devices do not support regular notifications, so we enable push notifications by default
alerts_enabled = active_session.detection.device.mobile? || active_session.detection.device.tablet?
data = {
policy: 'all',
alerts: Notification::TYPES.index_with { alerts_enabled },
}
data.deep_merge!(data_params) if params[:data]
push_subscription = ::Web::PushSubscription.create!(
endpoint: subscription_params[:endpoint],
key_p256dh: subscription_params[:keys][:p256dh],
key_auth: subscription_params[:keys][:auth],
data: data,
user_id: active_session.user_id,
access_token_id: active_session.access_token_id
)
active_session.update!(web_push_subscription: push_subscription)
render json: push_subscription, serializer: REST::WebPushSubscriptionSerializer
end end
def update def update
@ -43,6 +19,41 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
private private
def active_session
@active_session ||= current_session
end
def destroy_previous_subscriptions
active_session.web_push_subscription.destroy!
active_session.update!(web_push_subscription: nil)
end
def prior_subscriptions?
active_session.web_push_subscription.present?
end
def subscription_data
default_subscription_data.tap do |data|
data.deep_merge!(data_params) if params[:data]
end
end
def default_subscription_data
{
policy: 'all',
alerts: Notification::TYPES.index_with { alerts_enabled },
}
end
def alerts_enabled
# Mobile devices do not support regular notifications, so we enable push notifications by default
active_session.detection.device.mobile? || active_session.detection.device.tablet?
end
def update_session_with_subscription
active_session.update!(web_push_subscription: @push_subscription)
end
def set_push_subscription def set_push_subscription
@push_subscription = ::Web::PushSubscription.find(params[:id]) @push_subscription = ::Web::PushSubscription.find(params[:id])
end end
@ -51,6 +62,17 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController
@subscription_params ||= params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh]) @subscription_params ||= params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh])
end end
def web_push_subscription_params
{
access_token_id: active_session.access_token_id,
data: subscription_data,
endpoint: subscription_params[:endpoint],
key_auth: subscription_params[:keys][:auth],
key_p256dh: subscription_params[:keys][:p256dh],
user_id: active_session.user_id,
}
end
def data_params def data_params
@data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES) @data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES)
end end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class Auth::RegistrationsController < Devise::RegistrationsController class Auth::RegistrationsController < Devise::RegistrationsController
include RegistrationHelper
include RegistrationSpamConcern include RegistrationSpamConcern
layout :determine_layout layout :determine_layout
@ -82,19 +83,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end end
def check_enabled_registrations def check_enabled_registrations
redirect_to root_path if single_user_mode? || omniauth_only? || !allowed_registrations? || ip_blocked? redirect_to root_path unless allowed_registration?(request.remote_ip, @invite)
end
def allowed_registrations?
Setting.registrations_mode != 'none' || @invite&.valid_for_use?
end
def omniauth_only?
ENV['OMNIAUTH_ONLY'] == 'true'
end
def ip_blocked?
IpBlock.where(severity: :sign_up_block).where('ip >>= ?', request.remote_ip.to_s).exists?
end end
def invite_code def invite_code

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Api::ContentSecurityPolicy
extend ActiveSupport::Concern
included do
content_security_policy do |policy|
# Set every directive that does not have a fallback
policy.default_src :none
policy.frame_ancestors :none
policy.form_action :none
# Disable every directive with a fallback to cut on response size
policy.base_uri false
policy.font_src false
policy.img_src false
policy.style_src false
policy.media_src false
policy.frame_src false
policy.manifest_src false
policy.connect_src false
policy.script_src false
policy.child_src false
policy.worker_src false
end
end
end

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
module RegistrationHelper
extend ActiveSupport::Concern
def allowed_registration?(remote_ip, invite)
!Rails.configuration.x.single_user_mode && !omniauth_only? && (registrations_open? || invite&.valid_for_use?) && !ip_blocked?(remote_ip)
end
def registrations_open?
Setting.registrations_mode != 'none'
end
def omniauth_only?
ENV['OMNIAUTH_ONLY'] == 'true'
end
def ip_blocked?(remote_ip)
IpBlock.where(severity: :sign_up_block).exists?(['ip >>= ?', remote_ip.to_s])
end
end

View file

@ -661,3 +661,18 @@ export function unpinAccountFail(error) {
error, error,
}; };
} }
export const updateAccount = ({ displayName, note, avatar, header, discoverable, indexable }) => (dispatch, getState) => {
const data = new FormData();
data.append('display_name', displayName);
data.append('note', note);
if (avatar) data.append('avatar', avatar);
if (header) data.append('header', header);
data.append('discoverable', discoverable);
data.append('indexable', indexable);
return api(getState).patch('/api/v1/accounts/update_credentials', data).then(response => {
dispatch(importFetchedAccount(response.data));
});
};

View file

@ -20,6 +20,7 @@ export interface ApiAccountJSON {
bot: boolean; bot: boolean;
created_at: string; created_at: string;
discoverable: boolean; discoverable: boolean;
indexable: boolean;
display_name: string; display_name: string;
emojis: ApiCustomEmojiJSON[]; emojis: ApiCustomEmojiJSON[];
fields: ApiAccountFieldJSON[]; fields: ApiAccountFieldJSON[];

View file

@ -51,7 +51,7 @@ export default class Retention extends PureComponent {
let content; let content;
if (loading) { if (loading) {
content = <FormattedMessage id='loading_indicator.label' defaultMessage='Loading...' />; content = <FormattedMessage id='loading_indicator.label' defaultMessage='Loading' />;
} else { } else {
content = ( content = (
<table className='retention__table'> <table className='retention__table'>

View file

@ -0,0 +1,44 @@
import PropTypes from 'prop-types';
import { useState, useCallback } from 'react';
import { defineMessages } from 'react-intl';
import classNames from 'classnames';
import { useDispatch } from 'react-redux';
import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
import { showAlert } from 'mastodon/actions/alerts';
import { IconButton } from 'mastodon/components/icon_button';
const messages = defineMessages({
copied: { id: 'copy_icon_button.copied', defaultMessage: 'Copied to clipboard' },
});
export const CopyIconButton = ({ title, value, className }) => {
const [copied, setCopied] = useState(false);
const dispatch = useDispatch();
const handleClick = useCallback(() => {
navigator.clipboard.writeText(value);
setCopied(true);
dispatch(showAlert({ message: messages.copied }));
setTimeout(() => setCopied(false), 700);
}, [setCopied, value, dispatch]);
return (
<IconButton
className={classNames(className, copied ? 'copied' : 'copyable')}
title={title}
onClick={handleClick}
iconComponent={ContentCopyIcon}
/>
);
};
CopyIconButton.propTypes = {
title: PropTypes.string,
value: PropTypes.string,
className: PropTypes.string,
};

View file

@ -1,7 +1,23 @@
import { useIntl, defineMessages } from 'react-intl';
import { CircularProgress } from './circular_progress'; import { CircularProgress } from './circular_progress';
export const LoadingIndicator: React.FC = () => ( const messages = defineMessages({
<div className='loading-indicator'> loading: { id: 'loading_indicator.label', defaultMessage: 'Loading…' },
});
export const LoadingIndicator: React.FC = () => {
const intl = useIntl();
return (
<div
className='loading-indicator'
role='progressbar'
aria-busy
aria-live='polite'
aria-label={intl.formatMessage(messages.loading)}
>
<CircularProgress size={50} strokeWidth={6} /> <CircularProgress size={50} strokeWidth={6} />
</div> </div>
); );
};

View file

@ -19,6 +19,8 @@ import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/s
import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg'; import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg';
import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg'; import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg';
import { ReactComponent as RepeatDisabledIcon } from 'mastodon/../svg-icons/repeat_disabled.svg';
import { ReactComponent as RepeatPrivateIcon } from 'mastodon/../svg-icons/repeat_private.svg';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -348,6 +350,7 @@ class StatusActionBar extends ImmutablePureComponent {
let replyIcon; let replyIcon;
let replyIconComponent; let replyIconComponent;
let replyTitle; let replyTitle;
if (status.get('in_reply_to_id', null) === null) { if (status.get('in_reply_to_id', null) === null) {
replyIcon = 'reply'; replyIcon = 'reply';
replyIconComponent = ReplyIcon; replyIconComponent = ReplyIcon;
@ -360,15 +363,20 @@ class StatusActionBar extends ImmutablePureComponent {
const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private'; const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private';
let reblogTitle = ''; let reblogTitle, reblogIconComponent;
if (status.get('reblogged')) { if (status.get('reblogged')) {
reblogTitle = intl.formatMessage(messages.cancel_reblog_private); reblogTitle = intl.formatMessage(messages.cancel_reblog_private);
reblogIconComponent = publicStatus ? RepeatIcon : RepeatPrivateIcon;
} else if (publicStatus) { } else if (publicStatus) {
reblogTitle = intl.formatMessage(messages.reblog); reblogTitle = intl.formatMessage(messages.reblog);
reblogIconComponent = RepeatIcon;
} else if (reblogPrivate) { } else if (reblogPrivate) {
reblogTitle = intl.formatMessage(messages.reblog_private); reblogTitle = intl.formatMessage(messages.reblog_private);
reblogIconComponent = RepeatPrivateIcon;
} else { } else {
reblogTitle = intl.formatMessage(messages.cannot_reblog); reblogTitle = intl.formatMessage(messages.cannot_reblog);
reblogIconComponent = RepeatDisabledIcon;
} }
const filterButton = this.props.onFilter && ( const filterButton = this.props.onFilter && (
@ -380,7 +388,7 @@ class StatusActionBar extends ImmutablePureComponent {
return ( return (
<div className='status__action-bar'> <div className='status__action-bar'>
<IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} /> <IconButton className='status__action-bar__button' title={replyTitle} icon={isReply ? 'reply' : replyIcon} iconComponent={isReply ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} counter={status.get('replies_count')} />
<IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={RepeatIcon} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} /> <IconButton className={classNames('status__action-bar__button', { reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} counter={withCounters ? status.get('reblogs_count') : undefined} />
<IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} /> <IconButton className='status__action-bar__button star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} counter={withCounters ? status.get('favourites_count') : undefined} />
<IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /> <IconButton className='status__action-bar__button bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} />

View file

@ -14,10 +14,12 @@ import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/l
import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg'; import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications.svg'; import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications.svg';
import { ReactComponent as NotificationsActiveIcon } from '@material-symbols/svg-600/outlined/notifications_active-fill.svg'; import { ReactComponent as NotificationsActiveIcon } from '@material-symbols/svg-600/outlined/notifications_active-fill.svg';
import { ReactComponent as ShareIcon } from '@material-symbols/svg-600/outlined/share.svg';
import { Avatar } from 'mastodon/components/avatar'; import { Avatar } from 'mastodon/components/avatar';
import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge'; import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge';
import { Button } from 'mastodon/components/button'; import { Button } from 'mastodon/components/button';
import { CopyIconButton } from 'mastodon/components/copy_icon_button';
import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters'; import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { IconButton } from 'mastodon/components/icon_button'; import { IconButton } from 'mastodon/components/icon_button';
@ -46,6 +48,7 @@ const messages = defineMessages({
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
report: { id: 'account.report', defaultMessage: 'Report @{name}' }, report: { id: 'account.report', defaultMessage: 'Report @{name}' },
share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' }, share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' },
copy: { id: 'account.copy', defaultMessage: 'Copy link to profile' },
media: { id: 'account.media', defaultMessage: 'Media' }, media: { id: 'account.media', defaultMessage: 'Media' },
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' }, blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
@ -245,10 +248,9 @@ class Header extends ImmutablePureComponent {
const isRemote = account.get('acct') !== account.get('username'); const isRemote = account.get('acct') !== account.get('username');
const remoteDomain = isRemote ? account.get('acct').split('@')[1] : null; const remoteDomain = isRemote ? account.get('acct').split('@')[1] : null;
let actionBtn, bellBtn, lockedIcon, shareBtn;
let info = []; let info = [];
let actionBtn = '';
let bellBtn = '';
let lockedIcon = '';
let menu = []; let menu = [];
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) { if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
@ -267,6 +269,12 @@ class Header extends ImmutablePureComponent {
bellBtn = <IconButton icon={account.getIn(['relationship', 'notifying']) ? 'bell' : 'bell-o'} iconComponent={account.getIn(['relationship', 'notifying']) ? NotificationsActiveIcon : NotificationsIcon} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />; bellBtn = <IconButton icon={account.getIn(['relationship', 'notifying']) ? 'bell' : 'bell-o'} iconComponent={account.getIn(['relationship', 'notifying']) ? NotificationsActiveIcon : NotificationsIcon} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />;
} }
if ('share' in navigator) {
shareBtn = <IconButton className='optional' iconComponent={ShareIcon} title={intl.formatMessage(messages.share, { name: account.get('username') })} onClick={this.handleShare} />;
} else {
shareBtn = <CopyIconButton className='optional' title={intl.formatMessage(messages.copy)} value={account.get('url')} />;
}
if (me !== account.get('id')) { if (me !== account.get('id')) {
if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded
actionBtn = ''; actionBtn = '';
@ -297,10 +305,6 @@ class Header extends ImmutablePureComponent {
if (isRemote) { if (isRemote) {
menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: account.get('url') }); menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: account.get('url') });
}
if ('share' in navigator && !account.get('suspended')) {
menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare });
menu.push(null); menu.push(null);
} }
@ -414,6 +418,7 @@ class Header extends ImmutablePureComponent {
<> <>
{actionBtn} {actionBtn}
{bellBtn} {bellBtn}
{shareBtn}
</> </>
)} )}

View file

@ -204,7 +204,7 @@ class ListTimeline extends PureComponent {
</div> </div>
<div className='setting-toggle'> <div className='setting-toggle'>
<Toggle id={`list-${id}-exclusive`} defaultChecked={isExclusive} onChange={this.onExclusiveToggle} /> <Toggle id={`list-${id}-exclusive`} checked={isExclusive} onChange={this.onExclusiveToggle} />
<label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'> <label htmlFor={`list-${id}-exclusive`} className='setting-toggle__label'>
<FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home' /> <FormattedMessage id='lists.exclusive' defaultMessage='Hide these posts from home' />
</label> </label>

View file

@ -1,29 +0,0 @@
import PropTypes from 'prop-types';
import { Fragment } from 'react';
import classNames from 'classnames';
import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/done.svg';
import { Icon } from 'mastodon/components/icon';
const ProgressIndicator = ({ steps, completed }) => (
<div className='onboarding__progress-indicator'>
{(new Array(steps)).fill().map((_, i) => (
<Fragment key={i}>
{i > 0 && <div className={classNames('onboarding__progress-indicator__line', { active: completed > i })} />}
<div className={classNames('onboarding__progress-indicator__step', { active: completed > i })}>
{completed > i && <Icon icon={CheckIcon} />}
</div>
</Fragment>
))}
</div>
);
ProgressIndicator.propTypes = {
steps: PropTypes.number.isRequired,
completed: PropTypes.number,
};
export default ProgressIndicator;

View file

@ -1,11 +1,13 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg'; import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/done.svg'; import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/done.svg';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
const Step = ({ label, description, icon, iconComponent, completed, onClick, href }) => { export const Step = ({ label, description, icon, iconComponent, completed, onClick, href, to }) => {
const content = ( const content = (
<> <>
<div className='onboarding__steps__item__icon'> <div className='onboarding__steps__item__icon'>
@ -29,6 +31,12 @@ const Step = ({ label, description, icon, iconComponent, completed, onClick, hre
{content} {content}
</a> </a>
); );
} else if (to) {
return (
<Link to={to} className='onboarding__steps__item'>
{content}
</Link>
);
} }
return ( return (
@ -45,7 +53,6 @@ Step.propTypes = {
iconComponent: PropTypes.func, iconComponent: PropTypes.func,
completed: PropTypes.bool, completed: PropTypes.bool,
href: PropTypes.string, href: PropTypes.string,
to: PropTypes.string,
onClick: PropTypes.func, onClick: PropTypes.func,
}; };
export default Step;

View file

@ -1,44 +1,31 @@
import PropTypes from 'prop-types'; import { useEffect } from 'react';
import { PureComponent } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes'; import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { useDispatch } from 'react-redux';
import { fetchSuggestions } from 'mastodon/actions/suggestions'; import { fetchSuggestions } from 'mastodon/actions/suggestions';
import { markAsPartial } from 'mastodon/actions/timelines'; import { markAsPartial } from 'mastodon/actions/timelines';
import Column from 'mastodon/components/column';
import { ColumnBackButton } from 'mastodon/components/column_back_button'; import { ColumnBackButton } from 'mastodon/components/column_back_button';
import { EmptyAccount } from 'mastodon/components/empty_account'; import { EmptyAccount } from 'mastodon/components/empty_account';
import Account from 'mastodon/containers/account_container'; import Account from 'mastodon/containers/account_container';
import { useAppSelector } from 'mastodon/store';
const mapStateToProps = state => ({ export const Follows = () => {
suggestions: state.getIn(['suggestions', 'items']), const dispatch = useDispatch();
isLoading: state.getIn(['suggestions', 'isLoading']), const isLoading = useAppSelector(state => state.getIn(['suggestions', 'isLoading']));
}); const suggestions = useAppSelector(state => state.getIn(['suggestions', 'items']));
class Follows extends PureComponent { useEffect(() => {
static propTypes = {
onBack: PropTypes.func,
dispatch: PropTypes.func.isRequired,
suggestions: ImmutablePropTypes.list,
isLoading: PropTypes.bool,
};
componentDidMount () {
const { dispatch } = this.props;
dispatch(fetchSuggestions(true)); dispatch(fetchSuggestions(true));
}
componentWillUnmount () { return () => {
const { dispatch } = this.props;
dispatch(markAsPartial('home')); dispatch(markAsPartial('home'));
} };
}, [dispatch]);
render () {
const { onBack, isLoading, suggestions } = this.props;
let loadedContent; let loadedContent;
@ -51,8 +38,8 @@ class Follows extends PureComponent {
} }
return ( return (
<Column> <>
<ColumnBackButton onClick={onBack} /> <ColumnBackButton />
<div className='scrollable privacy-policy'> <div className='scrollable privacy-policy'>
<div className='column-title'> <div className='column-title'>
@ -67,13 +54,9 @@ class Follows extends PureComponent {
<p className='onboarding__lead'><FormattedMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' values={{ strong: chunks => <strong>{chunks}</strong> }} /></p> <p className='onboarding__lead'><FormattedMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' values={{ strong: chunks => <strong>{chunks}</strong> }} /></p>
<div className='onboarding__footer'> <div className='onboarding__footer'>
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></button> <Link className='link-button' to='/start'><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></Link>
</div> </div>
</div> </div>
</Column> </>
); );
} };
}
export default connect(mapStateToProps)(Follows);

View file

@ -1,116 +1,50 @@
import PropTypes from 'prop-types'; import { useCallback } from 'react';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
import { Helmet } from 'react-helmet'; import { Helmet } from 'react-helmet';
import { Link, withRouter } from 'react-router-dom'; import { Link, Switch, Route, useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import { ReactComponent as AccountCircleIcon } from '@material-symbols/svg-600/outlined/account_circle.svg'; import { ReactComponent as AccountCircleIcon } from '@material-symbols/svg-600/outlined/account_circle.svg';
import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg'; import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg'; import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
import { ReactComponent as EditNoteIcon } from '@material-symbols/svg-600/outlined/edit_note.svg'; import { ReactComponent as EditNoteIcon } from '@material-symbols/svg-600/outlined/edit_note.svg';
import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg'; import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
import { debounce } from 'lodash';
import illustration from 'mastodon/../images/elephant_ui_conversation.svg'; import illustration from 'mastodon/../images/elephant_ui_conversation.svg';
import { fetchAccount } from 'mastodon/actions/accounts';
import { focusCompose } from 'mastodon/actions/compose'; import { focusCompose } from 'mastodon/actions/compose';
import { closeOnboarding } from 'mastodon/actions/onboarding';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import Column from 'mastodon/features/ui/components/column'; import Column from 'mastodon/features/ui/components/column';
import { me } from 'mastodon/initial_state'; import { me } from 'mastodon/initial_state';
import { makeGetAccount } from 'mastodon/selectors'; import { useAppSelector } from 'mastodon/store';
import { assetHost } from 'mastodon/utils/config'; import { assetHost } from 'mastodon/utils/config';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
import Step from './components/step'; import { Step } from './components/step';
import Follows from './follows'; import { Follows } from './follows';
import Share from './share'; import { Profile } from './profile';
import { Share } from './share';
const messages = defineMessages({ const messages = defineMessages({
template: { id: 'onboarding.compose.template', defaultMessage: 'Hello #Mastodon!' }, template: { id: 'onboarding.compose.template', defaultMessage: 'Hello #Mastodon!' },
}); });
const mapStateToProps = () => { const Onboarding = () => {
const getAccount = makeGetAccount(); const account = useAppSelector(state => state.getIn(['accounts', me]));
const dispatch = useDispatch();
return state => ({ const intl = useIntl();
account: getAccount(state, me), const history = useHistory();
});
};
class Onboarding extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
account: ImmutablePropTypes.record,
...WithRouterPropTypes,
};
state = {
step: null,
profileClicked: false,
shareClicked: false,
};
handleClose = () => {
const { dispatch, history } = this.props;
dispatch(closeOnboarding());
history.push('/home');
};
handleProfileClick = () => {
this.setState({ profileClicked: true });
};
handleFollowClick = () => {
this.setState({ step: 'follows' });
};
handleComposeClick = () => {
const { dispatch, intl, history } = this.props;
const handleComposeClick = useCallback(() => {
dispatch(focusCompose(history, intl.formatMessage(messages.template))); dispatch(focusCompose(history, intl.formatMessage(messages.template)));
}; }, [dispatch, intl, history]);
handleShareClick = () => {
this.setState({ step: 'share', shareClicked: true });
};
handleBackClick = () => {
this.setState({ step: null });
};
handleWindowFocus = debounce(() => {
const { dispatch, account } = this.props;
dispatch(fetchAccount(account.get('id')));
}, 1000, { trailing: true });
componentDidMount () {
window.addEventListener('focus', this.handleWindowFocus, false);
}
componentWillUnmount () {
window.removeEventListener('focus', this.handleWindowFocus);
}
render () {
const { account } = this.props;
const { step, shareClicked } = this.state;
switch(step) {
case 'follows':
return <Follows onBack={this.handleBackClick} />;
case 'share':
return <Share onBack={this.handleBackClick} />;
}
return ( return (
<Column> <Column>
<Switch>
<Route path='/start' exact>
<div className='scrollable privacy-policy'> <div className='scrollable privacy-policy'>
<div className='column-title'> <div className='column-title'>
<img src={illustration} alt='' className='onboarding__illustration' /> <img src={illustration} alt='' className='onboarding__illustration' />
@ -119,10 +53,10 @@ class Onboarding extends ImmutablePureComponent {
</div> </div>
<div className='onboarding__steps'> <div className='onboarding__steps'>
<Step onClick={this.handleProfileClick} href='/settings/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' iconComponent={AccountCircleIcon} label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} /> <Step to='/start/profile' completed={(!account.get('avatar').endsWith('missing.png')) || (account.get('display_name').length > 0 && account.get('note').length > 0)} icon='address-book-o' iconComponent={AccountCircleIcon} label={<FormattedMessage id='onboarding.steps.setup_profile.title' defaultMessage='Customize your profile' />} description={<FormattedMessage id='onboarding.steps.setup_profile.body' defaultMessage='Others are more likely to interact with you with a filled out profile.' />} />
<Step onClick={this.handleFollowClick} completed={(account.get('following_count') * 1) >= 7} icon='user-plus' iconComponent={PersonAddIcon} label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} /> <Step to='/start/follows' completed={(account.get('following_count') * 1) >= 1} icon='user-plus' iconComponent={PersonAddIcon} label={<FormattedMessage id='onboarding.steps.follow_people.title' defaultMessage='Find at least {count, plural, one {one person} other {# people}} to follow' values={{ count: 7 }} />} description={<FormattedMessage id='onboarding.steps.follow_people.body' defaultMessage="You curate your own home feed. Let's fill it with interesting people." />} />
<Step onClick={this.handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' iconComponent={EditNoteIcon} label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' values={{ emoji: <img className='emojione' alt='🐘' src={`${assetHost}/emoji/1f418.svg`} /> }} />} /> <Step onClick={handleComposeClick} completed={(account.get('statuses_count') * 1) >= 1} icon='pencil-square-o' iconComponent={EditNoteIcon} label={<FormattedMessage id='onboarding.steps.publish_status.title' defaultMessage='Make your first post' />} description={<FormattedMessage id='onboarding.steps.publish_status.body' defaultMessage='Say hello to the world.' values={{ emoji: <img className='emojione' alt='🐘' src={`${assetHost}/emoji/1f418.svg`} /> }} />} />
<Step onClick={this.handleShareClick} completed={shareClicked} icon='copy' iconComponent={ContentCopyIcon} label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} /> <Step to='/start/share' icon='copy' iconComponent={ContentCopyIcon} label={<FormattedMessage id='onboarding.steps.share_profile.title' defaultMessage='Share your profile' />} description={<FormattedMessage id='onboarding.steps.share_profile.body' defaultMessage='Let your friends know how to find you on Mastodon!' />} />
</div> </div>
<p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage="Don't need help getting started?" /></p> <p className='onboarding__lead'><FormattedMessage id='onboarding.start.skip' defaultMessage="Don't need help getting started?" /></p>
@ -139,14 +73,18 @@ class Onboarding extends ImmutablePureComponent {
</Link> </Link>
</div> </div>
</div> </div>
</Route>
<Route path='/start/profile' component={Profile} />
<Route path='/start/follows' component={Follows} />
<Route path='/start/share' component={Share} />
</Switch>
<Helmet> <Helmet>
<meta name='robots' content='noindex' /> <meta name='robots' content='noindex' />
</Helmet> </Helmet>
</Column> </Column>
); );
} };
} export default Onboarding;
export default withRouter(connect(mapStateToProps)(injectIntl(Onboarding)));

View file

@ -0,0 +1,160 @@
import { useState, useMemo, useCallback, createRef } from 'react';
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { ReactComponent as AddPhotoAlternateIcon } from '@material-symbols/svg-600/outlined/add_photo_alternate.svg';
import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
import Toggle from 'react-toggle';
import { updateAccount } from 'mastodon/actions/accounts';
import { Button } from 'mastodon/components/button';
import { ColumnBackButton } from 'mastodon/components/column_back_button';
import { Icon } from 'mastodon/components/icon';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { me } from 'mastodon/initial_state';
import { useAppSelector } from 'mastodon/store';
import { unescapeHTML } from 'mastodon/utils/html';
const messages = defineMessages({
uploadHeader: { id: 'onboarding.profile.upload_header', defaultMessage: 'Upload profile header' },
uploadAvatar: { id: 'onboarding.profile.upload_avatar', defaultMessage: 'Upload profile picture' },
});
export const Profile = () => {
const account = useAppSelector(state => state.getIn(['accounts', me]));
const [displayName, setDisplayName] = useState(account.get('display_name'));
const [note, setNote] = useState(unescapeHTML(account.get('note')));
const [avatar, setAvatar] = useState(null);
const [header, setHeader] = useState(null);
const [discoverable, setDiscoverable] = useState(account.get('discoverable'));
const [isSaving, setIsSaving] = useState(false);
const [errors, setErrors] = useState();
const avatarFileRef = createRef();
const headerFileRef = createRef();
const dispatch = useDispatch();
const intl = useIntl();
const history = useHistory();
const handleDisplayNameChange = useCallback(e => {
setDisplayName(e.target.value);
}, [setDisplayName]);
const handleNoteChange = useCallback(e => {
setNote(e.target.value);
}, [setNote]);
const handleDiscoverableChange = useCallback(e => {
setDiscoverable(e.target.checked);
}, [setDiscoverable]);
const handleAvatarChange = useCallback(e => {
setAvatar(e.target?.files?.[0]);
}, [setAvatar]);
const handleHeaderChange = useCallback(e => {
setHeader(e.target?.files?.[0]);
}, [setHeader]);
const avatarPreview = useMemo(() => avatar ? URL.createObjectURL(avatar) : account.get('avatar'), [avatar, account]);
const headerPreview = useMemo(() => header ? URL.createObjectURL(header) : account.get('header'), [header, account]);
const handleSubmit = useCallback(() => {
setIsSaving(true);
dispatch(updateAccount({
displayName,
note,
avatar,
header,
discoverable,
indexable: discoverable,
})).then(() => history.push('/start/follows')).catch(err => {
setIsSaving(false);
setErrors(err.response.data.details);
});
}, [dispatch, displayName, note, avatar, header, discoverable, history]);
return (
<>
<ColumnBackButton />
<div className='scrollable privacy-policy'>
<div className='column-title'>
<h3><FormattedMessage id='onboarding.profile.title' defaultMessage='Profile setup' /></h3>
<p><FormattedMessage id='onboarding.profile.lead' defaultMessage='You can always complete this later in the settings, where even more customization options are available.' /></p>
</div>
<div className='simple_form'>
<div className='onboarding__profile'>
<label className={classNames('app-form__header-input', { selected: !!headerPreview, invalid: !!errors?.header })} title={intl.formatMessage(messages.uploadHeader)}>
<input
type='file'
hidden
ref={headerFileRef}
accept='image/*'
onChange={handleHeaderChange}
/>
{headerPreview && <img src={headerPreview} alt='' />}
<Icon icon={headerPreview ? EditIcon : AddPhotoAlternateIcon} />
</label>
<label className={classNames('app-form__avatar-input', { selected: !!avatarPreview, invalid: !!errors?.avatar })} title={intl.formatMessage(messages.uploadAvatar)}>
<input
type='file'
hidden
ref={avatarFileRef}
accept='image/*'
onChange={handleAvatarChange}
/>
{avatarPreview && <img src={avatarPreview} alt='' />}
<Icon icon={avatarPreview ? EditIcon : AddPhotoAlternateIcon} />
</label>
</div>
<div className={classNames('input with_block_label', { field_with_errors: !!errors?.display_name })}>
<label htmlFor='display_name'><FormattedMessage id='onboarding.profile.display_name' defaultMessage='Display name' /></label>
<span className='hint'><FormattedMessage id='onboarding.profile.display_name_hint' defaultMessage='Your full name or your fun name…' /></span>
<div className='label_input'>
<input id='display_name' type='text' value={displayName} onChange={handleDisplayNameChange} maxLength={30} />
</div>
</div>
<div className={classNames('input with_block_label', { field_with_errors: !!errors?.note })}>
<label htmlFor='note'><FormattedMessage id='onboarding.profile.note' defaultMessage='Bio' /></label>
<span className='hint'><FormattedMessage id='onboarding.profile.note_hint' defaultMessage='You can @mention other people or #hashtags…' /></span>
<div className='label_input'>
<textarea id='note' value={note} onChange={handleNoteChange} maxLength={500} />
</div>
</div>
<label className='app-form__toggle'>
<div className='app-form__toggle__label'>
<strong><FormattedMessage id='onboarding.profile.discoverable' defaultMessage='Make my profile discoverable' /></strong> <span className='recommended'><FormattedMessage id='recommended' defaultMessage='Recommended' /></span>
<span className='hint'><FormattedMessage id='onboarding.profile.discoverable_hint' defaultMessage='When you opt in to discoverability on Mastodon, your posts may appear in search results and trending, and your profile may be suggested to people with similar interests to you.' /></span>
</div>
<div className='app-form__toggle__toggle'>
<div>
<Toggle checked={discoverable} onChange={handleDiscoverableChange} />
</div>
</div>
</label>
</div>
<div className='onboarding__footer'>
<Button block onClick={handleSubmit} disabled={isSaving}>{isSaving ? <LoadingIndicator /> : <FormattedMessage id='onboarding.profile.save_and_continue' defaultMessage='Save and continue' />}</Button>
</div>
</div>
</>
);
};

View file

@ -1,31 +1,25 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames'; import classNames from 'classnames';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg'; import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg'; import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
import SwipeableViews from 'react-swipeable-views'; import SwipeableViews from 'react-swipeable-views';
import Column from 'mastodon/components/column';
import { ColumnBackButton } from 'mastodon/components/column_back_button'; import { ColumnBackButton } from 'mastodon/components/column_back_button';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { me, domain } from 'mastodon/initial_state'; import { me, domain } from 'mastodon/initial_state';
import { useAppSelector } from 'mastodon/store';
const messages = defineMessages({ const messages = defineMessages({
shareableMessage: { id: 'onboarding.share.message', defaultMessage: 'I\'m {username} on #Mastodon! Come follow me at {url}' }, shareableMessage: { id: 'onboarding.share.message', defaultMessage: 'I\'m {username} on #Mastodon! Come follow me at {url}' },
}); });
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
});
class CopyPasteText extends PureComponent { class CopyPasteText extends PureComponent {
static propTypes = { static propTypes = {
@ -141,22 +135,14 @@ class TipCarousel extends PureComponent {
} }
class Share extends PureComponent { export const Share = () => {
const account = useAppSelector(state => state.getIn(['accounts', me]));
static propTypes = { const intl = useIntl();
onBack: PropTypes.func,
account: ImmutablePropTypes.record,
intl: PropTypes.object,
};
render () {
const { onBack, account, intl } = this.props;
const url = (new URL(`/@${account.get('username')}`, document.baseURI)).href; const url = (new URL(`/@${account.get('username')}`, document.baseURI)).href;
return ( return (
<Column> <>
<ColumnBackButton onClick={onBack} /> <ColumnBackButton />
<div className='scrollable privacy-policy'> <div className='scrollable privacy-policy'>
<div className='column-title'> <div className='column-title'>
@ -187,13 +173,9 @@ class Share extends PureComponent {
</div> </div>
<div className='onboarding__footer'> <div className='onboarding__footer'>
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.action.back' defaultMessage='Take me back' /></button> <Link className='link-button' to='/start'><FormattedMessage id='onboarding.action.back' defaultMessage='Take me back' /></Link>
</div> </div>
</div> </div>
</Column> </>
); );
} };
}
export default connect(mapStateToProps)(injectIntl(Share));

View file

@ -166,7 +166,7 @@ class Footer extends ImmutablePureComponent {
onClose(); onClose();
} }
history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`); this.props.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
}; };
render () { render () {

View file

@ -18,6 +18,8 @@ import { ReactComponent as ReplyAllIcon } from '@material-symbols/svg-600/outlin
import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg'; import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg'; import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg';
import { ReactComponent as RepeatDisabledIcon } from 'mastodon/../svg-icons/repeat_disabled.svg';
import { ReactComponent as RepeatPrivateIcon } from 'mastodon/../svg-icons/repeat_private.svg';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router'; import { WithRouterPropTypes } from 'mastodon/utils/react_router';
@ -280,6 +282,7 @@ class ActionBar extends PureComponent {
let replyIcon; let replyIcon;
let replyIconComponent; let replyIconComponent;
if (status.get('in_reply_to_id', null) === null) { if (status.get('in_reply_to_id', null) === null) {
replyIcon = 'reply'; replyIcon = 'reply';
replyIconComponent = ReplyIcon; replyIconComponent = ReplyIcon;
@ -290,21 +293,26 @@ class ActionBar extends PureComponent {
const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private'; const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private';
let reblogTitle; let reblogTitle, reblogIconComponent;
if (status.get('reblogged')) { if (status.get('reblogged')) {
reblogTitle = intl.formatMessage(messages.cancel_reblog_private); reblogTitle = intl.formatMessage(messages.cancel_reblog_private);
reblogIconComponent = publicStatus ? RepeatIcon : RepeatPrivateIcon;
} else if (publicStatus) { } else if (publicStatus) {
reblogTitle = intl.formatMessage(messages.reblog); reblogTitle = intl.formatMessage(messages.reblog);
reblogIconComponent = RepeatIcon;
} else if (reblogPrivate) { } else if (reblogPrivate) {
reblogTitle = intl.formatMessage(messages.reblog_private); reblogTitle = intl.formatMessage(messages.reblog_private);
reblogIconComponent = RepeatPrivateIcon;
} else { } else {
reblogTitle = intl.formatMessage(messages.cannot_reblog); reblogTitle = intl.formatMessage(messages.cannot_reblog);
reblogIconComponent = RepeatDisabledIcon;
} }
return ( return (
<div className='detailed-status__action-bar'> <div className='detailed-status__action-bar'>
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div> <div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} iconComponent={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? ReplyIcon : replyIconComponent} onClick={this.handleReplyClick} /></div>
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={RepeatIcon} onClick={this.handleReblogClick} /></div> <div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' iconComponent={reblogIconComponent} onClick={this.handleReblogClick} /></div>
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div> <div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' iconComponent={status.get('favourited') ? StarIcon : StarBorderIcon} onClick={this.handleFavouriteClick} /></div>
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div> <div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' iconComponent={status.get('bookmarked') ? BookmarkIcon : BookmarkBorderIcon} onClick={this.handleBookmarkClick} /></div>

View file

@ -210,7 +210,7 @@ class SwitchingColumnsArea extends PureComponent {
<WrappedRoute path='/bookmarks' component={BookmarkedStatuses} content={children} /> <WrappedRoute path='/bookmarks' component={BookmarkedStatuses} content={children} />
<WrappedRoute path='/pinned' component={PinnedStatuses} content={children} /> <WrappedRoute path='/pinned' component={PinnedStatuses} content={children} />
<WrappedRoute path='/start' exact component={Onboarding} content={children} /> <WrappedRoute path='/start' component={Onboarding} content={children} />
<WrappedRoute path='/directory' component={Directory} content={children} /> <WrappedRoute path='/directory' component={Directory} content={children} />
<WrappedRoute path={['/explore', '/search']} component={Explore} content={children} /> <WrappedRoute path={['/explore', '/search']} component={Explore} content={children} />
<WrappedRoute path={['/publish', '/statuses/new']} component={Compose} content={children} /> <WrappedRoute path={['/publish', '/statuses/new']} component={Compose} content={children} />

View file

@ -14,6 +14,7 @@
"account.badges.group": "Groep", "account.badges.group": "Groep",
"account.block": "Blokkeer @{name}", "account.block": "Blokkeer @{name}",
"account.block_domain": "Blokkeer domein {domain}", "account.block_domain": "Blokkeer domein {domain}",
"account.block_short": "Blokkeer",
"account.blocked": "Geblokkeer", "account.blocked": "Geblokkeer",
"account.browse_more_on_origin_server": "Verken die oorspronklike profiel", "account.browse_more_on_origin_server": "Verken die oorspronklike profiel",
"account.cancel_follow_request": "Herroep volgversoek", "account.cancel_follow_request": "Herroep volgversoek",
@ -45,6 +46,7 @@
"account.posts_with_replies": "Plasings en antwoorde", "account.posts_with_replies": "Plasings en antwoorde",
"account.report": "Rapporteer @{name}", "account.report": "Rapporteer @{name}",
"account.requested": "Wag op goedkeuring. Klik om volgversoek te kanselleer", "account.requested": "Wag op goedkeuring. Klik om volgversoek te kanselleer",
"account.requested_follow": "{name} het versoek om jou te volg",
"account.share": "Deel @{name} se profiel", "account.share": "Deel @{name} se profiel",
"account.show_reblogs": "Wys aangestuurde plasings van @{name}", "account.show_reblogs": "Wys aangestuurde plasings van @{name}",
"account.statuses_counter": "{count, plural, one {{counter} Plaas} other {{counter} Plasings}}", "account.statuses_counter": "{count, plural, one {{counter} Plaas} other {{counter} Plasings}}",
@ -82,6 +84,7 @@
"column.community": "Plaaslike tydlyn", "column.community": "Plaaslike tydlyn",
"column.directory": "Blaai deur profiele", "column.directory": "Blaai deur profiele",
"column.domain_blocks": "Geblokkeerde domeine", "column.domain_blocks": "Geblokkeerde domeine",
"column.favourites": "Gunstelinge",
"column.follow_requests": "Volgversoeke", "column.follow_requests": "Volgversoeke",
"column.home": "Tuis", "column.home": "Tuis",
"column.lists": "Lyste", "column.lists": "Lyste",
@ -271,6 +274,7 @@
"privacy.unlisted.short": "Ongelys", "privacy.unlisted.short": "Ongelys",
"privacy_policy.last_updated": "Laaste bywerking op {date}", "privacy_policy.last_updated": "Laaste bywerking op {date}",
"privacy_policy.title": "Privaatheidsbeleid", "privacy_policy.title": "Privaatheidsbeleid",
"regeneration_indicator.sublabel": "Jou tuis-voer word voorberei!",
"reply_indicator.cancel": "Kanselleer", "reply_indicator.cancel": "Kanselleer",
"report.placeholder": "Type or paste additional comments", "report.placeholder": "Type or paste additional comments",
"report.submit": "Submit report", "report.submit": "Submit report",

View file

@ -334,7 +334,6 @@
"lists.search": "Buscar entre la chent a la quala sigues", "lists.search": "Buscar entre la chent a la quala sigues",
"lists.subheading": "Las tuyas listas", "lists.subheading": "Las tuyas listas",
"load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}", "load_pending": "{count, plural, one {# nuevo elemento} other {# nuevos elementos}}",
"loading_indicator.label": "Cargando...",
"media_gallery.toggle_visible": "{number, plural, one {Amaga la imachen} other {Amaga las imáchens}}", "media_gallery.toggle_visible": "{number, plural, one {Amaga la imachen} other {Amaga las imáchens}}",
"moved_to_account_banner.text": "La tuya cuenta {disabledAccount} ye actualment deshabilitada perque t'has mudau a {movedToAccount}.", "moved_to_account_banner.text": "La tuya cuenta {disabledAccount} ye actualment deshabilitada perque t'has mudau a {movedToAccount}.",
"mute_modal.duration": "Duración", "mute_modal.duration": "Duración",

View file

@ -389,7 +389,6 @@
"lists.search": "إبحث في قائمة الحسابات التي تُتابِعها", "lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
"lists.subheading": "قوائمك", "lists.subheading": "قوائمك",
"load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}", "load_pending": "{count, plural, one {# عنصر جديد} other {# عناصر جديدة}}",
"loading_indicator.label": "جارٍ التحميل…",
"media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}", "media_gallery.toggle_visible": "{number, plural, zero {} one {اخف الصورة} two {اخف الصورتين} few {اخف الصور} many {اخف الصور} other {اخف الصور}}",
"moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.", "moved_to_account_banner.text": "حسابك {disabledAccount} معطل حاليًا لأنك انتقلت إلى {movedToAccount}.",
"mute_modal.duration": "المدة", "mute_modal.duration": "المدة",

View file

@ -272,7 +272,6 @@
"lists.search": "Buscar ente los perfiles que sigues", "lists.search": "Buscar ente los perfiles que sigues",
"lists.subheading": "Les tos llistes", "lists.subheading": "Les tos llistes",
"load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}", "load_pending": "{count, plural, one {# elementu nuevu} other {# elementos nuevos}}",
"loading_indicator.label": "Cargando…",
"media_gallery.toggle_visible": "{number, plural, one {Anubrir la imaxe} other {Anubrir les imáxenes}}", "media_gallery.toggle_visible": "{number, plural, one {Anubrir la imaxe} other {Anubrir les imáxenes}}",
"mute_modal.duration": "Duración", "mute_modal.duration": "Duración",
"mute_modal.hide_notifications": "¿Quies anubrir los avisos d'esti perfil?", "mute_modal.hide_notifications": "¿Quies anubrir los avisos d'esti perfil?",

View file

@ -21,6 +21,7 @@
"account.blocked": "Заблакіраваны", "account.blocked": "Заблакіраваны",
"account.browse_more_on_origin_server": "Глядзіце больш у арыгінальным профілі", "account.browse_more_on_origin_server": "Глядзіце больш у арыгінальным профілі",
"account.cancel_follow_request": "Скасаваць запыт на падпіску", "account.cancel_follow_request": "Скасаваць запыт на падпіску",
"account.copy": "Скапіраваць спасылку на профіль",
"account.direct": "Згадаць асабіста @{name}", "account.direct": "Згадаць асабіста @{name}",
"account.disable_notifications": "Не паведамляць мне пра публікацыі @{name}", "account.disable_notifications": "Не паведамляць мне пра публікацыі @{name}",
"account.domain_blocked": "Дамен заблакаваны", "account.domain_blocked": "Дамен заблакаваны",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Адзначыць прачытаным", "conversation.mark_as_read": "Адзначыць прачытаным",
"conversation.open": "Прагледзець размову", "conversation.open": "Прагледзець размову",
"conversation.with": "З {names}", "conversation.with": "З {names}",
"copy_icon_button.copied": "Скапіявана ў буфер абмену",
"copypaste.copied": "Скапіравана", "copypaste.copied": "Скапіравана",
"copypaste.copy_to_clipboard": "Капіраваць у буфер абмену", "copypaste.copy_to_clipboard": "Капіраваць у буфер абмену",
"directory.federated": "З вядомага федэсвету", "directory.federated": "З вядомага федэсвету",
@ -201,7 +203,7 @@
"disabled_account_banner.text": "Ваш уліковы запіс {disabledAccount} часова адключаны.", "disabled_account_banner.text": "Ваш уліковы запіс {disabledAccount} часова адключаны.",
"dismissable_banner.community_timeline": "Гэта самыя апошнія допісы ад людзей, уліковыя запісы якіх размяшчаюцца на {domain}.", "dismissable_banner.community_timeline": "Гэта самыя апошнія допісы ад людзей, уліковыя запісы якіх размяшчаюцца на {domain}.",
"dismissable_banner.dismiss": "Адхіліць", "dismissable_banner.dismiss": "Адхіліць",
"dismissable_banner.explore_links": "Гэтыя навіны абмяркоўваюцца прама зараз на гэтым і іншых серверах дэцэнтралізаванай сеткі.", "dismissable_banner.explore_links": "Гэтыя навіны абмяркоўваюцца цяпер на гэтым і іншых серверах дэцэнтралізаванай сеткі.",
"dismissable_banner.explore_statuses": "Допісы з гэтага і іншых сервераў дэцэнтралізаванай сеткі, якія набіраюць папулярнасць прама зараз.", "dismissable_banner.explore_statuses": "Допісы з гэтага і іншых сервераў дэцэнтралізаванай сеткі, якія набіраюць папулярнасць прама зараз.",
"dismissable_banner.explore_tags": "Гэтыя хэштэгі зараз набіраюць папулярнасць сярод людзей на гэтым і іншых серверах дэцэнтралізаванай сеткі", "dismissable_banner.explore_tags": "Гэтыя хэштэгі зараз набіраюць папулярнасць сярод людзей на гэтым і іншых серверах дэцэнтралізаванай сеткі",
"dismissable_banner.public_timeline": "Гэта апошнія публічныя допісы людзей з усей сеткі, за якімі сочаць карыстальнікі {domain}.", "dismissable_banner.public_timeline": "Гэта апошнія публічныя допісы людзей з усей сеткі, за якімі сочаць карыстальнікі {domain}.",
@ -222,6 +224,7 @@
"emoji_button.search_results": "Вынікі пошуку", "emoji_button.search_results": "Вынікі пошуку",
"emoji_button.symbols": "Сімвалы", "emoji_button.symbols": "Сімвалы",
"emoji_button.travel": "Падарожжы і месцы", "emoji_button.travel": "Падарожжы і месцы",
"empty_column.account_hides_collections": "Гэты карыстальнік вырашыў схаваць гэтую інфармацыю",
"empty_column.account_suspended": "Уліковы запіс прыпынены", "empty_column.account_suspended": "Уліковы запіс прыпынены",
"empty_column.account_timeline": "Тут няма допісаў!", "empty_column.account_timeline": "Тут няма допісаў!",
"empty_column.account_unavailable": "Профіль недаступны", "empty_column.account_unavailable": "Профіль недаступны",
@ -389,7 +392,7 @@
"lists.search": "Шукайце сярод людзей, на якіх Вы падпісаны", "lists.search": "Шукайце сярод людзей, на якіх Вы падпісаны",
"lists.subheading": "Вашыя спісы", "lists.subheading": "Вашыя спісы",
"load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}", "load_pending": "{count, plural, one {# новы элемент} few {# новыя элементы} many {# новых элементаў} other {# новых элементаў}}",
"loading_indicator.label": "Загрузка...", "loading_indicator.label": "Загрузка",
"media_gallery.toggle_visible": "{number, plural, one {Схаваць відарыс} other {Схаваць відарысы}}", "media_gallery.toggle_visible": "{number, plural, one {Схаваць відарыс} other {Схаваць відарысы}}",
"moved_to_account_banner.text": "Ваш уліковы запіс {disabledAccount} зараз адключаны таму што вы перанесены на {movedToAccount}.", "moved_to_account_banner.text": "Ваш уліковы запіс {disabledAccount} зараз адключаны таму што вы перанесены на {movedToAccount}.",
"mute_modal.duration": "Працягласць", "mute_modal.duration": "Працягласць",
@ -478,10 +481,21 @@
"onboarding.follows.empty": "На жаль, зараз немагчыма паказаць вынікі. Вы можаце паспрабаваць выкарыстоўваць пошук і праглядзець старонку агляду, каб знайсці людзей, на якіх можна падпісацца, або паўтарыце спробу пазней.", "onboarding.follows.empty": "На жаль, зараз немагчыма паказаць вынікі. Вы можаце паспрабаваць выкарыстоўваць пошук і праглядзець старонку агляду, каб знайсці людзей, на якіх можна падпісацца, або паўтарыце спробу пазней.",
"onboarding.follows.lead": "Вы самі ствараеце свой хатні канал. Чым больш людзей вы падпішаце, тым больш актыўна і цікавей гэта будзе. Гэтыя профілі могуць стаць добрай адпраўной кропкай — вы заўсёды можаце адмяніць падпіску на іх пазней!", "onboarding.follows.lead": "Вы самі ствараеце свой хатні канал. Чым больш людзей вы падпішаце, тым больш актыўна і цікавей гэта будзе. Гэтыя профілі могуць стаць добрай адпраўной кропкай — вы заўсёды можаце адмяніць падпіску на іх пазней!",
"onboarding.follows.title": "Папулярна на Mastodon", "onboarding.follows.title": "Папулярна на Mastodon",
"onboarding.profile.discoverable": "Уключыць профіль і допісы ў алгарытмы рэкамендацый",
"onboarding.profile.display_name": "Бачнае імя",
"onboarding.profile.display_name_hint": "Ваша поўнае імя або ваш псеўданім…",
"onboarding.profile.indexable": "Індэксаваць публічныя допісы ў пошукавых сістэмах",
"onboarding.profile.lead": "Вы заўсёды можаце выканаць гэта пазней у Наладах, дзе даступна яшчэ больш параметраў.",
"onboarding.profile.note": "Біяграфія",
"onboarding.profile.note_hint": "Вы можаце @згадаць іншых людзей або выкарыстоўваць #хэштэгі…",
"onboarding.profile.save_and_continue": "Захаваць і працягнуць",
"onboarding.profile.title": "Налады профілю",
"onboarding.profile.upload_avatar": "Загрузіць фота профілю",
"onboarding.profile.upload_header": "Загрузіць шапку профілю",
"onboarding.share.lead": "Дайце людзям ведаць, як яны могуць знайсці вас на Mastodon!", "onboarding.share.lead": "Дайце людзям ведаць, як яны могуць знайсці вас на Mastodon!",
"onboarding.share.message": "Я {username} на #Mastodon! Сачыце за мной на {url}", "onboarding.share.message": "Я {username} на #Mastodon! Сачыце за мной на {url}",
"onboarding.share.next_steps": "Магчымыя наступныя крокі:", "onboarding.share.next_steps": "Магчымыя наступныя крокі:",
"onboarding.share.title": "Падзяліцеся сваім профілем", "onboarding.share.title": "Абагульце свой профіль",
"onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:", "onboarding.start.lead": "Your new Mastodon account is ready to go. Here's how you can make the most of it:",
"onboarding.start.skip": "Want to skip right ahead?", "onboarding.start.skip": "Want to skip right ahead?",
"onboarding.start.title": "Вы зрабілі гэта!", "onboarding.start.title": "Вы зрабілі гэта!",
@ -492,7 +506,7 @@
"onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.", "onboarding.steps.setup_profile.body": "Others are more likely to interact with you with a filled out profile.",
"onboarding.steps.setup_profile.title": "Customize your profile", "onboarding.steps.setup_profile.title": "Customize your profile",
"onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!", "onboarding.steps.share_profile.body": "Let your friends know how to find you on Mastodon!",
"onboarding.steps.share_profile.title": "Share your profile", "onboarding.steps.share_profile.title": "Абагульць ваш профіль у Mastodon",
"onboarding.tips.2fa": "<strong>Ці вы ведаеце?</strong> Вы можаце абараніць свой уліковы запіс, усталяваўшы двухфактарную аўтэнтыфікацыю ў наладах уліковага запісу. Яна працуе з любой праграмай TOTP на ваш выбар, нумар тэлефона не патрэбны!", "onboarding.tips.2fa": "<strong>Ці вы ведаеце?</strong> Вы можаце абараніць свой уліковы запіс, усталяваўшы двухфактарную аўтэнтыфікацыю ў наладах уліковага запісу. Яна працуе з любой праграмай TOTP на ваш выбар, нумар тэлефона не патрэбны!",
"onboarding.tips.accounts_from_other_servers": "<strong>Ці вы ведаеце?</strong> Паколькі Mastodon дэцэнтралізаваны, некаторыя профілі, якія вам трапляюцца, будуць размяшчацца на іншых серверах, адрозных ад вашага. І ўсё ж вы можаце бесперашкодна ўзаемадзейнічаць з імі! Іх сервер пазначаны ў другой палове імя карыстальніка!", "onboarding.tips.accounts_from_other_servers": "<strong>Ці вы ведаеце?</strong> Паколькі Mastodon дэцэнтралізаваны, некаторыя профілі, якія вам трапляюцца, будуць размяшчацца на іншых серверах, адрозных ад вашага. І ўсё ж вы можаце бесперашкодна ўзаемадзейнічаць з імі! Іх сервер пазначаны ў другой палове імя карыстальніка!",
"onboarding.tips.migration": "<strong>Ці вы ведаеце?</strong> Калі вы адчуваеце, што {domain} не з'яўляецца для вас лепшым выбарам у будучыні, вы можаце перайсці на іншы сервер Mastodon, не губляючы сваіх падпісчыкаў. Вы нават можаце стварыць свой уласны сервер!", "onboarding.tips.migration": "<strong>Ці вы ведаеце?</strong> Калі вы адчуваеце, што {domain} не з'яўляецца для вас лепшым выбарам у будучыні, вы можаце перайсці на іншы сервер Mastodon, не губляючы сваіх падпісчыкаў. Вы нават можаце стварыць свой уласны сервер!",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Резултати от търсене", "emoji_button.search_results": "Резултати от търсене",
"emoji_button.symbols": "Символи", "emoji_button.symbols": "Символи",
"emoji_button.travel": "Пътуване и места", "emoji_button.travel": "Пътуване и места",
"empty_column.account_hides_collections": "Този потребител е избрал да не прави това сведение достъпно",
"empty_column.account_suspended": "Спрян акаунт", "empty_column.account_suspended": "Спрян акаунт",
"empty_column.account_timeline": "Тук няма публикации!", "empty_column.account_timeline": "Тук няма публикации!",
"empty_column.account_unavailable": "Профилът не е наличен", "empty_column.account_unavailable": "Профилът не е наличен",
@ -389,7 +390,7 @@
"lists.search": "Търсене измежду последваните", "lists.search": "Търсене измежду последваните",
"lists.subheading": "Вашите списъци", "lists.subheading": "Вашите списъци",
"load_pending": "{count, plural, one {# нов елемент} other {# нови елемента}}", "load_pending": "{count, plural, one {# нов елемент} other {# нови елемента}}",
"loading_indicator.label": "Зареждане...", "loading_indicator.label": "Зареждане",
"media_gallery.toggle_visible": "Скриване на {number, plural, one {изображение} other {изображения}}", "media_gallery.toggle_visible": "Скриване на {number, plural, one {изображение} other {изображения}}",
"moved_to_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен, защото се преместихте в {movedToAccount}.", "moved_to_account_banner.text": "Вашият акаунт {disabledAccount} сега е изключен, защото се преместихте в {movedToAccount}.",
"mute_modal.duration": "Времетраене", "mute_modal.duration": "Времетраене",
@ -478,6 +479,17 @@
"onboarding.follows.empty": "За съжаление, в момента не могат да се показват резултати. Може да опитате да употребявате търсене или да прегледате страницата за изследване, за да намерите страница за последване, или да опитате пак по-късно.", "onboarding.follows.empty": "За съжаление, в момента не могат да се показват резултати. Може да опитате да употребявате търсене или да прегледате страницата за изследване, за да намерите страница за последване, или да опитате пак по-късно.",
"onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!", "onboarding.follows.lead": "Може да бъдете куратор на началния си инфоканал. Последвайки повече хора, по-деен и по-интересен ще става. Тези профили може да са добра начална точка, от която винаги по-късно да спрете да следвате!",
"onboarding.follows.title": "Популярно в Mastodon", "onboarding.follows.title": "Популярно в Mastodon",
"onboarding.profile.discoverable": "Включване на профила и публикации в алгоритмите за откриване",
"onboarding.profile.display_name": "Името на показ",
"onboarding.profile.display_name_hint": "Вашето пълно име или псевдоним…",
"onboarding.profile.indexable": "Включване на обществени публикации в резултатите от търсене",
"onboarding.profile.lead": "Винаги може да завършите това по-късно в настройките, където дори има повече възможности за настройване.",
"onboarding.profile.note": "Биогр.",
"onboarding.profile.note_hint": "Може да @споменавате други хора или #хаштагове…",
"onboarding.profile.save_and_continue": "Запазване и продължаване",
"onboarding.profile.title": "Настройване на профила",
"onboarding.profile.upload_avatar": "Качване на снимка на профила",
"onboarding.profile.upload_header": "Качване на заглавка на профила",
"onboarding.share.lead": "Позволете на хората да знаят, че могат да ви намерят в Mastodon!", "onboarding.share.lead": "Позволете на хората да знаят, че могат да ви намерят в Mastodon!",
"onboarding.share.message": "Аз съм {username} в #Mastodon! Елате да ме последвате при {url}", "onboarding.share.message": "Аз съм {username} в #Mastodon! Елате да ме последвате при {url}",
"onboarding.share.next_steps": "Възможни следващи стъпки:", "onboarding.share.next_steps": "Възможни следващи стъпки:",

View file

@ -314,7 +314,6 @@
"lists.search": "যাদের অনুসরণ করেন তাদের ভেতরে খুঁজুন", "lists.search": "যাদের অনুসরণ করেন তাদের ভেতরে খুঁজুন",
"lists.subheading": "আপনার তালিকা", "lists.subheading": "আপনার তালিকা",
"load_pending": "{count, plural, one {# নতুন জিনিস} other {# নতুন জিনিস}}", "load_pending": "{count, plural, one {# নতুন জিনিস} other {# নতুন জিনিস}}",
"loading_indicator.label": "আসছে...",
"media_gallery.toggle_visible": "দৃশ্যতার অবস্থা বদলান", "media_gallery.toggle_visible": "দৃশ্যতার অবস্থা বদলান",
"mute_modal.duration": "সময়কাল", "mute_modal.duration": "সময়কাল",
"mute_modal.hide_notifications": "এই ব্যবহারকারীর প্রজ্ঞাপন বন্ধ করবেন ?", "mute_modal.hide_notifications": "এই ব্যবহারকারীর প্রজ্ঞাপন বন্ধ করবেন ?",

View file

@ -329,7 +329,6 @@
"lists.search": "Klask e-touez tud heuliet ganeoc'h", "lists.search": "Klask e-touez tud heuliet ganeoc'h",
"lists.subheading": "Ho listennoù", "lists.subheading": "Ho listennoù",
"load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}", "load_pending": "{count, plural, one {# dra nevez} other {# dra nevez}}",
"loading_indicator.label": "O kargañ...",
"media_gallery.toggle_visible": "{number, plural, one {Kuzhat ar skeudenn} other {Kuzhat ar skeudenn}}", "media_gallery.toggle_visible": "{number, plural, one {Kuzhat ar skeudenn} other {Kuzhat ar skeudenn}}",
"mute_modal.duration": "Padelezh", "mute_modal.duration": "Padelezh",
"mute_modal.hide_notifications": "Kuzhat kemenadennoù eus an implijer-se ?", "mute_modal.hide_notifications": "Kuzhat kemenadennoù eus an implijer-se ?",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Resultats de la cerca", "emoji_button.search_results": "Resultats de la cerca",
"emoji_button.symbols": "Símbols", "emoji_button.symbols": "Símbols",
"emoji_button.travel": "Viatges i llocs", "emoji_button.travel": "Viatges i llocs",
"empty_column.account_hides_collections": "Aquest usuari ha elegit no mostrar aquesta informació",
"empty_column.account_suspended": "Compte suspès", "empty_column.account_suspended": "Compte suspès",
"empty_column.account_timeline": "No hi ha tuts aquí!", "empty_column.account_timeline": "No hi ha tuts aquí!",
"empty_column.account_unavailable": "Perfil no disponible", "empty_column.account_unavailable": "Perfil no disponible",
@ -389,7 +390,6 @@
"lists.search": "Cerca entre les persones que segueixes", "lists.search": "Cerca entre les persones que segueixes",
"lists.subheading": "Les teves llistes", "lists.subheading": "Les teves llistes",
"load_pending": "{count, plural, one {# element nou} other {# elements nous}}", "load_pending": "{count, plural, one {# element nou} other {# elements nous}}",
"loading_indicator.label": "Es carrega...",
"media_gallery.toggle_visible": "{number, plural, one {Amaga la imatge} other {Amaga les imatges}}", "media_gallery.toggle_visible": "{number, plural, one {Amaga la imatge} other {Amaga les imatges}}",
"moved_to_account_banner.text": "El teu compte {disabledAccount} està desactivat perquè l'has mogut a {movedToAccount}.", "moved_to_account_banner.text": "El teu compte {disabledAccount} està desactivat perquè l'has mogut a {movedToAccount}.",
"mute_modal.duration": "Durada", "mute_modal.duration": "Durada",

View file

@ -342,7 +342,6 @@
"lists.search": "بگەڕێ لەناو ئەو کەسانەی کە شوێنیان کەوتویت", "lists.search": "بگەڕێ لەناو ئەو کەسانەی کە شوێنیان کەوتویت",
"lists.subheading": "لیستەکانت", "lists.subheading": "لیستەکانت",
"load_pending": "{count, plural, one {# بەڕگەی نوێ} other {# بەڕگەی نوێ}}", "load_pending": "{count, plural, one {# بەڕگەی نوێ} other {# بەڕگەی نوێ}}",
"loading_indicator.label": "بارکردن...",
"media_gallery.toggle_visible": "شاردنەوەی {number, plural, one {image} other {images}}", "media_gallery.toggle_visible": "شاردنەوەی {number, plural, one {image} other {images}}",
"moved_to_account_banner.text": "ئەکاونتەکەت {disabledAccount} لە ئێستادا لەکارخراوە چونکە تۆ چوویتە {movedToAccount}.", "moved_to_account_banner.text": "ئەکاونتەکەت {disabledAccount} لە ئێستادا لەکارخراوە چونکە تۆ چوویتە {movedToAccount}.",
"mute_modal.duration": "ماوە", "mute_modal.duration": "ماوە",

View file

@ -236,7 +236,6 @@
"lists.search": "Circà indè i vostr'abbunamenti", "lists.search": "Circà indè i vostr'abbunamenti",
"lists.subheading": "E vo liste", "lists.subheading": "E vo liste",
"load_pending": "{count, plural, one {# entrata nova} other {# entrate nove}}", "load_pending": "{count, plural, one {# entrata nova} other {# entrate nove}}",
"loading_indicator.label": "Caricamentu...",
"media_gallery.toggle_visible": "Piattà {number, plural, one {ritrattu} other {ritratti}}", "media_gallery.toggle_visible": "Piattà {number, plural, one {ritrattu} other {ritratti}}",
"mute_modal.duration": "Durata", "mute_modal.duration": "Durata",
"mute_modal.hide_notifications": "Piattà nutificazione da st'utilizatore?", "mute_modal.hide_notifications": "Piattà nutificazione da st'utilizatore?",

View file

@ -21,6 +21,7 @@
"account.blocked": "Blokovaný", "account.blocked": "Blokovaný",
"account.browse_more_on_origin_server": "Více na původním profilu", "account.browse_more_on_origin_server": "Více na původním profilu",
"account.cancel_follow_request": "Zrušit žádost o sledování", "account.cancel_follow_request": "Zrušit žádost o sledování",
"account.copy": "Kopírovat odkaz na profil",
"account.direct": "Soukromě zmínit @{name}", "account.direct": "Soukromě zmínit @{name}",
"account.disable_notifications": "Přestat mě upozorňovat, když @{name} zveřejní příspěvek", "account.disable_notifications": "Přestat mě upozorňovat, když @{name} zveřejní příspěvek",
"account.domain_blocked": "Doména blokována", "account.domain_blocked": "Doména blokována",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Označit jako přečtené", "conversation.mark_as_read": "Označit jako přečtené",
"conversation.open": "Zobrazit konverzaci", "conversation.open": "Zobrazit konverzaci",
"conversation.with": "S {names}", "conversation.with": "S {names}",
"copy_icon_button.copied": "Zkopírováno do schránky",
"copypaste.copied": "Zkopírováno", "copypaste.copied": "Zkopírováno",
"copypaste.copy_to_clipboard": "Zkopírovat do schránky", "copypaste.copy_to_clipboard": "Zkopírovat do schránky",
"directory.federated": "Ze známého fedivesmíru", "directory.federated": "Ze známého fedivesmíru",
@ -222,6 +224,7 @@
"emoji_button.search_results": "Výsledky hledání", "emoji_button.search_results": "Výsledky hledání",
"emoji_button.symbols": "Symboly", "emoji_button.symbols": "Symboly",
"emoji_button.travel": "Cestování a místa", "emoji_button.travel": "Cestování a místa",
"empty_column.account_hides_collections": "Tento uživatel se rozhodl nezveřejňovat tuto informaci",
"empty_column.account_suspended": "Účet je pozastaven", "empty_column.account_suspended": "Účet je pozastaven",
"empty_column.account_timeline": "Nejsou tu žádné příspěvky!", "empty_column.account_timeline": "Nejsou tu žádné příspěvky!",
"empty_column.account_unavailable": "Profil není dostupný", "empty_column.account_unavailable": "Profil není dostupný",
@ -385,7 +388,6 @@
"lists.search": "Hledejte mezi lidmi, které sledujete", "lists.search": "Hledejte mezi lidmi, které sledujete",
"lists.subheading": "Vaše seznamy", "lists.subheading": "Vaše seznamy",
"load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}", "load_pending": "{count, plural, one {# nová položka} few {# nové položky} many {# nových položek} other {# nových položek}}",
"loading_indicator.label": "Načítání...",
"media_gallery.toggle_visible": "{number, plural, one {Skrýt obrázek} few {Skrýt obrázky} many {Skrýt obrázky} other {Skrýt obrázky}}", "media_gallery.toggle_visible": "{number, plural, one {Skrýt obrázek} few {Skrýt obrázky} many {Skrýt obrázky} other {Skrýt obrázky}}",
"moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.", "moved_to_account_banner.text": "Váš účet {disabledAccount} je momentálně deaktivován, protože jste se přesunul/a na {movedToAccount}.",
"mute_modal.duration": "Trvání", "mute_modal.duration": "Trvání",

View file

@ -191,6 +191,7 @@
"conversation.mark_as_read": "Nodi fel wedi'i ddarllen", "conversation.mark_as_read": "Nodi fel wedi'i ddarllen",
"conversation.open": "Gweld sgwrs", "conversation.open": "Gweld sgwrs",
"conversation.with": "Gyda {names}", "conversation.with": "Gyda {names}",
"copy_icon_button.copied": "Copïwyd i'r clipfwrdd",
"copypaste.copied": "Wedi ei gopïo", "copypaste.copied": "Wedi ei gopïo",
"copypaste.copy_to_clipboard": "Copïo i'r clipfwrdd", "copypaste.copy_to_clipboard": "Copïo i'r clipfwrdd",
"directory.federated": "O'r ffedysawd cyfan", "directory.federated": "O'r ffedysawd cyfan",
@ -390,7 +391,7 @@
"lists.search": "Chwilio ymysg pobl rydych yn eu dilyn", "lists.search": "Chwilio ymysg pobl rydych yn eu dilyn",
"lists.subheading": "Eich rhestrau", "lists.subheading": "Eich rhestrau",
"load_pending": "{count, plural, one {# eitem newydd} other {# eitem newydd}}", "load_pending": "{count, plural, one {# eitem newydd} other {# eitem newydd}}",
"loading_indicator.label": "Llwytho...", "loading_indicator.label": "Yn llwytho…",
"media_gallery.toggle_visible": "{number, plural, one {Cuddio delwedd} other {Cuddio delwedd}}", "media_gallery.toggle_visible": "{number, plural, one {Cuddio delwedd} other {Cuddio delwedd}}",
"moved_to_account_banner.text": "Ar hyn y bryd, mae eich cyfrif {disabledAccount} wedi ei analluogi am i chi symud i {movedToAccount}.", "moved_to_account_banner.text": "Ar hyn y bryd, mae eich cyfrif {disabledAccount} wedi ei analluogi am i chi symud i {movedToAccount}.",
"mute_modal.duration": "Hyd", "mute_modal.duration": "Hyd",
@ -479,6 +480,11 @@
"onboarding.follows.empty": "Yn anffodus, nid oes modd dangos unrhyw ganlyniadau ar hyn o bryd. Gallwch geisio defnyddio chwilio neu bori'r dudalen archwilio i ddod o hyd i bobl i'w dilyn, neu ceisio eto yn nes ymlaen.", "onboarding.follows.empty": "Yn anffodus, nid oes modd dangos unrhyw ganlyniadau ar hyn o bryd. Gallwch geisio defnyddio chwilio neu bori'r dudalen archwilio i ddod o hyd i bobl i'w dilyn, neu ceisio eto yn nes ymlaen.",
"onboarding.follows.lead": "Rydych chi'n curadu eich ffrwd gartref eich hun. Po fwyaf o bobl y byddwch chi'n eu dilyn, y mwyaf egnïol a diddorol fydd hi. Gall y proffiliau hyn fod yn fan cychwyn da - gallwch chi bob amser eu dad-ddilyn yn nes ymlaen:", "onboarding.follows.lead": "Rydych chi'n curadu eich ffrwd gartref eich hun. Po fwyaf o bobl y byddwch chi'n eu dilyn, y mwyaf egnïol a diddorol fydd hi. Gall y proffiliau hyn fod yn fan cychwyn da - gallwch chi bob amser eu dad-ddilyn yn nes ymlaen:",
"onboarding.follows.title": "Yn boblogaidd ar Mastodon", "onboarding.follows.title": "Yn boblogaidd ar Mastodon",
"onboarding.profile.display_name_hint": "Eich enw llawn neu'ch enw hwyl…",
"onboarding.profile.note": "Bywgraffiad",
"onboarding.profile.note_hint": "Gallwch @grybwyll pobl eraill neu #hashnodau…",
"onboarding.profile.save_and_continue": "Cadw a pharhau",
"onboarding.profile.title": "Gosodiad proffil",
"onboarding.share.lead": "Cofiwch ddweud wrth bobl sut y gallan nhw ddod o hyd i chi ar Mastodon!", "onboarding.share.lead": "Cofiwch ddweud wrth bobl sut y gallan nhw ddod o hyd i chi ar Mastodon!",
"onboarding.share.message": "Fi yw {username} ar #Mastodon! Dewch i'm dilyn i yn {url}", "onboarding.share.message": "Fi yw {username} ar #Mastodon! Dewch i'm dilyn i yn {url}",
"onboarding.share.next_steps": "Camau nesaf posib:", "onboarding.share.next_steps": "Camau nesaf posib:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Blokeret", "account.blocked": "Blokeret",
"account.browse_more_on_origin_server": "Se mere på den oprindelige profil", "account.browse_more_on_origin_server": "Se mere på den oprindelige profil",
"account.cancel_follow_request": "Annullér anmodning om at følge", "account.cancel_follow_request": "Annullér anmodning om at følge",
"account.copy": "Kopiér link til profil",
"account.direct": "Privat omtale @{name}", "account.direct": "Privat omtale @{name}",
"account.disable_notifications": "Advisér mig ikke længere, når @{name} poster", "account.disable_notifications": "Advisér mig ikke længere, når @{name} poster",
"account.domain_blocked": "Domæne blokeret", "account.domain_blocked": "Domæne blokeret",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Markér som læst", "conversation.mark_as_read": "Markér som læst",
"conversation.open": "Vis samtale", "conversation.open": "Vis samtale",
"conversation.with": "Med {names}", "conversation.with": "Med {names}",
"copy_icon_button.copied": "Kopieret til udklipsholderen",
"copypaste.copied": "Kopieret", "copypaste.copied": "Kopieret",
"copypaste.copy_to_clipboard": "Kopiér til udklipsholder", "copypaste.copy_to_clipboard": "Kopiér til udklipsholder",
"directory.federated": "Fra kendt fedivers", "directory.federated": "Fra kendt fedivers",
@ -390,7 +392,7 @@
"lists.search": "Søg blandt personer, som følges", "lists.search": "Søg blandt personer, som følges",
"lists.subheading": "Dine lister", "lists.subheading": "Dine lister",
"load_pending": "{count, plural, one {# nyt emne} other {# nye emner}}", "load_pending": "{count, plural, one {# nyt emne} other {# nye emner}}",
"loading_indicator.label": "Indlæser...", "loading_indicator.label": "Indlæser",
"media_gallery.toggle_visible": "{number, plural, one {Skjul billede} other {Skjul billeder}}", "media_gallery.toggle_visible": "{number, plural, one {Skjul billede} other {Skjul billeder}}",
"moved_to_account_banner.text": "Din konto {disabledAccount} er pt. deaktiveret, da du flyttede til {movedToAccount}.", "moved_to_account_banner.text": "Din konto {disabledAccount} er pt. deaktiveret, da du flyttede til {movedToAccount}.",
"mute_modal.duration": "Varighed", "mute_modal.duration": "Varighed",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Ingen resultater tilgængelige pt. Prøv at bruge søgning eller gennemse siden for at finde personer at følge, eller forsøg igen senere.", "onboarding.follows.empty": "Ingen resultater tilgængelige pt. Prøv at bruge søgning eller gennemse siden for at finde personer at følge, eller forsøg igen senere.",
"onboarding.follows.lead": "Man kurerer sin eget hjemme-feed. Jo flere personer man følger, des mere aktiv og interessant vil det være. Disse profiler kan være et godt udgangspunkt de kan altid fjernes senere!", "onboarding.follows.lead": "Man kurerer sin eget hjemme-feed. Jo flere personer man følger, des mere aktiv og interessant vil det være. Disse profiler kan være et godt udgangspunkt de kan altid fjernes senere!",
"onboarding.follows.title": "Populært på Mastodon", "onboarding.follows.title": "Populært på Mastodon",
"onboarding.profile.discoverable": "Fremhæv profil og indlæg i detekteringsalgoritmer",
"onboarding.profile.display_name": "Visningsnavn",
"onboarding.profile.display_name_hint": "Fulde navn eller dit sjove navn…",
"onboarding.profile.indexable": "Medtag offentlige indlæg i søgeresultater",
"onboarding.profile.lead": "Dette kan altid færdiggøres senere i indstillingerne, hvor endnu flere tilpasningsmuligheder forefindes.",
"onboarding.profile.note": "Bio",
"onboarding.profile.note_hint": "Man kan @omtale andre personer eller #hashtags…",
"onboarding.profile.save_and_continue": "Gem og fortsæt",
"onboarding.profile.title": "Profilopsætning",
"onboarding.profile.upload_avatar": "Upload profilbillede",
"onboarding.profile.upload_header": "Upload profiloverskrift",
"onboarding.share.lead": "Lad folk vide, hvordan de kan finde dig på Mastodon!", "onboarding.share.lead": "Lad folk vide, hvordan de kan finde dig på Mastodon!",
"onboarding.share.message": "Jeg er {username} på #Mastodon! Følg mig på {url}", "onboarding.share.message": "Jeg er {username} på #Mastodon! Følg mig på {url}",
"onboarding.share.next_steps": "Mulige næste trin:", "onboarding.share.next_steps": "Mulige næste trin:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Blockiert", "account.blocked": "Blockiert",
"account.browse_more_on_origin_server": "Mehr auf dem Originalprofil durchsuchen", "account.browse_more_on_origin_server": "Mehr auf dem Originalprofil durchsuchen",
"account.cancel_follow_request": "Folgeanfrage zurückziehen", "account.cancel_follow_request": "Folgeanfrage zurückziehen",
"account.copy": "Link zum Profil kopieren",
"account.direct": "@{name} privat erwähnen", "account.direct": "@{name} privat erwähnen",
"account.disable_notifications": "Höre auf mich zu benachrichtigen wenn @{name} etwas postet", "account.disable_notifications": "Höre auf mich zu benachrichtigen wenn @{name} etwas postet",
"account.domain_blocked": "Domain versteckt", "account.domain_blocked": "Domain versteckt",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Als gelesen markieren", "conversation.mark_as_read": "Als gelesen markieren",
"conversation.open": "Unterhaltung anzeigen", "conversation.open": "Unterhaltung anzeigen",
"conversation.with": "Mit {names}", "conversation.with": "Mit {names}",
"copy_icon_button.copied": "In die Zwischenablage kopiert",
"copypaste.copied": "Kopiert", "copypaste.copied": "Kopiert",
"copypaste.copy_to_clipboard": "In die Zwischenablage kopieren", "copypaste.copy_to_clipboard": "In die Zwischenablage kopieren",
"directory.federated": "Aus bekanntem Fediverse", "directory.federated": "Aus bekanntem Fediverse",
@ -390,7 +392,7 @@
"lists.search": "Suche nach Leuten, denen du folgst", "lists.search": "Suche nach Leuten, denen du folgst",
"lists.subheading": "Deine Listen", "lists.subheading": "Deine Listen",
"load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}", "load_pending": "{count, plural, one {# neuer Beitrag} other {# neue Beiträge}}",
"loading_indicator.label": "Wird geladen …", "loading_indicator.label": "Wird geladen …",
"media_gallery.toggle_visible": "{number, plural, one {Medium ausblenden} other {Medien ausblenden}}", "media_gallery.toggle_visible": "{number, plural, one {Medium ausblenden} other {Medien ausblenden}}",
"moved_to_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert, weil du zu {movedToAccount} umgezogen bist.", "moved_to_account_banner.text": "Dein Konto {disabledAccount} ist derzeit deaktiviert, weil du zu {movedToAccount} umgezogen bist.",
"mute_modal.duration": "Dauer", "mute_modal.duration": "Dauer",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Bedauerlicherweise können aktuell keine Ergebnisse angezeigt werden. Du kannst die Suche verwenden oder den Reiter „Entdecken“ auswählen, um neue Leute zum Folgen zu finden oder du versuchst es später erneut.", "onboarding.follows.empty": "Bedauerlicherweise können aktuell keine Ergebnisse angezeigt werden. Du kannst die Suche verwenden oder den Reiter „Entdecken“ auswählen, um neue Leute zum Folgen zu finden oder du versuchst es später erneut.",
"onboarding.follows.lead": "Deine Startseite ist der primäre Anlaufpunkt, um Mastodon zu erleben. Je mehr Profilen du folgst, umso aktiver und interessanter wird sie. Damit du direkt loslegen kannst, gibt es hier ein paar Vorschläge:", "onboarding.follows.lead": "Deine Startseite ist der primäre Anlaufpunkt, um Mastodon zu erleben. Je mehr Profilen du folgst, umso aktiver und interessanter wird sie. Damit du direkt loslegen kannst, gibt es hier ein paar Vorschläge:",
"onboarding.follows.title": "Personalisiere deine Startseite", "onboarding.follows.title": "Personalisiere deine Startseite",
"onboarding.profile.discoverable": "Profil und Beiträge in Suchalgorithmen berücksichtigen",
"onboarding.profile.display_name": "Anzeigename",
"onboarding.profile.display_name_hint": "Dein richtiger Name oder dein Fantasiename …",
"onboarding.profile.indexable": "Öffentliche Beiträge in die Suchergebnisse einbeziehen",
"onboarding.profile.lead": "Du kannst das später in den Einstellungen vervollständigen, wo noch mehr Anpassungsmöglichkeiten zur Verfügung stehen.",
"onboarding.profile.note": "Über mich",
"onboarding.profile.note_hint": "Du kannst andere @Profile erwähnen oder #Hashtags verwenden …",
"onboarding.profile.save_and_continue": "Speichern und fortsetzen",
"onboarding.profile.title": "Profil einrichten",
"onboarding.profile.upload_avatar": "Profilbild hochladen",
"onboarding.profile.upload_header": "Titelbild hochladen",
"onboarding.share.lead": "Lass die Leute wissen, wie sie dich auf Mastodon finden können!", "onboarding.share.lead": "Lass die Leute wissen, wie sie dich auf Mastodon finden können!",
"onboarding.share.message": "Ich bin {username} auf #Mastodon! Folge mir auf {url}", "onboarding.share.message": "Ich bin {username} auf #Mastodon! Folge mir auf {url}",
"onboarding.share.next_steps": "Mögliche nächste Schritte:", "onboarding.share.next_steps": "Mögliche nächste Schritte:",

View file

@ -345,7 +345,6 @@
"lists.search": "Αναζήτησε μεταξύ των ανθρώπων που ακουλουθείς", "lists.search": "Αναζήτησε μεταξύ των ανθρώπων που ακουλουθείς",
"lists.subheading": "Οι λίστες σου", "lists.subheading": "Οι λίστες σου",
"load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}", "load_pending": "{count, plural, one {# νέο στοιχείο} other {# νέα στοιχεία}}",
"loading_indicator.label": "Φορτώνει...",
"media_gallery.toggle_visible": "{number, plural, one {Απόκρυψη εικόνας} other {Απόκρυψη εικόνων}}", "media_gallery.toggle_visible": "{number, plural, one {Απόκρυψη εικόνας} other {Απόκρυψη εικόνων}}",
"moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.", "moved_to_account_banner.text": "Ο λογαριασμός σου {disabledAccount} είναι προσωρινά απενεργοποιημένος επειδή μεταφέρθηκες στον {movedToAccount}.",
"mute_modal.duration": "Διάρκεια", "mute_modal.duration": "Διάρκεια",

View file

@ -389,7 +389,7 @@
"lists.search": "Search among people you follow", "lists.search": "Search among people you follow",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"load_pending": "{count, plural, one {# new item} other {# new items}}", "load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading",
"media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}", "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
"moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.", "moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.",
"mute_modal.duration": "Duration", "mute_modal.duration": "Duration",
@ -478,6 +478,17 @@
"onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.", "onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Personalize your home feed", "onboarding.follows.title": "Personalize your home feed",
"onboarding.profile.discoverable": "Feature profile and posts in discovery algorithms",
"onboarding.profile.display_name": "Display name",
"onboarding.profile.display_name_hint": "Your full name or your fun name…",
"onboarding.profile.indexable": "Include public posts in search results",
"onboarding.profile.lead": "You can always complete this later in the settings, where even more customisation options are available.",
"onboarding.profile.note": "Bio",
"onboarding.profile.note_hint": "You can @mention other people or #hashtags…",
"onboarding.profile.save_and_continue": "Save and continue",
"onboarding.profile.title": "Profile setup",
"onboarding.profile.upload_avatar": "Upload profile picture",
"onboarding.profile.upload_header": "Upload profile header",
"onboarding.share.lead": "Let people know how they can find you on Mastodon!", "onboarding.share.lead": "Let people know how they can find you on Mastodon!",
"onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}", "onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}",
"onboarding.share.next_steps": "Possible next steps:", "onboarding.share.next_steps": "Possible next steps:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Blocked", "account.blocked": "Blocked",
"account.browse_more_on_origin_server": "Browse more on the original profile", "account.browse_more_on_origin_server": "Browse more on the original profile",
"account.cancel_follow_request": "Cancel follow", "account.cancel_follow_request": "Cancel follow",
"account.copy": "Copy link to profile",
"account.direct": "Privately mention @{name}", "account.direct": "Privately mention @{name}",
"account.disable_notifications": "Stop notifying me when @{name} posts", "account.disable_notifications": "Stop notifying me when @{name} posts",
"account.domain_blocked": "Domain blocked", "account.domain_blocked": "Domain blocked",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Mark as read", "conversation.mark_as_read": "Mark as read",
"conversation.open": "View conversation", "conversation.open": "View conversation",
"conversation.with": "With {names}", "conversation.with": "With {names}",
"copy_icon_button.copied": "Copied to clipboard",
"copypaste.copied": "Copied", "copypaste.copied": "Copied",
"copypaste.copy_to_clipboard": "Copy to clipboard", "copypaste.copy_to_clipboard": "Copy to clipboard",
"directory.federated": "From known fediverse", "directory.federated": "From known fediverse",
@ -390,7 +392,7 @@
"lists.search": "Search among people you follow", "lists.search": "Search among people you follow",
"lists.subheading": "Your lists", "lists.subheading": "Your lists",
"load_pending": "{count, plural, one {# new item} other {# new items}}", "load_pending": "{count, plural, one {# new item} other {# new items}}",
"loading_indicator.label": "Loading...", "loading_indicator.label": "Loading",
"media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}", "media_gallery.toggle_visible": "{number, plural, one {Hide image} other {Hide images}}",
"moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.", "moved_to_account_banner.text": "Your account {disabledAccount} is currently disabled because you moved to {movedToAccount}.",
"mute_modal.duration": "Duration", "mute_modal.duration": "Duration",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.", "onboarding.follows.empty": "Unfortunately, no results can be shown right now. You can try using search or browsing the explore page to find people to follow, or try again later.",
"onboarding.follows.lead": "Your home feed is the primary way to experience Mastodon. The more people you follow, the more active and interesting it will be. To get you started, here are some suggestions:", "onboarding.follows.lead": "Your home feed is the primary way to experience Mastodon. The more people you follow, the more active and interesting it will be. To get you started, here are some suggestions:",
"onboarding.follows.title": "Personalize your home feed", "onboarding.follows.title": "Personalize your home feed",
"onboarding.profile.discoverable": "Make my profile discoverable",
"onboarding.profile.discoverable_hint": "When you opt in to discoverability on Mastodon, your posts may appear in search results and trending, and your profile may be suggested to people with similar interests to you.",
"onboarding.profile.display_name": "Display name",
"onboarding.profile.display_name_hint": "Your full name or your fun name…",
"onboarding.profile.lead": "You can always complete this later in the settings, where even more customization options are available.",
"onboarding.profile.note": "Bio",
"onboarding.profile.note_hint": "You can @mention other people or #hashtags…",
"onboarding.profile.save_and_continue": "Save and continue",
"onboarding.profile.title": "Profile setup",
"onboarding.profile.upload_avatar": "Upload profile picture",
"onboarding.profile.upload_header": "Upload profile header",
"onboarding.share.lead": "Let people know how they can find you on Mastodon!", "onboarding.share.lead": "Let people know how they can find you on Mastodon!",
"onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}", "onboarding.share.message": "I'm {username} on #Mastodon! Come follow me at {url}",
"onboarding.share.next_steps": "Possible next steps:", "onboarding.share.next_steps": "Possible next steps:",
@ -522,6 +535,7 @@
"privacy.unlisted.short": "Unlisted", "privacy.unlisted.short": "Unlisted",
"privacy_policy.last_updated": "Last updated {date}", "privacy_policy.last_updated": "Last updated {date}",
"privacy_policy.title": "Privacy Policy", "privacy_policy.title": "Privacy Policy",
"recommended": "Recommended",
"refresh": "Refresh", "refresh": "Refresh",
"regeneration_indicator.label": "Loading…", "regeneration_indicator.label": "Loading…",
"regeneration_indicator.sublabel": "Your home feed is being prepared!", "regeneration_indicator.sublabel": "Your home feed is being prepared!",

View file

@ -365,7 +365,6 @@
"lists.search": "Serĉi inter la homoj, kiujn vi sekvas", "lists.search": "Serĉi inter la homoj, kiujn vi sekvas",
"lists.subheading": "Viaj listoj", "lists.subheading": "Viaj listoj",
"load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}", "load_pending": "{count,plural, one {# nova elemento} other {# novaj elementoj}}",
"loading_indicator.label": "Ŝargado…",
"media_gallery.toggle_visible": "{number, plural, one {Kaŝi la bildon} other {Kaŝi la bildojn}}", "media_gallery.toggle_visible": "{number, plural, one {Kaŝi la bildon} other {Kaŝi la bildojn}}",
"moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.", "moved_to_account_banner.text": "Via konto {disabledAccount} estas malvalidigita ĉar vi movis ĝin al {movedToAccount}.",
"mute_modal.duration": "Daŭro", "mute_modal.duration": "Daŭro",

View file

@ -21,6 +21,7 @@
"account.blocked": "Bloqueado", "account.blocked": "Bloqueado",
"account.browse_more_on_origin_server": "Explorar más en el perfil original", "account.browse_more_on_origin_server": "Explorar más en el perfil original",
"account.cancel_follow_request": "Dejar de seguir", "account.cancel_follow_request": "Dejar de seguir",
"account.copy": "Copiar enlace al perfil",
"account.direct": "Mención privada a @{name}", "account.direct": "Mención privada a @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} envíe mensajes", "account.disable_notifications": "Dejar de notificarme cuando @{name} envíe mensajes",
"account.domain_blocked": "Dominio bloqueado", "account.domain_blocked": "Dominio bloqueado",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Marcar como leída", "conversation.mark_as_read": "Marcar como leída",
"conversation.open": "Ver conversación", "conversation.open": "Ver conversación",
"conversation.with": "Con {names}", "conversation.with": "Con {names}",
"copy_icon_button.copied": "Copiado en el portapapeles",
"copypaste.copied": "Copiado", "copypaste.copied": "Copiado",
"copypaste.copy_to_clipboard": "Copiar al portapapeles", "copypaste.copy_to_clipboard": "Copiar al portapapeles",
"directory.federated": "Desde fediverso conocido", "directory.federated": "Desde fediverso conocido",
@ -390,7 +392,7 @@
"lists.search": "Buscar entre la gente que seguís", "lists.search": "Buscar entre la gente que seguís",
"lists.subheading": "Tus listas", "lists.subheading": "Tus listas",
"load_pending": "{count, plural, one {# elemento nuevo} other {# elementos nuevos}}", "load_pending": "{count, plural, one {# elemento nuevo} other {# elementos nuevos}}",
"loading_indicator.label": "Cargando...", "loading_indicator.label": "Cargando",
"media_gallery.toggle_visible": "Ocultar {number, plural, one {imagen} other {imágenes}}", "media_gallery.toggle_visible": "Ocultar {number, plural, one {imagen} other {imágenes}}",
"moved_to_account_banner.text": "Tu cuenta {disabledAccount} está actualmente deshabilitada porque te mudaste a {movedToAccount}.", "moved_to_account_banner.text": "Tu cuenta {disabledAccount} está actualmente deshabilitada porque te mudaste a {movedToAccount}.",
"mute_modal.duration": "Duración", "mute_modal.duration": "Duración",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Podés intentar usar la búsqueda o navegar por la página de exploración para encontrar cuentas a las que seguir, o intentarlo de nuevo más tarde.", "onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Podés intentar usar la búsqueda o navegar por la página de exploración para encontrar cuentas a las que seguir, o intentarlo de nuevo más tarde.",
"onboarding.follows.lead": "Tu línea temporal de inicio es la forma principal de experimentar Mastodon. Cuanta más cuentas sigás, más activa e interesante será. Para empezar, acá tenés algunas sugerencias:", "onboarding.follows.lead": "Tu línea temporal de inicio es la forma principal de experimentar Mastodon. Cuanta más cuentas sigás, más activa e interesante será. Para empezar, acá tenés algunas sugerencias:",
"onboarding.follows.title": "Personalizá tu línea de tiempo principal", "onboarding.follows.title": "Personalizá tu línea de tiempo principal",
"onboarding.profile.discoverable": "Destacar perfil y mensajes en algoritmos de descubrimiento",
"onboarding.profile.display_name": "Nombre para mostrar",
"onboarding.profile.display_name_hint": "Tu nombre completo o tu pseudónimo…",
"onboarding.profile.indexable": "Incluir mensajes públicos en resultados de búsqueda",
"onboarding.profile.lead": "Siempre podés completar esto más tarde en la configuración, donde hay disponibles más opciones de personalización.",
"onboarding.profile.note": "Biografía",
"onboarding.profile.note_hint": "Podés @mencionar otras cuentas o usar #etiquetas…",
"onboarding.profile.save_and_continue": "Guardar y continuar",
"onboarding.profile.title": "Configuración del perfil",
"onboarding.profile.upload_avatar": "Subir avatar",
"onboarding.profile.upload_header": "Subir cabecera",
"onboarding.share.lead": "¡Decile a la gente cómo te pueden encontrar en Mastodon!", "onboarding.share.lead": "¡Decile a la gente cómo te pueden encontrar en Mastodon!",
"onboarding.share.message": "¡En #Mastodon soy «{username}»! Podés seguirme desde {url}", "onboarding.share.message": "¡En #Mastodon soy «{username}»! Podés seguirme desde {url}",
"onboarding.share.next_steps": "Posibles próximos pasos:", "onboarding.share.next_steps": "Posibles próximos pasos:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Bloqueado", "account.blocked": "Bloqueado",
"account.browse_more_on_origin_server": "Ver más en el perfil original", "account.browse_more_on_origin_server": "Ver más en el perfil original",
"account.cancel_follow_request": "Retirar solicitud de seguimiento", "account.cancel_follow_request": "Retirar solicitud de seguimiento",
"account.copy": "Copiar enlace al perfil",
"account.direct": "Mención privada @{name}", "account.direct": "Mención privada @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo", "account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
"account.domain_blocked": "Dominio oculto", "account.domain_blocked": "Dominio oculto",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Marcar como leído", "conversation.mark_as_read": "Marcar como leído",
"conversation.open": "Ver conversación", "conversation.open": "Ver conversación",
"conversation.with": "Con {names}", "conversation.with": "Con {names}",
"copy_icon_button.copied": "Copiado al portapapeles",
"copypaste.copied": "Copiado", "copypaste.copied": "Copiado",
"copypaste.copy_to_clipboard": "Copiar al portapapeles", "copypaste.copy_to_clipboard": "Copiar al portapapeles",
"directory.federated": "Desde el fediverso conocido", "directory.federated": "Desde el fediverso conocido",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Puedes intentar usar la búsqueda o navegar por la página de exploración para encontrar gente a la que seguir, o inténtalo de nuevo más tarde.", "onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Puedes intentar usar la búsqueda o navegar por la página de exploración para encontrar gente a la que seguir, o inténtalo de nuevo más tarde.",
"onboarding.follows.lead": "Tienes que personalizar tu inicio. Cuantas más personas sigas, más activo e interesante será. Estos perfiles pueden ser un buen punto de partida, ¡pero siempre puedes dejar de seguirlos más adelante!", "onboarding.follows.lead": "Tienes que personalizar tu inicio. Cuantas más personas sigas, más activo e interesante será. Estos perfiles pueden ser un buen punto de partida, ¡pero siempre puedes dejar de seguirlos más adelante!",
"onboarding.follows.title": "Popular en Mastodon", "onboarding.follows.title": "Popular en Mastodon",
"onboarding.profile.discoverable": "Destacar el perfil y las publicaciones en el algoritmo de descubrimiento",
"onboarding.profile.display_name": "Nombre a mostrar",
"onboarding.profile.display_name_hint": "Tu nombre completo o tu apodo…",
"onboarding.profile.indexable": "Incluir publicaciones públicas en los resultados de búsqueda",
"onboarding.profile.lead": "Siempre puedes completar esto más tarde en los ajustes, donde hay aún más opciones de personalización disponibles.",
"onboarding.profile.note": "Biografía",
"onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #hashtags…",
"onboarding.profile.save_and_continue": "Guardar y continuar",
"onboarding.profile.title": "Configuración del perfil",
"onboarding.profile.upload_avatar": "Subir foto de perfil",
"onboarding.profile.upload_header": "Subir foto de cabecera",
"onboarding.share.lead": "¡Dile a la gente cómo te pueden encontrar en Mastodon!", "onboarding.share.lead": "¡Dile a la gente cómo te pueden encontrar en Mastodon!",
"onboarding.share.message": "¡Soy {username} en #Mastodon! Ven a seguirme en {url}", "onboarding.share.message": "¡Soy {username} en #Mastodon! Ven a seguirme en {url}",
"onboarding.share.next_steps": "Posibles siguientes pasos:", "onboarding.share.next_steps": "Posibles siguientes pasos:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Bloqueado", "account.blocked": "Bloqueado",
"account.browse_more_on_origin_server": "Ver más en el perfil original", "account.browse_more_on_origin_server": "Ver más en el perfil original",
"account.cancel_follow_request": "Retirar solicitud de seguimiento", "account.cancel_follow_request": "Retirar solicitud de seguimiento",
"account.copy": "Copiar enlace al perfil",
"account.direct": "Mención privada a @{name}", "account.direct": "Mención privada a @{name}",
"account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo", "account.disable_notifications": "Dejar de notificarme cuando @{name} publique algo",
"account.domain_blocked": "Dominio bloqueado", "account.domain_blocked": "Dominio bloqueado",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Marcar como leído", "conversation.mark_as_read": "Marcar como leído",
"conversation.open": "Ver conversación", "conversation.open": "Ver conversación",
"conversation.with": "Con {names}", "conversation.with": "Con {names}",
"copy_icon_button.copied": "Copiado al portapapeles",
"copypaste.copied": "Copiado", "copypaste.copied": "Copiado",
"copypaste.copy_to_clipboard": "Copiar al portapapeles", "copypaste.copy_to_clipboard": "Copiar al portapapeles",
"directory.federated": "Desde el fediverso conocido", "directory.federated": "Desde el fediverso conocido",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Puedes intentar usar la búsqueda o navegar por la página de exploración para encontrar personas a las que seguir, o inténtalo de nuevo más tarde.", "onboarding.follows.empty": "Desafortunadamente, no se pueden mostrar resultados en este momento. Puedes intentar usar la búsqueda o navegar por la página de exploración para encontrar personas a las que seguir, o inténtalo de nuevo más tarde.",
"onboarding.follows.lead": "Tu línea de inicio es la forma principal de experimentar Mastodon. Cuanta más personas sigas, más activa e interesante será. Para empezar, aquí hay algunas sugerencias:", "onboarding.follows.lead": "Tu línea de inicio es la forma principal de experimentar Mastodon. Cuanta más personas sigas, más activa e interesante será. Para empezar, aquí hay algunas sugerencias:",
"onboarding.follows.title": "Personaliza tu línea de inicio", "onboarding.follows.title": "Personaliza tu línea de inicio",
"onboarding.profile.discoverable": "Destacar perfil y publicaciones en algoritmos de descubrimiento",
"onboarding.profile.display_name": "Nombre para mostrar",
"onboarding.profile.display_name_hint": "Tu nombre completo o tu apodo…",
"onboarding.profile.indexable": "Incluir publicaciones públicas en los resultados de búsqueda",
"onboarding.profile.lead": "Siempre puedes completar esto más tarde en los ajustes, donde hay aún más opciones de personalización disponibles.",
"onboarding.profile.note": "Biografía",
"onboarding.profile.note_hint": "Puedes @mencionar a otras personas o #etiquetas…",
"onboarding.profile.save_and_continue": "Guardar y continuar",
"onboarding.profile.title": "Configuración del perfil",
"onboarding.profile.upload_avatar": "Subir foto de perfil",
"onboarding.profile.upload_header": "Subir encabezado de perfil",
"onboarding.share.lead": "¡Cuéntale a otras personas cómo te pueden encontrar en Mastodon!", "onboarding.share.lead": "¡Cuéntale a otras personas cómo te pueden encontrar en Mastodon!",
"onboarding.share.message": "¡Soy {username} en #Mastodon! Ven a seguirme en {url}", "onboarding.share.message": "¡Soy {username} en #Mastodon! Ven a seguirme en {url}",
"onboarding.share.next_steps": "Posibles siguientes pasos:", "onboarding.share.next_steps": "Posibles siguientes pasos:",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Otsitulemused", "emoji_button.search_results": "Otsitulemused",
"emoji_button.symbols": "Sümbolid", "emoji_button.symbols": "Sümbolid",
"emoji_button.travel": "Reisimine & kohad", "emoji_button.travel": "Reisimine & kohad",
"empty_column.account_hides_collections": "See kasutaja otsustas mitte teha seda infot saadavaks",
"empty_column.account_suspended": "Konto kustutatud", "empty_column.account_suspended": "Konto kustutatud",
"empty_column.account_timeline": "Siin postitusi ei ole!", "empty_column.account_timeline": "Siin postitusi ei ole!",
"empty_column.account_unavailable": "Profiil pole saadaval", "empty_column.account_unavailable": "Profiil pole saadaval",
@ -389,7 +390,6 @@
"lists.search": "Otsi enda jälgitavate inimeste hulgast", "lists.search": "Otsi enda jälgitavate inimeste hulgast",
"lists.subheading": "Sinu nimekirjad", "lists.subheading": "Sinu nimekirjad",
"load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}", "load_pending": "{count, plural, one {# uus kirje} other {# uut kirjet}}",
"loading_indicator.label": "Laeb..",
"media_gallery.toggle_visible": "{number, plural, one {Varja pilt} other {Varja pildid}}", "media_gallery.toggle_visible": "{number, plural, one {Varja pilt} other {Varja pildid}}",
"moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.", "moved_to_account_banner.text": "Kontot {disabledAccount} ei ole praegu võimalik kasutada, sest kolisid kontole {movedToAccount}.",
"mute_modal.duration": "Kestus", "mute_modal.duration": "Kestus",

View file

@ -21,6 +21,7 @@
"account.blocked": "Blokeatuta", "account.blocked": "Blokeatuta",
"account.browse_more_on_origin_server": "Arakatu gehiago jatorrizko profilean", "account.browse_more_on_origin_server": "Arakatu gehiago jatorrizko profilean",
"account.cancel_follow_request": "Baztertu jarraitzeko eskaera", "account.cancel_follow_request": "Baztertu jarraitzeko eskaera",
"account.copy": "Kopiatu profilerako esteka",
"account.direct": "Aipatu pribatuki @{name}", "account.direct": "Aipatu pribatuki @{name}",
"account.disable_notifications": "Utzi jakinarazteari @{name} erabiltzailearen bidalketetan", "account.disable_notifications": "Utzi jakinarazteari @{name} erabiltzailearen bidalketetan",
"account.domain_blocked": "Ezkutatutako domeinua", "account.domain_blocked": "Ezkutatutako domeinua",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Markatu irakurrita bezala", "conversation.mark_as_read": "Markatu irakurrita bezala",
"conversation.open": "Ikusi elkarrizketa", "conversation.open": "Ikusi elkarrizketa",
"conversation.with": "Hauekin: {names}", "conversation.with": "Hauekin: {names}",
"copy_icon_button.copied": "Arbelera kopiatu da",
"copypaste.copied": "Kopiatuta", "copypaste.copied": "Kopiatuta",
"copypaste.copy_to_clipboard": "Kopiatu arbelera", "copypaste.copy_to_clipboard": "Kopiatu arbelera",
"directory.federated": "Fedibertso ezagunekoak", "directory.federated": "Fedibertso ezagunekoak",
@ -389,8 +391,8 @@
"lists.replies_policy.title": "Erakutsi erantzunak:", "lists.replies_policy.title": "Erakutsi erantzunak:",
"lists.search": "Bilatu jarraitzen dituzun pertsonen artean", "lists.search": "Bilatu jarraitzen dituzun pertsonen artean",
"lists.subheading": "Zure zerrendak", "lists.subheading": "Zure zerrendak",
"load_pending": "{count, plural, one {eleentuberri #} other {# elementu berri}}", "load_pending": "{count, plural, one {elementu berri #} other {# elementu berri}}",
"loading_indicator.label": "Kargatzen...", "loading_indicator.label": "Kargatzen",
"media_gallery.toggle_visible": "Txandakatu ikusgaitasuna", "media_gallery.toggle_visible": "Txandakatu ikusgaitasuna",
"moved_to_account_banner.text": "Zure {disabledAccount} kontua desgaituta dago une honetan, {movedToAccount} kontura aldatu zinelako.", "moved_to_account_banner.text": "Zure {disabledAccount} kontua desgaituta dago une honetan, {movedToAccount} kontura aldatu zinelako.",
"mute_modal.duration": "Iraupena", "mute_modal.duration": "Iraupena",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Zoritxarrez, ezin da emaitzik erakutsi orain. Bilaketa erabil dezakezu edo Arakatu orrian jendea bilatu jarraitzeko, edo saiatu geroago.", "onboarding.follows.empty": "Zoritxarrez, ezin da emaitzik erakutsi orain. Bilaketa erabil dezakezu edo Arakatu orrian jendea bilatu jarraitzeko, edo saiatu geroago.",
"onboarding.follows.lead": "Hasierako orria zuk pertsonalizatzen duzu. Gero eta jende gehiagori jarraitu, orduan eta aktibo eta interesgarriago izango da. Profil hauek egokiak izan daitezke hasteko, beti ere, geroago jarraitzeari utz diezazkiekezu!", "onboarding.follows.lead": "Hasierako orria zuk pertsonalizatzen duzu. Gero eta jende gehiagori jarraitu, orduan eta aktibo eta interesgarriago izango da. Profil hauek egokiak izan daitezke hasteko, beti ere, geroago jarraitzeari utz diezazkiekezu!",
"onboarding.follows.title": "Mastodonen pil-pilean", "onboarding.follows.title": "Mastodonen pil-pilean",
"onboarding.profile.discoverable": "Ezagutarazi profila eta bidalketak bilaketa algoritmoetan",
"onboarding.profile.display_name": "Bistaratzeko izena",
"onboarding.profile.display_name_hint": "Zure izena edo ezizena…",
"onboarding.profile.indexable": "Gehitu argitalpen publikoak bilaketa-emaitzetan",
"onboarding.profile.lead": "Geroagoago bete daiteke konfigurazioan, non pertsonalizatzeko aukera gehiago dauden.",
"onboarding.profile.note": "Biografia",
"onboarding.profile.note_hint": "Beste pertsona batzuk @aipa ditzakezu edo #traolak erabili…",
"onboarding.profile.save_and_continue": "Gorde eta jarraitu",
"onboarding.profile.title": "Profilaren konfigurazioa",
"onboarding.profile.upload_avatar": "Igo profilaren irudia",
"onboarding.profile.upload_header": "Igo profilaren goiburua",
"onboarding.share.lead": "Esan jendeari nola aurki zaitzaketen Mastodonen!", "onboarding.share.lead": "Esan jendeari nola aurki zaitzaketen Mastodonen!",
"onboarding.share.message": "{username} naiz #Mastodon-en! Jarrai nazazu hemen: {url}", "onboarding.share.message": "{username} naiz #Mastodon-en! Jarrai nazazu hemen: {url}",
"onboarding.share.next_steps": "Hurrengo urrats posibleak:", "onboarding.share.next_steps": "Hurrengo urrats posibleak:",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "نتایج جست‌وجو", "emoji_button.search_results": "نتایج جست‌وجو",
"emoji_button.symbols": "نمادها", "emoji_button.symbols": "نمادها",
"emoji_button.travel": "سفر و مکان", "emoji_button.travel": "سفر و مکان",
"empty_column.account_hides_collections": "کاربر خواسته که این اطّلاعات در دسترس نباشند",
"empty_column.account_suspended": "حساب معلق شد", "empty_column.account_suspended": "حساب معلق شد",
"empty_column.account_timeline": "هیچ فرسته‌ای این‌جا نیست!", "empty_column.account_timeline": "هیچ فرسته‌ای این‌جا نیست!",
"empty_column.account_unavailable": "نمایهٔ موجود نیست", "empty_column.account_unavailable": "نمایهٔ موجود نیست",
@ -358,13 +359,13 @@
"keyboard_shortcuts.profile": "گشودن نمایهٔ نویسنده", "keyboard_shortcuts.profile": "گشودن نمایهٔ نویسنده",
"keyboard_shortcuts.reply": "پاسخ به فرسته", "keyboard_shortcuts.reply": "پاسخ به فرسته",
"keyboard_shortcuts.requests": "گشودن سیاههٔ درخواست‌های پی‌گیری", "keyboard_shortcuts.requests": "گشودن سیاههٔ درخواست‌های پی‌گیری",
"keyboard_shortcuts.search": "تمرکز روی جست‌وجو", "keyboard_shortcuts.search": "تمرکز روی نوار جست‌وجو",
"keyboard_shortcuts.spoilers": "نمایش/نهفتن زمینهٔ هشدار محتوا", "keyboard_shortcuts.spoilers": "نمایش/نهفتن زمینهٔ هشدار محتوا",
"keyboard_shortcuts.start": "گشودن ستون «آغاز کنید»", "keyboard_shortcuts.start": "گشودن ستون «آغاز کنید»",
"keyboard_shortcuts.toggle_hidden": "نمایش/نهفتن نوشتهٔ پشت هشدار محتوا", "keyboard_shortcuts.toggle_hidden": "نمایش/نهفتن نوشتهٔ پشت هشدار محتوا",
"keyboard_shortcuts.toggle_sensitivity": "نمایش/نهفتن رسانه", "keyboard_shortcuts.toggle_sensitivity": "نمایش/نهفتن رسانه",
"keyboard_shortcuts.toot": "شروع یک فرستهٔ جدید", "keyboard_shortcuts.toot": "شروع یک فرستهٔ جدید",
"keyboard_shortcuts.unfocus": "برداشتن تمرکز از نوشتن/جست‌وجو", "keyboard_shortcuts.unfocus": "برداشتن تمرکز از ناحیهٔ نوشتن یا جست‌وجو",
"keyboard_shortcuts.up": "بالا بردن در سیاهه", "keyboard_shortcuts.up": "بالا بردن در سیاهه",
"lightbox.close": "بستن", "lightbox.close": "بستن",
"lightbox.compress": "فشرده‌سازی جعبهٔ نمایش تصویر", "lightbox.compress": "فشرده‌سازی جعبهٔ نمایش تصویر",
@ -389,7 +390,7 @@
"lists.search": "جست‌وجو بین کسانی که پی‌گرفته‌اید", "lists.search": "جست‌وجو بین کسانی که پی‌گرفته‌اید",
"lists.subheading": "سیاهه‌هایتان", "lists.subheading": "سیاهه‌هایتان",
"load_pending": "{count, plural, one {# مورد جدید} other {# مورد جدید}}", "load_pending": "{count, plural, one {# مورد جدید} other {# مورد جدید}}",
"loading_indicator.label": "بار کردن…", "loading_indicator.label": "در حال بارگذاری…",
"media_gallery.toggle_visible": "{number, plural, one {نهفتن تصویر} other {نهفتن تصاویر}}", "media_gallery.toggle_visible": "{number, plural, one {نهفتن تصویر} other {نهفتن تصاویر}}",
"moved_to_account_banner.text": "حسابتان {disabledAccount} اکنون از کار افتاده؛ چرا که به {movedToAccount} منتقل شدید.", "moved_to_account_banner.text": "حسابتان {disabledAccount} اکنون از کار افتاده؛ چرا که به {movedToAccount} منتقل شدید.",
"mute_modal.duration": "مدت زمان", "mute_modal.duration": "مدت زمان",
@ -478,6 +479,13 @@
"onboarding.follows.empty": "متأسفانه هم‌اکنون نتیجه‌ای قابل نمایش نیست. می‌توانید استفاده از جست‌وجو یا مرور صفحهٔ کاوش را برای یافتن افرادی برای پی‌گیری آزموده یا دوباره تلاش کنید.", "onboarding.follows.empty": "متأسفانه هم‌اکنون نتیجه‌ای قابل نمایش نیست. می‌توانید استفاده از جست‌وجو یا مرور صفحهٔ کاوش را برای یافتن افرادی برای پی‌گیری آزموده یا دوباره تلاش کنید.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon", "onboarding.follows.title": "Popular on Mastodon",
"onboarding.profile.discoverable": "معرفی نمایه و فرسته‌ها در الگوریتم‌های کشف",
"onboarding.profile.display_name": "نام نمایشی",
"onboarding.profile.display_name_hint": "نام کامل یا نام باحالتان…",
"onboarding.profile.note": "درباره شما",
"onboarding.profile.note_hint": "می‌توانید افراد دیگر را @نام‌بردن یا #برچسب بزنید…",
"onboarding.profile.save_and_continue": "ذخیره کن و ادامه بده",
"onboarding.profile.title": "تنظیم نمایه",
"onboarding.share.lead": "بگذارید افراد بدانند چگونه می‌توانند در ماستادون بیابندتان!", "onboarding.share.lead": "بگذارید افراد بدانند چگونه می‌توانند در ماستادون بیابندتان!",
"onboarding.share.message": "من {username} روی #ماستودون هستم! مرا در {url} پی‌بگیرید", "onboarding.share.message": "من {username} روی #ماستودون هستم! مرا در {url} پی‌بگیرید",
"onboarding.share.next_steps": "گام‌های ممکن بعدی:", "onboarding.share.next_steps": "گام‌های ممکن بعدی:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Estetty", "account.blocked": "Estetty",
"account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella", "account.browse_more_on_origin_server": "Selaile lisää alkuperäisellä palvelimella",
"account.cancel_follow_request": "Peruuta seurantapyyntö", "account.cancel_follow_request": "Peruuta seurantapyyntö",
"account.copy": "Kopioi profiilin linkki",
"account.direct": "Mainitse @{name} yksityisesti", "account.direct": "Mainitse @{name} yksityisesti",
"account.disable_notifications": "Lopeta ilmoittamasta minulle, kun @{name} julkaisee", "account.disable_notifications": "Lopeta ilmoittamasta minulle, kun @{name} julkaisee",
"account.domain_blocked": "Verkkotunnus estetty", "account.domain_blocked": "Verkkotunnus estetty",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Merkitse luetuksi", "conversation.mark_as_read": "Merkitse luetuksi",
"conversation.open": "Näytä keskustelu", "conversation.open": "Näytä keskustelu",
"conversation.with": "{names} kanssa", "conversation.with": "{names} kanssa",
"copy_icon_button.copied": "Kopioitu leikepöydälle",
"copypaste.copied": "Kopioitu", "copypaste.copied": "Kopioitu",
"copypaste.copy_to_clipboard": "Kopioi leikepöydälle", "copypaste.copy_to_clipboard": "Kopioi leikepöydälle",
"directory.federated": "Koko tunnettu fediversumi", "directory.federated": "Koko tunnettu fediversumi",
@ -222,6 +224,7 @@
"emoji_button.search_results": "Hakutulokset", "emoji_button.search_results": "Hakutulokset",
"emoji_button.symbols": "Symbolit", "emoji_button.symbols": "Symbolit",
"emoji_button.travel": "Matkailu ja paikat", "emoji_button.travel": "Matkailu ja paikat",
"empty_column.account_hides_collections": "Käyttäjä on päättänyt olla julkaisematta näitä tietoja",
"empty_column.account_suspended": "Tili jäädytetty", "empty_column.account_suspended": "Tili jäädytetty",
"empty_column.account_timeline": "Ei viestejä täällä.", "empty_column.account_timeline": "Ei viestejä täällä.",
"empty_column.account_unavailable": "Profiilia ei löydy", "empty_column.account_unavailable": "Profiilia ei löydy",
@ -389,7 +392,7 @@
"lists.search": "Etsi seuraamistasi henkilöistä", "lists.search": "Etsi seuraamistasi henkilöistä",
"lists.subheading": "Omat listasi", "lists.subheading": "Omat listasi",
"load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}", "load_pending": "{count, plural, one {# uusi kohde} other {# uutta kohdetta}}",
"loading_indicator.label": "Ladataan...", "loading_indicator.label": "Ladataan",
"media_gallery.toggle_visible": "{number, plural, one {Piilota kuva} other {Piilota kuvat}}", "media_gallery.toggle_visible": "{number, plural, one {Piilota kuva} other {Piilota kuvat}}",
"moved_to_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä, koska teit siirron tiliin {movedToAccount}.", "moved_to_account_banner.text": "Tilisi {disabledAccount} on tällä hetkellä poissa käytöstä, koska teit siirron tiliin {movedToAccount}.",
"mute_modal.duration": "Kesto", "mute_modal.duration": "Kesto",
@ -478,6 +481,17 @@
"onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.", "onboarding.follows.empty": "Valitettavasti tuloksia ei voida näyttää juuri nyt. Voit kokeilla hakua tai selata tutustumissivua löytääksesi seurattavaa tai yrittää myöhemmin uudelleen.",
"onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!", "onboarding.follows.lead": "Kokoat oman kotisyötteesi itse. Mitä enemmän ihmisiä seuraat, sitä aktiivisempi ja kiinnostavampi syöte on. Nämä profiilit voivat olla alkuun hyvä lähtökohta — voit aina lopettaa niiden seuraamisen myöhemmin!",
"onboarding.follows.title": "Mukauta kotisyötettäsi", "onboarding.follows.title": "Mukauta kotisyötettäsi",
"onboarding.profile.discoverable": "Pidä profiilia ja julkaisuja esillä löytämisalgoritmeissa",
"onboarding.profile.display_name": "Näyttönimi",
"onboarding.profile.display_name_hint": "Koko nimesi tai lempinimesi…",
"onboarding.profile.indexable": "Sisällytä julkiset julkaisut hakutuloksiin",
"onboarding.profile.lead": "Voit viimeistellä tämän milloin tahansa asetuksissa, jossa on saatavilla vielä enemmän mukautusvalintoja.",
"onboarding.profile.note": "Elämäkerta",
"onboarding.profile.note_hint": "Voit @mainita muita käyttäjiä tai #aihetunnisteita…",
"onboarding.profile.save_and_continue": "Tallenna ja jatka",
"onboarding.profile.title": "Profiilin määritys",
"onboarding.profile.upload_avatar": "Lataa profiilikuva",
"onboarding.profile.upload_header": "Lataa profiilin otsakekuva",
"onboarding.share.lead": "Kerro ihmisille, kuinka he voivat löytää sinut Mastodonista!", "onboarding.share.lead": "Kerro ihmisille, kuinka he voivat löytää sinut Mastodonista!",
"onboarding.share.message": "Olen {username} #Mastodonissa! Seuraa minua osoitteessa {url}", "onboarding.share.message": "Olen {username} #Mastodonissa! Seuraa minua osoitteessa {url}",
"onboarding.share.next_steps": "Mahdolliset seuraavat vaiheet:", "onboarding.share.next_steps": "Mahdolliset seuraavat vaiheet:",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Leitiúrslit", "emoji_button.search_results": "Leitiúrslit",
"emoji_button.symbols": "Ímyndir", "emoji_button.symbols": "Ímyndir",
"emoji_button.travel": "Ferðing og støð", "emoji_button.travel": "Ferðing og støð",
"empty_column.account_hides_collections": "Hesin brúkarin hevur valt, at hesar upplýsingarnar ikki skulu vera tøkar",
"empty_column.account_suspended": "Kontan gjørd óvirkin", "empty_column.account_suspended": "Kontan gjørd óvirkin",
"empty_column.account_timeline": "Einki uppslag her!", "empty_column.account_timeline": "Einki uppslag her!",
"empty_column.account_unavailable": "Vangin er ikki tøkur", "empty_column.account_unavailable": "Vangin er ikki tøkur",
@ -389,7 +390,6 @@
"lists.search": "Leita millum fólk, sum tú fylgir", "lists.search": "Leita millum fólk, sum tú fylgir",
"lists.subheading": "Tínir listar", "lists.subheading": "Tínir listar",
"load_pending": "{count, plural, one {# nýtt evni} other {# nýggj evni}}", "load_pending": "{count, plural, one {# nýtt evni} other {# nýggj evni}}",
"loading_indicator.label": "Innlesi...",
"media_gallery.toggle_visible": "{number, plural, one {Fjal mynd} other {Fjal myndir}}", "media_gallery.toggle_visible": "{number, plural, one {Fjal mynd} other {Fjal myndir}}",
"moved_to_account_banner.text": "Konta tín {disabledAccount} er í løtuni óvirkin, tí tú flutti til {movedToAccount}.", "moved_to_account_banner.text": "Konta tín {disabledAccount} er í løtuni óvirkin, tí tú flutti til {movedToAccount}.",
"mute_modal.duration": "Tíðarbil", "mute_modal.duration": "Tíðarbil",

View file

@ -479,6 +479,9 @@
"onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer de rechercher ou de parcourir la page \"Explorer\" pour trouver des personnes à suivre, ou réessayer plus tard.", "onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer de rechercher ou de parcourir la page \"Explorer\" pour trouver des personnes à suivre, ou réessayer plus tard.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Popular on Mastodon", "onboarding.follows.title": "Popular on Mastodon",
"onboarding.profile.discoverable": "Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages",
"onboarding.profile.save_and_continue": "Enregistrer et continuer",
"onboarding.profile.upload_avatar": "Importer une photo de profil",
"onboarding.share.lead": "Faites savoir aux gens comment vous trouver sur Mastodon!", "onboarding.share.lead": "Faites savoir aux gens comment vous trouver sur Mastodon!",
"onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}", "onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}",
"onboarding.share.next_steps": "Étapes suivantes possibles:", "onboarding.share.next_steps": "Étapes suivantes possibles:",

View file

@ -107,7 +107,7 @@
"closed_registrations_modal.preamble": "Mastodon est décentralisé : peu importe où vous créez votre compte, vous serez en mesure de suivre et d'interagir avec quiconque sur ce serveur. Vous pouvez même l'héberger !", "closed_registrations_modal.preamble": "Mastodon est décentralisé : peu importe où vous créez votre compte, vous serez en mesure de suivre et d'interagir avec quiconque sur ce serveur. Vous pouvez même l'héberger !",
"closed_registrations_modal.title": "Inscription sur Mastodon", "closed_registrations_modal.title": "Inscription sur Mastodon",
"column.about": "À propos", "column.about": "À propos",
"column.blocks": "Comptes bloqués", "column.blocks": "Utilisateurs bloqués",
"column.bookmarks": "Marque-pages", "column.bookmarks": "Marque-pages",
"column.community": "Fil public local", "column.community": "Fil public local",
"column.direct": "Mentions privées", "column.direct": "Mentions privées",
@ -479,6 +479,9 @@
"onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.", "onboarding.follows.empty": "Malheureusement, aucun résultat ne peut être affiché pour le moment. Vous pouvez essayer d'utiliser la recherche ou parcourir la page de découverte pour trouver des personnes à suivre, ou réessayez plus tard.",
"onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!", "onboarding.follows.lead": "You curate your own home feed. The more people you follow, the more active and interesting it will be. These profiles may be a good starting point—you can always unfollow them later!",
"onboarding.follows.title": "Personnaliser votre flux principal", "onboarding.follows.title": "Personnaliser votre flux principal",
"onboarding.profile.discoverable": "Autoriser des algorithmes de découverte à mettre en avant votre profil et vos messages",
"onboarding.profile.save_and_continue": "Enregistrer et continuer",
"onboarding.profile.upload_avatar": "Importer une photo de profil",
"onboarding.share.lead": "Faites savoir aux gens comment ils peuvent vous trouver sur Mastodon!", "onboarding.share.lead": "Faites savoir aux gens comment ils peuvent vous trouver sur Mastodon!",
"onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}", "onboarding.share.message": "Je suis {username} sur #Mastodon! Suivez-moi sur {url}",
"onboarding.share.next_steps": "Étapes suivantes possibles :", "onboarding.share.next_steps": "Étapes suivantes possibles :",

View file

@ -222,6 +222,7 @@
"emoji_button.search_results": "Sykresultaten", "emoji_button.search_results": "Sykresultaten",
"emoji_button.symbols": "Symboalen", "emoji_button.symbols": "Symboalen",
"emoji_button.travel": "Reizgje en lokaasjes", "emoji_button.travel": "Reizgje en lokaasjes",
"empty_column.account_hides_collections": "Dizze brûker hat derfoar keazen dizze ynformaasje net beskikber te meitsjen",
"empty_column.account_suspended": "Account beskoattele", "empty_column.account_suspended": "Account beskoattele",
"empty_column.account_timeline": "Hjir binne gjin berjochten!", "empty_column.account_timeline": "Hjir binne gjin berjochten!",
"empty_column.account_unavailable": "Profyl net beskikber", "empty_column.account_unavailable": "Profyl net beskikber",
@ -389,7 +390,6 @@
"lists.search": "Sykje nei minsken dyt jo folgje", "lists.search": "Sykje nei minsken dyt jo folgje",
"lists.subheading": "Jo listen", "lists.subheading": "Jo listen",
"load_pending": "{count, plural, one {# nij item} other {# nije items}}", "load_pending": "{count, plural, one {# nij item} other {# nije items}}",
"loading_indicator.label": "Lade…",
"media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}", "media_gallery.toggle_visible": "{number, plural, one {ôfbylding ferstopje} other {ôfbyldingen ferstopje}}",
"moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.", "moved_to_account_banner.text": "Omdat jo nei {movedToAccount} ferhuze binne is jo account {disabledAccount} op dit stuit útskeakele.",
"mute_modal.duration": "Doer", "mute_modal.duration": "Doer",

View file

@ -316,7 +316,6 @@
"lists.replies_policy.title": "Taispeáin freagraí:", "lists.replies_policy.title": "Taispeáin freagraí:",
"lists.search": "Cuardaigh i measc daoine atá á leanúint agat", "lists.search": "Cuardaigh i measc daoine atá á leanúint agat",
"lists.subheading": "Do liostaí", "lists.subheading": "Do liostaí",
"loading_indicator.label": "Ag lódáil...",
"mute_modal.duration": "Tréimhse", "mute_modal.duration": "Tréimhse",
"mute_modal.hide_notifications": "Cuir póstalacha ón t-úsáideoir seo i bhfolach?", "mute_modal.hide_notifications": "Cuir póstalacha ón t-úsáideoir seo i bhfolach?",
"mute_modal.indefinite": "Gan téarma", "mute_modal.indefinite": "Gan téarma",

View file

@ -389,7 +389,6 @@
"lists.search": "Lorg am measg nan daoine a leanas tu", "lists.search": "Lorg am measg nan daoine a leanas tu",
"lists.subheading": "Na liostaichean agad", "lists.subheading": "Na liostaichean agad",
"load_pending": "{count, plural, one {# nì ùr} two {# nì ùr} few {# nithean ùra} other {# nì ùr}}", "load_pending": "{count, plural, one {# nì ùr} two {# nì ùr} few {# nithean ùra} other {# nì ùr}}",
"loading_indicator.label": "Ga luchdadh…",
"media_gallery.toggle_visible": "{number, plural, 1 {Falaich an dealbh} one {Falaich na dealbhan} two {Falaich na dealbhan} few {Falaich na dealbhan} other {Falaich na dealbhan}}", "media_gallery.toggle_visible": "{number, plural, 1 {Falaich an dealbh} one {Falaich na dealbhan} two {Falaich na dealbhan} few {Falaich na dealbhan} other {Falaich na dealbhan}}",
"moved_to_account_banner.text": "Tha an cunntas {disabledAccount} agad à comas on a rinn thu imrich gu {movedToAccount}.", "moved_to_account_banner.text": "Tha an cunntas {disabledAccount} agad à comas on a rinn thu imrich gu {movedToAccount}.",
"mute_modal.duration": "Faide", "mute_modal.duration": "Faide",

View file

@ -390,7 +390,7 @@
"lists.search": "Procurar entre as persoas que segues", "lists.search": "Procurar entre as persoas que segues",
"lists.subheading": "As túas listaxes", "lists.subheading": "As túas listaxes",
"load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}", "load_pending": "{count, plural, one {# novo elemento} other {# novos elementos}}",
"loading_indicator.label": "Estase a cargar...", "loading_indicator.label": "Estase a cargar",
"media_gallery.toggle_visible": "Agochar {number, plural, one {imaxe} other {imaxes}}", "media_gallery.toggle_visible": "Agochar {number, plural, one {imaxe} other {imaxes}}",
"moved_to_account_banner.text": "A túa conta {disabledAccount} está actualmente desactivada porque movéchela a {movedToAccount}.", "moved_to_account_banner.text": "A túa conta {disabledAccount} está actualmente desactivada porque movéchela a {movedToAccount}.",
"mute_modal.duration": "Duración", "mute_modal.duration": "Duración",
@ -479,6 +479,17 @@
"onboarding.follows.empty": "Desgraciadamente agora mesmo non hai nada que mostrar. Podes intentalo coa busca ou na páxina descubrir para atopar persoas ás que seguir, ou intentalo máis tarde.", "onboarding.follows.empty": "Desgraciadamente agora mesmo non hai nada que mostrar. Podes intentalo coa busca ou na páxina descubrir para atopar persoas ás que seguir, ou intentalo máis tarde.",
"onboarding.follows.lead": "Podes facer que a túa cronoloxía de inicio sexa como ti a queres. Canta máis xente sigas máis interesante será. Estes perfís poderían axudarche a comezar —sempre poderás deixar de seguilos despois!", "onboarding.follows.lead": "Podes facer que a túa cronoloxía de inicio sexa como ti a queres. Canta máis xente sigas máis interesante será. Estes perfís poderían axudarche a comezar —sempre poderás deixar de seguilos despois!",
"onboarding.follows.title": "Popular en Mastodon", "onboarding.follows.title": "Popular en Mastodon",
"onboarding.profile.discoverable": "Perfil destacado e publicacións nos algoritmos de descubrimento",
"onboarding.profile.display_name": "Nome público",
"onboarding.profile.display_name_hint": "O teu nome completo ou un nome divertido…",
"onboarding.profile.indexable": "Incluír publicacións públicas nos resultados das buscas",
"onboarding.profile.lead": "Sempre poderás incluír esta información mais tarde nos axustes, onde terás máis opcións dispoñibles.",
"onboarding.profile.note": "Acerca de ti",
"onboarding.profile.note_hint": "Podes @mencionar a outras persoas ou usar #cancelos…",
"onboarding.profile.save_and_continue": "Gardar e continuar",
"onboarding.profile.title": "Configuración do perfil",
"onboarding.profile.upload_avatar": "Subir imaxe do perfil",
"onboarding.profile.upload_header": "Subir cabeceira para o perfil",
"onboarding.share.lead": "Fai que as persoas saiban como atoparte en Mastodon!", "onboarding.share.lead": "Fai que as persoas saiban como atoparte en Mastodon!",
"onboarding.share.message": "Son {username} en #Mastodon! Ségueme en {url}", "onboarding.share.message": "Son {username} en #Mastodon! Ségueme en {url}",
"onboarding.share.next_steps": "Seguintes pasos:", "onboarding.share.next_steps": "Seguintes pasos:",

View file

@ -21,6 +21,7 @@
"account.blocked": "לחסום", "account.blocked": "לחסום",
"account.browse_more_on_origin_server": "ראה יותר בפרופיל המקורי", "account.browse_more_on_origin_server": "ראה יותר בפרופיל המקורי",
"account.cancel_follow_request": "משיכת בקשת מעקב", "account.cancel_follow_request": "משיכת בקשת מעקב",
"account.copy": "להעתיק קישור לפרופיל",
"account.direct": "הודעה פרטית אל @{name}", "account.direct": "הודעה פרטית אל @{name}",
"account.disable_notifications": "הפסק לשלוח לי התראות כש@{name} מפרסמים", "account.disable_notifications": "הפסק לשלוח לי התראות כש@{name} מפרסמים",
"account.domain_blocked": "הדומיין חסום", "account.domain_blocked": "הדומיין חסום",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "סמן כנקרא", "conversation.mark_as_read": "סמן כנקרא",
"conversation.open": "צפו בשיחה", "conversation.open": "צפו בשיחה",
"conversation.with": "עם {names}", "conversation.with": "עם {names}",
"copy_icon_button.copied": "הועתק ללוח",
"copypaste.copied": "הועתק", "copypaste.copied": "הועתק",
"copypaste.copy_to_clipboard": "העתקה ללוח הגזירים", "copypaste.copy_to_clipboard": "העתקה ללוח הגזירים",
"directory.federated": "מהפדרציה הידועה", "directory.federated": "מהפדרציה הידועה",
@ -390,7 +392,7 @@
"lists.search": "חיפוש בין אנשים שאני עוקב\\ת אחריהם", "lists.search": "חיפוש בין אנשים שאני עוקב\\ת אחריהם",
"lists.subheading": "הרשימות שלך", "lists.subheading": "הרשימות שלך",
"load_pending": "{count, plural, one {# פריט חדש} other {# פריטים חדשים}}", "load_pending": "{count, plural, one {# פריט חדש} other {# פריטים חדשים}}",
"loading_indicator.label": "טוען...", "loading_indicator.label": "בטעינה…",
"media_gallery.toggle_visible": "{number, plural, one {להסתיר תמונה} two {להסתיר תמונותיים} many {להסתיר תמונות} other {להסתיר תמונות}}", "media_gallery.toggle_visible": "{number, plural, one {להסתיר תמונה} two {להסתיר תמונותיים} many {להסתיר תמונות} other {להסתיר תמונות}}",
"moved_to_account_banner.text": "חשבונך {disabledAccount} אינו פעיל כרגע עקב מעבר ל{movedToAccount}.", "moved_to_account_banner.text": "חשבונך {disabledAccount} אינו פעיל כרגע עקב מעבר ל{movedToAccount}.",
"mute_modal.duration": "משך הזמן", "mute_modal.duration": "משך הזמן",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "למצער, תוצאות לחיפושך אינן בנמצא. ניתן להשתמש בחיפוש או בדף החקירות לשם מציאת אנשים ולעקבם. אפשר גם לנסות שוב אחר כך.", "onboarding.follows.empty": "למצער, תוצאות לחיפושך אינן בנמצא. ניתן להשתמש בחיפוש או בדף החקירות לשם מציאת אנשים ולעקבם. אפשר גם לנסות שוב אחר כך.",
"onboarding.follows.lead": "אתם אוצרים את הזרם הבייתי שלכם. ככל שתעקבו אחרי יותר אנשים, הוא יהיה עשיר ופעיל יותר. הנה כמה פרופילים להתחיל בהם - תמיד ניתן להפסיק מעקב אחריהם בהמשך!", "onboarding.follows.lead": "אתם אוצרים את הזרם הבייתי שלכם. ככל שתעקבו אחרי יותר אנשים, הוא יהיה עשיר ופעיל יותר. הנה כמה פרופילים להתחיל בהם - תמיד ניתן להפסיק מעקב אחריהם בהמשך!",
"onboarding.follows.title": "פופולארי על מסטודון", "onboarding.follows.title": "פופולארי על מסטודון",
"onboarding.profile.discoverable": "הצגת פרופיל והודעות במסך התגליות",
"onboarding.profile.display_name": "שם להצגה",
"onboarding.profile.display_name_hint": "שמך המלא או כינוי הכיף שלך…",
"onboarding.profile.indexable": "הכללת הודעות ציבוריות בתוצאות החיפוש",
"onboarding.profile.lead": "תמיד ניתן להשלים זאת אחר כך בהגדרות, שם יש אפילו עוד אפשרויות להתאמה אישית.",
"onboarding.profile.note": "אודות",
"onboarding.profile.note_hint": "ניתן @לאזכר משתמשים אחרים או #תגיות…",
"onboarding.profile.save_and_continue": "לשמור ולהמשיך",
"onboarding.profile.title": "הגדרת פרופיל",
"onboarding.profile.upload_avatar": "העלאת תמונת פרופיל",
"onboarding.profile.upload_header": "העלאת כותרת פרופיל",
"onboarding.share.lead": "כדאי להודיע לחברים היכן למצוא אותך במסטודון!", "onboarding.share.lead": "כדאי להודיע לחברים היכן למצוא אותך במסטודון!",
"onboarding.share.message": "אני {username} ברשת #מסטודון! בואו לעקוב אחרי בכתובת {url}", "onboarding.share.message": "אני {username} ברשת #מסטודון! בואו לעקוב אחרי בכתובת {url}",
"onboarding.share.next_steps": "לאיפה להמשיך מכאן:", "onboarding.share.next_steps": "לאיפה להמשיך מכאן:",
@ -518,7 +531,7 @@
"privacy.private.short": "לעוקבים בלבד", "privacy.private.short": "לעוקבים בלבד",
"privacy.public.long": "גלוי לכל", "privacy.public.long": "גלוי לכל",
"privacy.public.short": "פומבי", "privacy.public.short": "פומבי",
"privacy.unlisted.long": "גלוי לכל, אבל מוסתר מאמצעי גילוי", "privacy.unlisted.long": "גלוי לכל, אבל מוסתר מאמצעי תגלית",
"privacy.unlisted.short": "לא רשום (לא לפיד הכללי)", "privacy.unlisted.short": "לא רשום (לא לפיד הכללי)",
"privacy_policy.last_updated": "עודכן לאחרונה {date}", "privacy_policy.last_updated": "עודכן לאחרונה {date}",
"privacy_policy.title": "מדיניות פרטיות", "privacy_policy.title": "מדיניות פרטיות",

View file

@ -360,7 +360,6 @@
"lists.replies_policy.none": "कोई नहीं", "lists.replies_policy.none": "कोई नहीं",
"lists.replies_policy.title": "इसके जवाब दिखाएं:", "lists.replies_policy.title": "इसके जवाब दिखाएं:",
"lists.subheading": "आपकी सूचियाँ", "lists.subheading": "आपकी सूचियाँ",
"loading_indicator.label": "लोड हो रहा है...",
"mute_modal.duration": "अवधि", "mute_modal.duration": "अवधि",
"mute_modal.hide_notifications": "इस सभ्य की ओरसे आनेवाली सूचनाए शांत करे", "mute_modal.hide_notifications": "इस सभ्य की ओरसे आनेवाली सूचनाए शांत करे",
"mute_modal.indefinite": "अनिश्चितकालीन", "mute_modal.indefinite": "अनिश्चितकालीन",

View file

@ -306,7 +306,6 @@
"lists.replies_policy.none": "Nitko", "lists.replies_policy.none": "Nitko",
"lists.search": "Traži među praćenim ljudima", "lists.search": "Traži među praćenim ljudima",
"lists.subheading": "Vaše liste", "lists.subheading": "Vaše liste",
"loading_indicator.label": "Učitavanje...",
"media_gallery.toggle_visible": "Sakrij {number, plural, one {sliku} other {slike}}", "media_gallery.toggle_visible": "Sakrij {number, plural, one {sliku} other {slike}}",
"mute_modal.duration": "Trajanje", "mute_modal.duration": "Trajanje",
"mute_modal.hide_notifications": "Sakrij obavijesti ovog korisnika?", "mute_modal.hide_notifications": "Sakrij obavijesti ovog korisnika?",

View file

@ -21,6 +21,7 @@
"account.blocked": "Letiltva", "account.blocked": "Letiltva",
"account.browse_more_on_origin_server": "További böngészés az eredeti profilon", "account.browse_more_on_origin_server": "További böngészés az eredeti profilon",
"account.cancel_follow_request": "Követési kérés visszavonása", "account.cancel_follow_request": "Követési kérés visszavonása",
"account.copy": "Hivatkozás másolása a profilba",
"account.direct": "@{name} személyes említése", "account.direct": "@{name} személyes említése",
"account.disable_notifications": "Ne figyelmeztessen, ha @{name} bejegyzést tesz közzé", "account.disable_notifications": "Ne figyelmeztessen, ha @{name} bejegyzést tesz közzé",
"account.domain_blocked": "Letiltott domain", "account.domain_blocked": "Letiltott domain",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Megjelölés olvasottként", "conversation.mark_as_read": "Megjelölés olvasottként",
"conversation.open": "Beszélgetés megtekintése", "conversation.open": "Beszélgetés megtekintése",
"conversation.with": "Velük: {names}", "conversation.with": "Velük: {names}",
"copy_icon_button.copied": "A szöveg a vágólapra másolva",
"copypaste.copied": "Másolva", "copypaste.copied": "Másolva",
"copypaste.copy_to_clipboard": "Másolás vágólapra", "copypaste.copy_to_clipboard": "Másolás vágólapra",
"directory.federated": "Az ismert fediverzumból", "directory.federated": "Az ismert fediverzumból",
@ -390,7 +392,7 @@
"lists.search": "Keresés a követett személyek között", "lists.search": "Keresés a követett személyek között",
"lists.subheading": "Saját listák", "lists.subheading": "Saját listák",
"load_pending": "{count, plural, one {# új elem} other {# új elem}}", "load_pending": "{count, plural, one {# új elem} other {# új elem}}",
"loading_indicator.label": "Betöltés...", "loading_indicator.label": "Betöltés",
"media_gallery.toggle_visible": "{number, plural, one {Kép elrejtése} other {Képek elrejtése}}", "media_gallery.toggle_visible": "{number, plural, one {Kép elrejtése} other {Képek elrejtése}}",
"moved_to_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva, mert átköltöztél ide: {movedToAccount}.", "moved_to_account_banner.text": "A(z) {disabledAccount} fiókod jelenleg le van tiltva, mert átköltöztél ide: {movedToAccount}.",
"mute_modal.duration": "Időtartam", "mute_modal.duration": "Időtartam",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.", "onboarding.follows.empty": "Sajnos jelenleg nem jeleníthető meg eredmény. Kipróbálhatod a keresést vagy böngészheted a felfedező oldalon a követni kívánt személyeket, vagy próbáld meg később.",
"onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:", "onboarding.follows.lead": "A saját hírfolyamod az elsődleges tapasztalás a Mastodonon. Minél több embert követsz, annál aktívabb és érdekesebb a dolog. Az induláshoz itt van néhány javaslat:",
"onboarding.follows.title": "Népszerű a Mastodonon", "onboarding.follows.title": "Népszerű a Mastodonon",
"onboarding.profile.discoverable": "Profil és bejegyzések szerepeltetése a felfedezési algoritmusokban",
"onboarding.profile.display_name": "Megjelenített név",
"onboarding.profile.display_name_hint": "Teljes neved vagy vicces neved…",
"onboarding.profile.indexable": "Nyilvános bejegyzések szerepeltetése a keresési eredményekben",
"onboarding.profile.lead": "Ezt később bármikor befejezheted a beállításokban, ahol még több testreszabási lehetőség áll rendelkezésre.",
"onboarding.profile.note": "Bemutatkozás",
"onboarding.profile.note_hint": "Megemlíthetsz @másokat vagy #hashtag-eket…",
"onboarding.profile.save_and_continue": "Mentés és folytatás",
"onboarding.profile.title": "Profilbeállítás",
"onboarding.profile.upload_avatar": "Profilkép feltöltése",
"onboarding.profile.upload_header": "Profil fejléc feltöltése",
"onboarding.share.lead": "Tudassuk az emberekkel, hogyan találhatnak meg a Mastodonon!", "onboarding.share.lead": "Tudassuk az emberekkel, hogyan találhatnak meg a Mastodonon!",
"onboarding.share.message": "{username} vagyok a #Mastodon hálózaton! Kövess itt: {url}.", "onboarding.share.message": "{username} vagyok a #Mastodon hálózaton! Kövess itt: {url}.",
"onboarding.share.next_steps": "Lehetséges következő lépések:", "onboarding.share.next_steps": "Lehetséges következő lépések:",

View file

@ -314,7 +314,6 @@
"lists.search": "Փնտրել քո հետեւած մարդկանց մէջ", "lists.search": "Փնտրել քո հետեւած մարդկանց մէջ",
"lists.subheading": "Քո ցանկերը", "lists.subheading": "Քո ցանկերը",
"load_pending": "{count, plural, one {# նոր նիւթ} other {# նոր նիւթ}}", "load_pending": "{count, plural, one {# նոր նիւթ} other {# նոր նիւթ}}",
"loading_indicator.label": "Բեռնւում է…",
"media_gallery.toggle_visible": "Ցուցադրել/թաքցնել", "media_gallery.toggle_visible": "Ցուցադրել/թաքցնել",
"mute_modal.duration": "Տեւողութիւն", "mute_modal.duration": "Տեւողութիւն",
"mute_modal.hide_notifications": "Թաքցնե՞լ ծանուցումներն այս օգտատիրոջից։", "mute_modal.hide_notifications": "Թաքցնե՞լ ծանուցումներն այս օգտատիրոջից։",

View file

@ -353,7 +353,6 @@
"lists.search": "Cari di antara orang yang Anda ikuti", "lists.search": "Cari di antara orang yang Anda ikuti",
"lists.subheading": "Daftar Anda", "lists.subheading": "Daftar Anda",
"load_pending": "{count, plural, other {# item baru}}", "load_pending": "{count, plural, other {# item baru}}",
"loading_indicator.label": "Tunggu sebentar...",
"media_gallery.toggle_visible": "Tampil/Sembunyikan", "media_gallery.toggle_visible": "Tampil/Sembunyikan",
"moved_to_account_banner.text": "Akun {disabledAccount} Anda kini dinonaktifkan karena Anda pindah ke {movedToAccount}.", "moved_to_account_banner.text": "Akun {disabledAccount} Anda kini dinonaktifkan karena Anda pindah ke {movedToAccount}.",
"mute_modal.duration": "Durasi", "mute_modal.duration": "Durasi",

View file

@ -1,8 +1,11 @@
{ {
"account.add_or_remove_from_list": "Tinye ma ọ bụ Wepu na ndepụta", "account.add_or_remove_from_list": "Tinye ma ọ bụ Wepu na ndepụta",
"account.badges.bot": "Bot", "account.badges.bot": "Bot",
"account.badges.group": "Otù",
"account.cancel_follow_request": "Withdraw follow request", "account.cancel_follow_request": "Withdraw follow request",
"account.follow": "Soro", "account.follow": "Soro",
"account.followers": "Ndị na-eso",
"account.following": "Na-eso",
"account.follows_you": "Na-eso gị", "account.follows_you": "Na-eso gị",
"account.mute": "Mee ogbi @{name}", "account.mute": "Mee ogbi @{name}",
"account.unfollow": "Kwụsị iso", "account.unfollow": "Kwụsị iso",
@ -11,16 +14,20 @@
"audio.hide": "Zoo ụda", "audio.hide": "Zoo ụda",
"bundle_column_error.retry": "Nwaa ọzọ", "bundle_column_error.retry": "Nwaa ọzọ",
"bundle_column_error.routing.title": "404", "bundle_column_error.routing.title": "404",
"bundle_modal_error.close": "Mechie",
"bundle_modal_error.retry": "Nwaa ọzọ", "bundle_modal_error.retry": "Nwaa ọzọ",
"column.about": "Maka", "column.about": "Maka",
"column.blocks": "Ojiarụ egbochiri", "column.blocks": "Ojiarụ egbochiri",
"column.bookmarks": "Ebenrụtụakā", "column.bookmarks": "Ebenrụtụakā",
"column.home": "Be", "column.home": "Be",
"column.lists": "Ndepụta",
"column.pins": "Pinned post", "column.pins": "Pinned post",
"column_header.pin": "Gbado na profaịlụ gị",
"column_subheading.settings": "Mwube", "column_subheading.settings": "Mwube",
"community.column_settings.media_only": "Media only", "community.column_settings.media_only": "Media only",
"compose.language.change": "Gbanwee asụsụ", "compose.language.change": "Gbanwee asụsụ",
"compose.language.search": "Chọọ asụsụ...", "compose.language.search": "Chọọ asụsụ...",
"compose.published.open": "Mepe",
"compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.", "compose_form.encryption_warning": "Posts on Mastodon are not end-to-end encrypted. Do not share any dangerous information over Mastodon.",
"compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.",
"compose_form.placeholder": "What is on your mind?", "compose_form.placeholder": "What is on your mind?",
@ -32,7 +39,10 @@
"confirmations.delete.message": "Are you sure you want to delete this status?", "confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete_list.confirm": "Hichapụ", "confirmations.delete_list.confirm": "Hichapụ",
"confirmations.domain_block.confirm": "Hide entire domain", "confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.edit.confirm": "Dezie",
"confirmations.mute.confirm": "Mee ogbi",
"confirmations.reply.confirm": "Zaa", "confirmations.reply.confirm": "Zaa",
"confirmations.unfollow.confirm": "Kwụsị iso",
"conversation.delete": "Hichapụ nkata", "conversation.delete": "Hichapụ nkata",
"dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.", "dismissable_banner.explore_links": "These news stories are being talked about by people on this and other servers of the decentralized network right now.",
"dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.", "dismissable_banner.explore_tags": "These hashtags are gaining traction among people on this and other servers of the decentralized network right now.",
@ -76,8 +86,8 @@
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list", "keyboard_shortcuts.up": "to move up in the list",
"lists.delete": "Hichapụ ndepụta", "lists.delete": "Hichapụ ndepụta",
"lists.edit": "Dezie ndepụta",
"lists.subheading": "Ndepụta gị", "lists.subheading": "Ndepụta gị",
"loading_indicator.label": "Na-adọnye...",
"navigation_bar.about": "Maka", "navigation_bar.about": "Maka",
"navigation_bar.bookmarks": "Ebenrụtụakā", "navigation_bar.bookmarks": "Ebenrụtụakā",
"navigation_bar.domain_blocks": "Hidden domains", "navigation_bar.domain_blocks": "Hidden domains",
@ -100,20 +110,27 @@
"privacy.change": "Adjust status privacy", "privacy.change": "Adjust status privacy",
"privacy.direct.short": "Direct", "privacy.direct.short": "Direct",
"privacy.private.short": "Followers-only", "privacy.private.short": "Followers-only",
"relative_time.full.just_now": "kịta",
"relative_time.just_now": "kịta", "relative_time.just_now": "kịta",
"relative_time.today": "taa", "relative_time.today": "taa",
"reply_indicator.cancel": "Kagbuo", "reply_indicator.cancel": "Kagbuo",
"report.categories.other": "Ọzọ", "report.categories.other": "Ọzọ",
"report.categories.spam": "Nzipụ Ozièlètrọniìk Nkeāchọghị",
"report.mute": "Mee ogbi",
"report.placeholder": "Type or paste additional comments", "report.placeholder": "Type or paste additional comments",
"report.submit": "Submit report", "report.submit": "Submit report",
"report.target": "Report {target}", "report.target": "Report {target}",
"report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached", "report_notification.attached_statuses": "{count, plural, one {# post} other {# posts}} attached",
"report_notification.categories.other": "Ọzọ",
"search.placeholder": "Chọọ",
"server_banner.active_users": "ojiarụ dị ìrè", "server_banner.active_users": "ojiarụ dị ìrè",
"server_banner.learn_more": "Mụtakwuo",
"sign_in_banner.sign_in": "Sign in", "sign_in_banner.sign_in": "Sign in",
"status.admin_status": "Open this status in the moderation interface", "status.admin_status": "Open this status in the moderation interface",
"status.bookmark": "Kee ebenrụtụakā", "status.bookmark": "Kee ebenrụtụakā",
"status.copy": "Copy link to status", "status.copy": "Copy link to status",
"status.delete": "Hichapụ", "status.delete": "Hichapụ",
"status.edit": "Dezie",
"status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}", "status.edited_x_times": "Edited {count, plural, one {# time} other {# times}}",
"status.open": "Expand this status", "status.open": "Expand this status",
"status.remove_bookmark": "Wepu ebenrụtụakā", "status.remove_bookmark": "Wepu ebenrụtụakā",

View file

@ -383,7 +383,6 @@
"lists.search": "Trovez inter personi quon vu sequas", "lists.search": "Trovez inter personi quon vu sequas",
"lists.subheading": "Vua listi", "lists.subheading": "Vua listi",
"load_pending": "{count, plural, one {# nova kozo} other {# nova kozi}}", "load_pending": "{count, plural, one {# nova kozo} other {# nova kozi}}",
"loading_indicator.label": "Kargante...",
"media_gallery.toggle_visible": "Chanjar videbleso", "media_gallery.toggle_visible": "Chanjar videbleso",
"moved_to_account_banner.text": "Vua konto {disabledAccount} es nune desaktiva pro ke vu movis a {movedToAccount}.", "moved_to_account_banner.text": "Vua konto {disabledAccount} es nune desaktiva pro ke vu movis a {movedToAccount}.",
"mute_modal.duration": "Durado", "mute_modal.duration": "Durado",

View file

@ -21,6 +21,7 @@
"account.blocked": "Útilokaður", "account.blocked": "Útilokaður",
"account.browse_more_on_origin_server": "Skoða nánari upplýsingar á notandasniðinu", "account.browse_more_on_origin_server": "Skoða nánari upplýsingar á notandasniðinu",
"account.cancel_follow_request": "Taka fylgjendabeiðni til baka", "account.cancel_follow_request": "Taka fylgjendabeiðni til baka",
"account.copy": "Afrita tengil í notandasnið",
"account.direct": "Einkaspjall við @{name}", "account.direct": "Einkaspjall við @{name}",
"account.disable_notifications": "Hætta að láta mig vita þegar @{name} sendir inn", "account.disable_notifications": "Hætta að láta mig vita þegar @{name} sendir inn",
"account.domain_blocked": "Lén útilokað", "account.domain_blocked": "Lén útilokað",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Merkja sem lesið", "conversation.mark_as_read": "Merkja sem lesið",
"conversation.open": "Skoða samtal", "conversation.open": "Skoða samtal",
"conversation.with": "Við {names}", "conversation.with": "Við {names}",
"copy_icon_button.copied": "Afritað á klippispjald",
"copypaste.copied": "Afritað", "copypaste.copied": "Afritað",
"copypaste.copy_to_clipboard": "Afrita á klippispjald", "copypaste.copy_to_clipboard": "Afrita á klippispjald",
"directory.federated": "Frá samtengdum vefþjónum", "directory.federated": "Frá samtengdum vefþjónum",
@ -390,7 +392,7 @@
"lists.search": "Leita meðal þeirra sem þú fylgist með", "lists.search": "Leita meðal þeirra sem þú fylgist með",
"lists.subheading": "Listarnir þínir", "lists.subheading": "Listarnir þínir",
"load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}", "load_pending": "{count, plural, one {# nýtt atriði} other {# ný atriði}}",
"loading_indicator.label": "Hleð inn...", "loading_indicator.label": "Hleð inn",
"media_gallery.toggle_visible": "Víxla sýnileika", "media_gallery.toggle_visible": "Víxla sýnileika",
"moved_to_account_banner.text": "Aðgangurinn þinn {disabledAccount} er óvirkur í augnablikinu vegna þess að þú fluttir þig yfir á {movedToAccount}.", "moved_to_account_banner.text": "Aðgangurinn þinn {disabledAccount} er óvirkur í augnablikinu vegna þess að þú fluttir þig yfir á {movedToAccount}.",
"mute_modal.duration": "Lengd", "mute_modal.duration": "Lengd",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Því miður er ekki hægt að birta neinar niðurstöður í augnablikinu. Þú getur reynt að nota leitina eða skoðað könnunarsíðuna til að finna fólk til að fylgjast með, nú eða prófað aftur síðar.", "onboarding.follows.empty": "Því miður er ekki hægt að birta neinar niðurstöður í augnablikinu. Þú getur reynt að nota leitina eða skoðað könnunarsíðuna til að finna fólk til að fylgjast með, nú eða prófað aftur síðar.",
"onboarding.follows.lead": "Þú ræktar heimastreymið þitt. Því fleira fólki sem þú fylgist með, því virkara og áhugaverðara verður það. Að fylgjast með þessum notendum gæti verið ágætt til að byrja með - þú getur alltaf hætt að fylgjast með þeim síðar!", "onboarding.follows.lead": "Þú ræktar heimastreymið þitt. Því fleira fólki sem þú fylgist með, því virkara og áhugaverðara verður það. Að fylgjast með þessum notendum gæti verið ágætt til að byrja með - þú getur alltaf hætt að fylgjast með þeim síðar!",
"onboarding.follows.title": "Vinsælt á Mastodon", "onboarding.follows.title": "Vinsælt á Mastodon",
"onboarding.profile.discoverable": "Hafa notandasnið og færslur með í reikniritum leitar",
"onboarding.profile.display_name": "Birtingarnafn",
"onboarding.profile.display_name_hint": "Fullt nafn þitt eða eitthvað til gamans…",
"onboarding.profile.indexable": "Hafa opinberar færslur með í leitarniðurstöðum",
"onboarding.profile.lead": "Þú getur alltaf klárað þetta seinna í stillingunum, þar sem enn fleiri möguleikar bjóðast á sérsníðingum.",
"onboarding.profile.note": "Æviágrip",
"onboarding.profile.note_hint": "Þú getur @minnst á annað fólk eða #myllumerki…",
"onboarding.profile.save_and_continue": "Vista og halda áfram",
"onboarding.profile.title": "Uppsetning notandasniðs",
"onboarding.profile.upload_avatar": "Sendu inn auðkennismynd",
"onboarding.profile.upload_header": "Sendu inn bakgrunnsmynd í haus notandasniðs",
"onboarding.share.lead": "Láttu fólk vita hvernig það getur fundið þig á Mastodon!", "onboarding.share.lead": "Láttu fólk vita hvernig það getur fundið þig á Mastodon!",
"onboarding.share.message": "Ég heiti {username} á #Mastodon! Þú getur fylgst með mér á {url}", "onboarding.share.message": "Ég heiti {username} á #Mastodon! Þú getur fylgst með mér á {url}",
"onboarding.share.next_steps": "Möguleg næstu skref:", "onboarding.share.next_steps": "Möguleg næstu skref:",

View file

@ -21,6 +21,7 @@
"account.blocked": "Bloccato", "account.blocked": "Bloccato",
"account.browse_more_on_origin_server": "Sfoglia di più sul profilo originale", "account.browse_more_on_origin_server": "Sfoglia di più sul profilo originale",
"account.cancel_follow_request": "Annulla la richiesta di seguire", "account.cancel_follow_request": "Annulla la richiesta di seguire",
"account.copy": "Copia link del profilo",
"account.direct": "Menziona privatamente @{name}", "account.direct": "Menziona privatamente @{name}",
"account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post", "account.disable_notifications": "Smetti di avvisarmi quando @{name} pubblica un post",
"account.domain_blocked": "Dominio bloccato", "account.domain_blocked": "Dominio bloccato",
@ -191,6 +192,7 @@
"conversation.mark_as_read": "Segna come letto", "conversation.mark_as_read": "Segna come letto",
"conversation.open": "Visualizza conversazione", "conversation.open": "Visualizza conversazione",
"conversation.with": "Con {names}", "conversation.with": "Con {names}",
"copy_icon_button.copied": "Copiato negli appunti",
"copypaste.copied": "Copiato", "copypaste.copied": "Copiato",
"copypaste.copy_to_clipboard": "Copia negli Appunti", "copypaste.copy_to_clipboard": "Copia negli Appunti",
"directory.federated": "Da un fediverse noto", "directory.federated": "Da un fediverse noto",
@ -252,7 +254,7 @@
"explore.search_results": "Risultati della ricerca", "explore.search_results": "Risultati della ricerca",
"explore.suggested_follows": "Persone", "explore.suggested_follows": "Persone",
"explore.title": "Esplora", "explore.title": "Esplora",
"explore.trending_links": "Novità", "explore.trending_links": "Notizie",
"explore.trending_statuses": "Post", "explore.trending_statuses": "Post",
"explore.trending_tags": "Hashtag", "explore.trending_tags": "Hashtag",
"filter_modal.added.context_mismatch_explanation": "La categoria di questo filtro non si applica al contesto in cui hai acceduto a questo post. Se desideri che il post sia filtrato anche in questo contesto, dovrai modificare il filtro.", "filter_modal.added.context_mismatch_explanation": "La categoria di questo filtro non si applica al contesto in cui hai acceduto a questo post. Se desideri che il post sia filtrato anche in questo contesto, dovrai modificare il filtro.",
@ -390,7 +392,7 @@
"lists.search": "Cerca tra le persone che segui", "lists.search": "Cerca tra le persone che segui",
"lists.subheading": "Le tue liste", "lists.subheading": "Le tue liste",
"load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}", "load_pending": "{count, plural, one {# nuovo oggetto} other {# nuovi oggetti}}",
"loading_indicator.label": "Caricamento...", "loading_indicator.label": "Caricamento",
"media_gallery.toggle_visible": "{number, plural, one {Nascondi immagine} other {Nascondi immagini}}", "media_gallery.toggle_visible": "{number, plural, one {Nascondi immagine} other {Nascondi immagini}}",
"moved_to_account_banner.text": "Il tuo profilo {disabledAccount} è correntemente disabilitato perché ti sei spostato a {movedToAccount}.", "moved_to_account_banner.text": "Il tuo profilo {disabledAccount} è correntemente disabilitato perché ti sei spostato a {movedToAccount}.",
"mute_modal.duration": "Durata", "mute_modal.duration": "Durata",
@ -479,6 +481,17 @@
"onboarding.follows.empty": "Sfortunatamente, nessun risultato può essere mostrato in questo momento. Puoi provare a utilizzare la ricerca o sfogliare la pagina di esplorazione per trovare persone da seguire, oppure riprova più tardi.", "onboarding.follows.empty": "Sfortunatamente, nessun risultato può essere mostrato in questo momento. Puoi provare a utilizzare la ricerca o sfogliare la pagina di esplorazione per trovare persone da seguire, oppure riprova più tardi.",
"onboarding.follows.lead": "La cronologia della tua home è gestita da te. Più persone segui, più attiva e interessante sarà. Questi profili possono essere un buon punto di partenza; puoi sempre smettere di seguirli in seguito!", "onboarding.follows.lead": "La cronologia della tua home è gestita da te. Più persone segui, più attiva e interessante sarà. Questi profili possono essere un buon punto di partenza; puoi sempre smettere di seguirli in seguito!",
"onboarding.follows.title": "Popolare su Mastodon", "onboarding.follows.title": "Popolare su Mastodon",
"onboarding.profile.discoverable": "Include il profilo e i post negli algoritmi di scoperta",
"onboarding.profile.display_name": "Nome da visualizzare",
"onboarding.profile.display_name_hint": "Il tuo nome completo o il tuo nome divertente…",
"onboarding.profile.indexable": "Includi i post pubblici nei risultati di ricerca",
"onboarding.profile.lead": "Puoi sempre completarlo in un secondo momento nelle impostazioni, dove sono disponibili ancora più opzioni di personalizzazione.",
"onboarding.profile.note": "Biografia",
"onboarding.profile.note_hint": "Puoi @menzionare altre persone o #hashtags…",
"onboarding.profile.save_and_continue": "Salva e continua",
"onboarding.profile.title": "Configurazione del profilo",
"onboarding.profile.upload_avatar": "Carica l'immagine del profilo",
"onboarding.profile.upload_header": "Carica l'intestazione del profilo",
"onboarding.share.lead": "Fai sapere alle persone come possono trovarti su Mastodon!", "onboarding.share.lead": "Fai sapere alle persone come possono trovarti su Mastodon!",
"onboarding.share.message": "Sono {username} su #Mastodon! Vieni a seguirmi su {url}", "onboarding.share.message": "Sono {username} su #Mastodon! Vieni a seguirmi su {url}",
"onboarding.share.next_steps": "Possibili passaggi successivi:", "onboarding.share.next_steps": "Possibili passaggi successivi:",

View file

@ -390,7 +390,7 @@
"lists.search": "フォローしている人の中から検索", "lists.search": "フォローしている人の中から検索",
"lists.subheading": "あなたのリスト", "lists.subheading": "あなたのリスト",
"load_pending": "{count}件の新着", "load_pending": "{count}件の新着",
"loading_indicator.label": "読み込み中...", "loading_indicator.label": "",
"media_gallery.toggle_visible": "{number, plural, one {画像を閉じる} other {画像を閉じる}}", "media_gallery.toggle_visible": "{number, plural, one {画像を閉じる} other {画像を閉じる}}",
"moved_to_account_banner.text": "あなたのアカウント『{disabledAccount}』は『{movedToAccount}』に移動したため現在無効になっています。", "moved_to_account_banner.text": "あなたのアカウント『{disabledAccount}』は『{movedToAccount}』に移動したため現在無効になっています。",
"mute_modal.duration": "ミュートする期間", "mute_modal.duration": "ミュートする期間",
@ -586,8 +586,8 @@
"search.no_recent_searches": "検索履歴はありません", "search.no_recent_searches": "検索履歴はありません",
"search.placeholder": "検索", "search.placeholder": "検索",
"search.quick_action.account_search": "{x}に該当するプロフィール", "search.quick_action.account_search": "{x}に該当するプロフィール",
"search.quick_action.go_to_account": "{x}のプロフィールを見る", "search.quick_action.go_to_account": "プロフィール {x} を見る",
"search.quick_action.go_to_hashtag": "{x}に該当するハッシュタグ", "search.quick_action.go_to_hashtag": "ハッシュタグ {x} を見る",
"search.quick_action.open_url": "MastodonでURLを開く", "search.quick_action.open_url": "MastodonでURLを開く",
"search.quick_action.status_search": "{x}に該当する投稿", "search.quick_action.status_search": "{x}に該当する投稿",
"search.search_or_paste": "検索またはURLを入力", "search.search_or_paste": "検索またはURLを入力",

View file

@ -165,7 +165,6 @@
"lists.new.title_placeholder": "ახალი სიის სათაური", "lists.new.title_placeholder": "ახალი სიის სათაური",
"lists.search": "ძებნა ადამიანებს შორის რომელთაც მიჰყვებით", "lists.search": "ძებნა ადამიანებს შორის რომელთაც მიჰყვებით",
"lists.subheading": "თქვენი სიები", "lists.subheading": "თქვენი სიები",
"loading_indicator.label": "იტვირთება...",
"media_gallery.toggle_visible": "ხილვადობის ჩართვა", "media_gallery.toggle_visible": "ხილვადობის ჩართვა",
"mute_modal.hide_notifications": "დავმალოთ შეტყობინებები ამ მომხმარებლისგან?", "mute_modal.hide_notifications": "დავმალოთ შეტყობინებები ამ მომხმარებლისგან?",
"navigation_bar.blocks": "დაბლოკილი მომხმარებლები", "navigation_bar.blocks": "დაბლოკილი მომხმარებლები",

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