Browse Source

Merge pull request #377 from glitch-soc/merge-upstream

hhhhhhhhhnnnnnnnnnnnghh!!!!!
closed-social-glitch-2
beatrix 6 years ago
committed by GitHub
parent
commit
43a9a781a4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
159 changed files with 3553 additions and 1570 deletions
  1. +12
    -3
      .env.production.sample
  2. +6
    -2
      Gemfile
  3. +8
    -8
      Gemfile.lock
  4. +29
    -7
      app/controllers/accounts_controller.rb
  5. +4
    -0
      app/controllers/api/base_controller.rb
  6. +0
    -4
      app/controllers/api/v1/accounts/search_controller.rb
  7. +3
    -3
      app/controllers/api/v1/accounts/statuses_controller.rb
  8. +3
    -3
      app/controllers/api/v1/accounts_controller.rb
  9. +6
    -6
      app/controllers/api/v1/reports_controller.rb
  10. +1
    -5
      app/controllers/api/v1/search_controller.rb
  11. +11
    -3
      app/controllers/api/v1/timelines/public_controller.rb
  12. +11
    -3
      app/controllers/api/v1/timelines/tag_controller.rb
  13. +3
    -3
      app/controllers/application_controller.rb
  14. +1
    -1
      app/controllers/auth/sessions_controller.rb
  15. +2
    -0
      app/controllers/follower_accounts_controller.rb
  16. +2
    -0
      app/controllers/following_accounts_controller.rb
  17. +198
    -169
      app/javascript/flavours/glitch/styles/about.scss
  18. +9
    -0
      app/javascript/mastodon/actions/reports.js
  19. +2
    -2
      app/javascript/mastodon/actions/timelines.js
  20. +3
    -2
      app/javascript/mastodon/components/media_gallery.js
  21. +1
    -0
      app/javascript/mastodon/components/status.js
  22. +2
    -2
      app/javascript/mastodon/features/account/components/action_bar.js
  23. +9
    -7
      app/javascript/mastodon/features/account_gallery/components/media_item.js
  24. +0
    -5
      app/javascript/mastodon/features/account_gallery/index.js
  25. +8
    -0
      app/javascript/mastodon/features/account_timeline/components/header.js
  26. +14
    -9
      app/javascript/mastodon/features/account_timeline/index.js
  27. +3
    -2
      app/javascript/mastodon/features/compose/components/search.js
  28. +1
    -0
      app/javascript/mastodon/features/status/components/detailed_status.js
  29. +5
    -6
      app/javascript/mastodon/features/ui/components/bundle.js
  30. +13
    -4
      app/javascript/mastodon/features/ui/components/columns_area.js
  31. +35
    -12
      app/javascript/mastodon/features/ui/components/report_modal.js
  32. +1
    -2
      app/javascript/mastodon/features/ui/components/tabs_bar.js
  33. +1
    -0
      app/javascript/mastodon/features/ui/index.js
  34. +8
    -3
      app/javascript/mastodon/features/ui/util/react_router_helpers.js
  35. +22
    -3
      app/javascript/mastodon/features/video/index.js
  36. +1
    -0
      app/javascript/mastodon/initial_state.js
  37. +10
    -2
      app/javascript/mastodon/locales/ar.json
  38. +8
    -0
      app/javascript/mastodon/locales/bg.json
  39. +42
    -34
      app/javascript/mastodon/locales/ca.json
  40. +8
    -0
      app/javascript/mastodon/locales/de.json
  41. +40
    -4
      app/javascript/mastodon/locales/defaultMessages.json
  42. +8
    -0
      app/javascript/mastodon/locales/en.json
  43. +147
    -139
      app/javascript/mastodon/locales/eo.json
  44. +8
    -0
      app/javascript/mastodon/locales/es.json
  45. +8
    -0
      app/javascript/mastodon/locales/fa.json
  46. +196
    -188
      app/javascript/mastodon/locales/fi.json
  47. +10
    -2
      app/javascript/mastodon/locales/fr.json
  48. +9
    -1
      app/javascript/mastodon/locales/gl.json
  49. +8
    -0
      app/javascript/mastodon/locales/he.json
  50. +8
    -0
      app/javascript/mastodon/locales/hr.json
  51. +9
    -1
      app/javascript/mastodon/locales/hu.json
  52. +8
    -0
      app/javascript/mastodon/locales/hy.json
  53. +8
    -0
      app/javascript/mastodon/locales/id.json
  54. +8
    -0
      app/javascript/mastodon/locales/io.json
  55. +8
    -0
      app/javascript/mastodon/locales/it.json
  56. +11
    -3
      app/javascript/mastodon/locales/ja.json
  57. +8
    -0
      app/javascript/mastodon/locales/ko.json
  58. +9
    -1
      app/javascript/mastodon/locales/nl.json
  59. +8
    -0
      app/javascript/mastodon/locales/no.json
  60. +8
    -0
      app/javascript/mastodon/locales/oc.json
  61. +9
    -4
      app/javascript/mastodon/locales/pl.json
  62. +9
    -1
      app/javascript/mastodon/locales/pt-BR.json
  63. +8
    -0
      app/javascript/mastodon/locales/pt.json
  64. +8
    -0
      app/javascript/mastodon/locales/ru.json
  65. +25
    -17
      app/javascript/mastodon/locales/sk.json
  66. +8
    -0
      app/javascript/mastodon/locales/sr-Latn.json
  67. +8
    -0
      app/javascript/mastodon/locales/sr.json
  68. +8
    -0
      app/javascript/mastodon/locales/sv.json
  69. +8
    -0
      app/javascript/mastodon/locales/th.json
  70. +8
    -0
      app/javascript/mastodon/locales/tr.json
  71. +8
    -0
      app/javascript/mastodon/locales/uk.json
  72. +8
    -0
      app/javascript/mastodon/locales/zh-CN.json
  73. +8
    -0
      app/javascript/mastodon/locales/zh-HK.json
  74. +8
    -0
      app/javascript/mastodon/locales/zh-TW.json
  75. +4
    -0
      app/javascript/mastodon/reducers/reports.js
  76. +197
    -166
      app/javascript/styles/mastodon/about.scss
  77. +46
    -37
      app/javascript/styles/mastodon/accounts.scss
  78. +176
    -39
      app/javascript/styles/mastodon/components.scss
  79. +5
    -0
      app/javascript/styles/mastodon/forms.scss
  80. +2
    -0
      app/lib/activitypub/activity.rb
  81. +25
    -0
      app/lib/activitypub/activity/flag.rb
  82. +2
    -0
      app/lib/activitypub/activity/reject.rb
  83. +1
    -0
      app/lib/exceptions.rb
  84. +18
    -1
      app/lib/request.rb
  85. +11
    -0
      app/lib/sidekiq_error_handler.rb
  86. +9
    -0
      app/models/concerns/paginable.rb
  87. +1
    -1
      app/models/import.rb
  88. +4
    -0
      app/models/report.rb
  89. +21
    -5
      app/models/user.rb
  90. +27
    -0
      app/serializers/activitypub/flag_serializer.rb
  91. +1
    -0
      app/serializers/initial_state_serializer.rb
  92. +10
    -1
      app/serializers/rest/instance_serializer.rb
  93. +54
    -0
      app/services/report_service.rb
  94. +101
    -47
      app/views/about/show.html.haml
  95. +23
    -0
      app/views/accounts/_follow_button.html.haml
  96. +5
    -2
      app/views/accounts/_grid_card.html.haml
  97. +1
    -18
      app/views/accounts/_header.html.haml
  98. +5
    -2
      app/views/accounts/show.html.haml
  99. +2
    -2
      app/views/auth/passwords/edit.html.haml
  100. +2
    -2
      app/views/auth/registrations/edit.html.haml

+ 12
- 3
.env.production.sample View File

@ -33,7 +33,6 @@ LOCAL_DOMAIN=example.com
# Application secrets
# Generate each with the `RAILS_ENV=production bundle exec rake secret` task (`docker-compose run --rm web rake secret` if you use docker compose)
PAPERCLIP_SECRET=
SECRET_KEY_BASE=
OTP_SECRET=
@ -143,6 +142,16 @@ STREAMING_CLUSTER_NUM=1
# Maximum allowed character count
# MAX_TOOT_CHARS=500
# LDAP authentication (optional)
# LDAP_ENABLED=true
# LDAP_HOST=localhost
# LDAP_PORT=389
# LDAP_METHOD=simple_tls
# LDAP_BASE=
# LDAP_BIND_DN=
# LDAP_PASSWORD=
# LDAP_UID=cn
# PAM authentication (optional)
# PAM authentication uses for the email generation the "email" pam variable
# and optional as fallback PAM_DEFAULT_SUFFIX
@ -153,7 +162,7 @@ STREAMING_CLUSTER_NUM=1
# PAM_DEFAULT_SUFFIX=pam
# Name of the pam service (pam "auth" section is evaluated)
# PAM_DEFAULT_SERVICE=rpam
# Name of the pam service used for checking if an user can register (pam "account" section is evaluated)
# Name of the pam service used for checking if an user can register (pam "account" section is evaluated) (nil (disabled) by default)
# PAM_CONTROLLED_SERVICE=rpam
# Global OAuth settings (optional) :
@ -186,7 +195,7 @@ STREAMING_CLUSTER_NUM=1
# Optional SAML authentication (cf. omniauth-saml)
# SAML_ENABLED=true
# SAML_ACS_URL=
# SAML_ISSUER=http://localhost:3000/auth/auth/saml/metadata
# SAML_ISSUER=http://localhost:3000/auth/auth/saml/callback
# SAML_IDP_SSO_TARGET_URL=https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO
# SAML_IDP_CERT=
# SAML_IDP_CERT_FINGERPRINT=

+ 6
- 2
Gemfile View File

@ -7,7 +7,6 @@ gem 'pkg-config', '~> 1.2'
gem 'puma', '~> 3.10'
gem 'rails', '~> 5.1.4'
gem 'uglifier', '~> 3.2'
gem 'hamlit-rails', '~> 0.2'
gem 'pg', '~> 0.20'
@ -35,8 +34,9 @@ gem 'devise', '~> 4.4'
gem 'devise-two-factor', '~> 3.0'
gem 'devise_pam_authenticatable2', '~> 8.0', install_if: -> { ENV['PAM_ENABLED'] == 'true' }
gem 'net-ldap', '~> 0.10', install_if: -> { ENV['LDAP_ENABLED'] == 'true' }
gem 'omniauth-cas', '~> 1.1', install_if: -> { ENV['CAS_ENABLED'] == 'true' }
gem 'omniauth-saml', '~> 1.8', install_if: -> { ENV['SAML_ENABLED'] == 'true' }
gem 'omniauth-saml', '~> 1.10', install_if: -> { ENV['SAML_ENABLED'] == 'true' }
gem 'omniauth', '~> 1.2'
gem 'doorkeeper', '~> 4.2'
@ -98,6 +98,10 @@ group :development, :test do
gem 'rspec-rails', '~> 3.7'
end
group :production, :test do
gem 'private_address_check', '~> 0.4.1'
end
group :test do
gem 'capybara', '~> 2.15'
gem 'climate_control', '~> 0.2'

+ 8
- 8
Gemfile.lock View File

@ -178,7 +178,6 @@ GEM
et-orbi (1.0.8)
tzinfo
excon (0.59.0)
execjs (2.7.0)
fabrication (2.18.0)
faker (1.8.4)
i18n (~> 0.5)
@ -319,6 +318,7 @@ GEM
multi_json (1.12.2)
multipart-post (2.0.0)
necromancer (0.4.0)
net-ldap (0.16.1)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (4.2.0)
@ -340,9 +340,9 @@ GEM
addressable (~> 2.3)
nokogiri (~> 1.5)
omniauth (~> 1.2)
omniauth-saml (1.9.0)
omniauth-saml (1.10.0)
omniauth (~> 1.3, >= 1.3.2)
ruby-saml (~> 1.4, >= 1.4.3)
ruby-saml (~> 1.7)
orm_adapter (0.5.0)
ostatus2 (2.0.3)
addressable (~> 2.5)
@ -379,6 +379,7 @@ GEM
premailer-rails (1.10.1)
actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9)
private_address_check (0.4.1)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@ -498,7 +499,7 @@ GEM
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-oembed (0.12.0)
ruby-progressbar (1.9.0)
ruby-saml (1.6.1)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
rufus-scheduler (3.4.2)
et-orbi (~> 1.0)
@ -586,8 +587,6 @@ GEM
thread_safe (~> 0.1)
tzinfo-data (1.2017.3)
tzinfo (>= 1.0.0)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.4)
@ -672,12 +671,13 @@ DEPENDENCIES
memory_profiler
microformats (~> 4.0)
mime-types (~> 3.1)
net-ldap (~> 0.10)
nokogiri (~> 1.8)
nsa (~> 0.2)
oj (~> 3.3)
omniauth (~> 1.2)
omniauth-cas (~> 1.1)
omniauth-saml (~> 1.8)
omniauth-saml (~> 1.10)
ostatus2 (~> 2.0)
ox (~> 2.8)
paperclip (~> 5.1)
@ -688,6 +688,7 @@ DEPENDENCIES
pkg-config (~> 1.2)
posix-spawn
premailer-rails
private_address_check (~> 0.4.1)
pry-rails (~> 0.3)
puma (~> 3.10)
pundit (~> 1.1)
@ -724,7 +725,6 @@ DEPENDENCIES
tty-prompt
twitter-text (~> 1.14)
tzinfo-data (~> 1.2017)
uglifier (~> 3.2)
webmock (~> 3.0)
webpacker (~> 3.0)
webpush

+ 29
- 7
app/controllers/accounts_controller.rb View File

@ -1,6 +1,8 @@
# frozen_string_literal: true
class AccountsController < ApplicationController
PAGE_SIZE = 20
include AccountControllerConcern
before_action :set_cache_headers
@ -17,13 +19,16 @@ class AccountsController < ApplicationController
end
@pinned_statuses = cache_collection(@account.pinned_statuses, Status) if show_pinned_statuses?
@statuses = filtered_statuses.paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = filtered_status_page(params)
@statuses = cache_collection(@statuses, Status)
@next_url = next_url unless @statuses.empty?
unless @statuses.empty?
@older_url = older_url if @statuses.last.id > filtered_statuses.last.id
@newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
end
end
format.atom do
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20n class="o">, params[:max_id], params[:since_id])
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id])
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? }))
end
@ -70,13 +75,22 @@ class AccountsController < ApplicationController
@account = Account.find_local!(params[:username])
end
def next_url
def older_url
::Rails.logger.info("older: max_id #{@statuses.last.id}, url #{pagination_url(max_id: @statuses.last.id)}")
pagination_url(max_id: @statuses.last.id)
end
def newer_url
pagination_url(min_id: @statuses.first.id)
end
def pagination_url(max_id: nil, min_id: nil)
if media_requested?
short_account_media_url(@account, max_id: @statuses.last.id)
short_account_media_url(@account, max_id: max_id, min_id: min_id)
elsif replies_requested?
short_account_with_replies_url(@account, max_id: @statuses.last.id)
short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
else
short_account_url(@account, max_id: @statuses.last.id)
short_account_url(@account, max_id: max_id, min_id: min_id)
end
end
@ -87,4 +101,12 @@ class AccountsController < ApplicationController
def replies_requested?
request.path.ends_with?('/with_replies')
end
def filtered_status_page(params)
if params[:min_id].present?
filtered_statuses.paginate_by_min_id(PAGE_SIZE, params[:min_id]).reverse
else
filtered_statuses.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id]).to_a
end
end
end

+ 4
- 0
app/controllers/api/base_controller.rb View File

@ -51,6 +51,10 @@ class Api::BaseController < ApplicationController
[params[:limit].to_i.abs, default_limit * 2].min
end
def truthy_param?(key)
ActiveModel::Type::Boolean.new.cast(params[key])
end
def current_resource_owner
@current_user ||= User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end

+ 0
- 4
app/controllers/api/v1/accounts/search_controller.rb View File

@ -22,8 +22,4 @@ class Api::V1::Accounts::SearchController < Api::BaseController
following: truthy_param?(:following)
)
end
def truthy_param?(key)
params[key] == 'true'
end
end

+ 3
- 3
app/controllers/api/v1/accounts/statuses_controller.rb View File

@ -28,9 +28,9 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
def account_statuses
default_statuses.tap do |statuses|
statuses.merge!(only_media_scope) if params[:only_media]
statuses.merge!(pinned_scope) if params[:pinned]
statuses.merge!(no_replies_scope) if params[:exclude_replies]
statuses.merge!(only_media_scope) if truthy_param?(:only_media)
statuses.merge!(pinned_scope) if truthy_param?(:pinned)
statuses.merge!(no_replies_scope) if truthy_param?(:exclude_replies)
end
end

+ 3
- 3
app/controllers/api/v1/accounts_controller.rb View File

@ -13,9 +13,9 @@ class Api::V1::AccountsController < Api::BaseController
end
def follow
FollowService.new.call(current_user.account, @account.acct, reblogs: params[:reblogs])
FollowService.new.call(current_user.account, @account.acct, reblogs: truthy_param?(:reblogs))
options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: params[:reblogs] } }, requested_map: { @account.id => false } }
options = @account.locked? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } }
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships(options)
end
@ -26,7 +26,7 @@ class Api::V1::AccountsController < Api::BaseController
end
def mute
MuteService.new.call(current_user.account, @account, notifications: params[:notifications])
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications))
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end

+ 6
- 6
app/controllers/api/v1/reports_controller.rb View File

@ -13,14 +13,14 @@ class Api::V1::ReportsController < Api::BaseController
end
def create
@report = current_account.reports.create!(
target_account: reported_account,
@report = ReportService.new.call(
current_account,
reported_account,
status_ids: reported_status_ids,
comment: report_params[:comment]
comment: report_params[:comment],
forward: report_params[:forward]
)
User.staff.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
render json: @report, serializer: REST::ReportSerializer
end
@ -39,6 +39,6 @@ class Api::V1::ReportsController < Api::BaseController
end
def report_params
params.permit(:account_id, :comment, status_ids: [])
params.permit(:account_id, :comment, :forward, status_ids: [])
end
end

+ 1
- 5
app/controllers/api/v1/search_controller.rb View File

@ -33,12 +33,8 @@ class Api::V1::SearchController < Api::BaseController
SearchService.new.call(
params[:q],
RESULTS_LIMIT,
resolving_search?,
truthy_param?(:resolve),
current_account
)
end
def resolving_search?
params[:resolve] == 'true'
end
end

+ 11
- 3
app/controllers/api/v1/timelines/public_controller.rb View File

@ -21,15 +21,23 @@ class Api::V1::Timelines::PublicController < Api::BaseController
end
def public_statuses
public_timeline_statuses.paginate_by_max_id(
statuses = public_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
if truthy_param?(:only_media)
# `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.
status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id)
statuses.where(id: status_ids)
else
statuses
end
end
def public_timeline_statuses
Status.as_public_timeline(current_account, params[:local])
Status.as_public_timeline(current_account, truthy_param?(:local))
end
def insert_pagination_headers
@ -37,7 +45,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
params.permit(:local, :limit, :only_media).merge(core_params)
end
def next_path

+ 11
- 3
app/controllers/api/v1/timelines/tag_controller.rb View File

@ -29,16 +29,24 @@ class Api::V1::Timelines::TagController < Api::BaseController
if @tag.nil?
[]
else
tag_timeline_statuses.paginate_by_max_id(
statuses = tag_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
if truthy_param?(:only_media)
# `SELECT DISTINCT id, updated_at` is too slow, so pluck ids at first, and then select id, updated_at with ids.
status_ids = statuses.joins(:media_attachments).distinct(:id).pluck(:id)
statuses.where(id: status_ids)
else
statuses
end
end
end
def tag_timeline_statuses
Status.as_tag_timeline(@tag, current_account, params[:local])
Status.as_tag_timeline(@tag, current_account, truthy_param?(:local))
end
def insert_pagination_headers
@ -46,7 +54,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
params.permit(:local, :limit, :only_media).merge(core_params)
end
def next_path

+ 3
- 3
app/controllers/application_controller.rb View File

@ -15,7 +15,7 @@ class ApplicationController < ActionController::Base
helper_method :current_flavour
helper_method :current_skin
helper_method :single_user_mode?
helper_method :use_pam?
helper_method :use_seamless_external_login?
rescue_from ActionController::RoutingError, with: :not_found
rescue_from ActiveRecord::RecordNotFound, with: :not_found
@ -146,8 +146,8 @@ class ApplicationController < ActionController::Base
@single_user_mode ||= Rails.configuration.x.single_user_mode && Account.exists?
end
def use_pam?
Devise.pam_authentication
def use_seamless_external_login?
Devise.pam_authentication || Devise.ldap_authentication
end
def current_account

+ 1
- 1
app/controllers/auth/sessions_controller.rb View File

@ -38,7 +38,7 @@ class Auth::SessionsController < Devise::SessionsController
if session[:otp_user_id]
User.find(session[:otp_user_id])
elsif user_params[:email]
if use_pam? && Devise.check_at_sign && user_params[:email].index('@').nil?
if use_seamless_external_login? && Devise.check_at_sign && user_params[:email].index('@').nil?
User.joins(:account).find_by(accounts: { username: user_params[:email] })
else
User.find_for_authentication(email: user_params[:email])

+ 2
- 0
app/controllers/follower_accounts_controller.rb View File

@ -9,6 +9,8 @@ class FollowerAccountsController < ApplicationController
respond_to do |format|
format.html do
use_pack 'public'
@relationships = AccountRelationshipsPresenter.new(@follows.map(&:account_id), current_user.account_id) if user_signed_in?
end
format.json do

+ 2
- 0
app/controllers/following_accounts_controller.rb View File

@ -9,6 +9,8 @@ class FollowingAccountsController < ApplicationController
respond_to do |format|
format.html do
use_pack 'public'
@relationships = AccountRelationshipsPresenter.new(@follows.map(&:target_account_id), current_user.account_id) if user_signed_in?
end
format.json do

+ 198
- 169
app/javascript/flavours/glitch/styles/about.scss View File

@ -15,117 +15,169 @@ $small-breakpoint: 960px;
}
}
.show-xs,
.show-sm {
display: none;
}
.landing-page {
.grid {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 2fr;
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
display: none;
}
.show-m {
display: block;
}
.column-1 {
grid-column: 1;
grid-row: 1;
}
@media screen and (max-width: $small-breakpoint) {
.hide-sm {
display: none !important;
}
.column-2 {
grid-column: 2;
grid-row: 1;
}
.show-sm {
display: block !important;
}
}
.column-3 {
grid-column: 3;
grid-row: 1 / 3;
}
@media screen and (max-width: $column-breakpoint) {
.hide-xs {
display: none !important;
.column-4 {
grid-column: 1 / 3;
grid-row: 2;
}
}
.show-xs {
display: block !important;
}
}
@media screen and (max-width: $small-breakpoint) {
.grid {
grid-template-columns: 40% 60%;
.row {
display: flex;
flex-wrap: wrap;
margin: 0 -5px;
.column-0 {
display: none;
}
@for $i from 1 through 15 {
.column-#{$i} {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
.column-1 {
grid-column: 1;
grid-row: 1;
@media screen and (max-width: $small-breakpoint) {
&-sm {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
&.non-preview .landing-page__forms {
height: 100%;
}
}
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
.column-2 {
grid-column: 2;
grid-row: 1 / 3;
&:last-child {
margin-bottom: 0;
&.non-preview {
grid-column: 2;
grid-row: 1;
}
}
.column-3 {
grid-column: 1;
grid-row: 2 / 4;
}
.column-4 {
grid-column: 2;
grid-row: 3;
&.non-preview {
grid-column: 1 / 3;
grid-row: 2;
}
}
}
}
}
.column-flex {
display: flex;
flex-direction: column;
}
@media screen and (max-width: $column-breakpoint) {
.grid {
grid-template-columns: auto;
.separator-or {
position: relative;
margin: 40px 0;
text-align: center;
.column-0 {
display: block;
grid-column: 1;
grid-row: 1;
}
&::before {
content: "";
display: block;
width: 100%;
height: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
position: absolute;
top: 50%;
left: 0;
.column-1 {
grid-column: 1;
grid-row: 3;
.brand {
display: none;
}
}
.column-2 {
grid-column: 1;
grid-row: 2;
.landing-page__logo,
.landing-page__call-to-action {
display: none;
}
&.non-preview {
grid-column: 1;
grid-row: 2;
}
}
.column-3 {
grid-column: 1;
grid-row: 5;
}
.column-4 {
grid-column: 1;
grid-row: 4;
&.non-preview {
grid-column: 1;
grid-row: 4;
}
}
}
}
span {
display: inline-block;
background: $ui-base-color;
font-size: 12px;
font-weight: 500;
color: $ui-primary-color;
text-transform: uppercase;
.column-flex {
display: flex;
flex-direction: column;
}
.separator-or {
position: relative;
z-index: 1;
padding: 0 8px;
cursor: default;
margin: 40px 0;
text-align: center;
&::before {
content: "";
display: block;
width: 100%;
height: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
position: absolute;
top: 50%;
left: 0;
}
span {
display: inline-block;
background: $ui-base-color;
font-size: 12px;
font-weight: 500;
color: $ui-primary-color;
text-transform: uppercase;
position: relative;
z-index: 1;
padding: 0 8px;
cursor: default;
}
}
}
.landing-page {
p,
li {
font-family: 'mastodon-font-sans-serif', sans-serif;
@ -502,7 +554,7 @@ $small-breakpoint: 960px;
display: block;
width: 80px;
height: 80px;
border-radius: $ui-avatar-border-size;
border-radius: 48px;
}
}
@ -539,6 +591,7 @@ $small-breakpoint: 960px;
img {
position: static;
padding: 10px 0;
}
@media screen and (max-width: $small-breakpoint) {
@ -558,18 +611,33 @@ $small-breakpoint: 960px;
}
&__call-to-action {
margin-bottom: 10px;
background: darken($ui-base-color, 4%);
border-radius: 4px;
padding: 25px 40px;
overflow: hidden;
.row {
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.information-board__section {
padding: 0;
.row__information-board {
display: flex;
justify-content: flex-end;
align-items: flex-end;
.information-board__section {
flex: 1 0 auto;
padding: 0 10px;
}
}
.row__mascot {
flex: 1;
margin: 10px -50px 0 0;
}
}
@ -619,6 +687,8 @@ $small-breakpoint: 960px;
&__short-description {
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 40px;
}
@ -668,7 +738,6 @@ $small-breakpoint: 960px;
height: 100%;
@media screen and (max-width: $small-breakpoint) {
margin-bottom: 10px;
height: auto;
}
@ -717,15 +786,14 @@ $small-breakpoint: 960px;
width: 100%;
flex: 1 1 auto;
overflow: hidden;
height: 100%;
.column-header {
color: inherit;
font-family: inherit;
font-size: 16px;
padding: 15px;
line-height: inherit;
font-weight: inherit;
margin: 0;
}
.column {
@ -942,93 +1010,54 @@ $small-breakpoint: 960px;
}
&.tag-page {
.features {
padding: 30px 0;
.container-alt {
max-width: 820px;
#mastodon-timeline {
margin-right: 0;
border-top-right-radius: 0;
}
.about-mastodon {
.about-hashtag {
background: darken($ui-base-color, 4%);
padding: 0 20px 20px 30px;
border-radius: 0 5px 5px 0;
.brand {
padding-top: 20px;
margin-bottom: 20px;
img {
height: 48px;
width: auto;
}
}
p {
strong {
color: $ui-secondary-color;
font-weight: 700;
}
}
.grid {
@media screen and (min-width: $small-breakpoint) {
grid-template-columns: 33% 67%;
}
.cta {
margin: 0;
.column-2 {
grid-column: 2;
grid-row: 1;
}
}
.button {
margin-right: 4px;
}
}
}
.brand {
text-align: unset;
padding: 0;
.features-list {
margin-left: 30px;
margin-right: 10px;
}
}
img {
height: 48px;
width: auto;
}
}
@media screen and (max-width: 675px) {
.features {
padding: 10px 0;
.cta {
margin: 0;
.container-alt {
display: flex;
flex-direction: column;
#mastodon-timeline {
order: 2;
flex: 0 0 auto;
height: 60vh;
margin-bottom: 20px;
border-top-right-radius: 4px;
}
.button {
margin-right: 4px;
}
}
.about-mastodon {
order: 1;
flex: 0 0 auto;
max-width: 100%;
@media screen and (max-width: $column-breakpoint) {
.grid {
.column-1 {
grid-column: 1;
grid-row: 2;
}
.about-hashtag {
background: unset;
padding: 0;
border-radius: 0;
.column-2 {
grid-column: 1;
grid-row: 1;
}
}
.cta {
margin: 20px 0;
}
}
.brand {
margin: 0;
}
.features-list {
display: none;
}
}
}
.landing-page__features {
display: none;
}
}
}

+ 9
- 0
app/javascript/mastodon/actions/reports.js View File

@ -10,6 +10,7 @@ export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE';
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE';
export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE';
export function initReport(account, status) {
return dispatch => {
@ -45,6 +46,7 @@ export function submitReport() {
account_id: getState().getIn(['reports', 'new', 'account_id']),
status_ids: getState().getIn(['reports', 'new', 'status_ids']),
comment: getState().getIn(['reports', 'new', 'comment']),
forward: getState().getIn(['reports', 'new', 'forward']),
}).then(response => {
dispatch(closeModal());
dispatch(submitReportSuccess(response.data));
@ -78,3 +80,10 @@ export function changeReportComment(comment) {
comment,
};
};
export function changeReportForward(forward) {
return {
type: REPORT_FORWARD_CHANGE,
forward,
};
};

+ 2
- 2
app/javascript/mastodon/actions/timelines.js View File

@ -120,7 +120,7 @@ export function refreshTimeline(timelineId, path, params = {}) {
export const refreshHomeTimeline = () => refreshTimeline('home', '/api/v1/timelines/home');
export const refreshPublicTimeline = () => refreshTimeline('public', '/api/v1/timelines/public');
export const refreshCommunityTimeline = () => refreshTimeline('community', '/api/v1/timelines/public', { local: true });
export const refreshAccountTimeline = accountId => refreshTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
export const refreshAccountTimeline = (accountId, withReplies) => refreshTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies });
export const refreshAccountMediaTimeline = accountId => refreshTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
export const refreshHashtagTimeline = hashtag => refreshTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
export const refreshListTimeline = id => refreshTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`);
@ -161,7 +161,7 @@ export function expandTimeline(timelineId, path, params = {}) {
export const expandHomeTimeline = () => expandTimeline('home', '/api/v1/timelines/home');
export const expandPublicTimeline = () => expandTimeline('public', '/api/v1/timelines/public');
export const expandCommunityTimeline = () => expandTimeline('community', '/api/v1/timelines/public', { local: true });
export const expandAccountTimeline = accountId => expandTimeline(`account:${accountId}`, `/api/v1/accounts/${accountId}/statuses`);
export const expandAccountTimeline = (accountId, withReplies) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies });
export const expandAccountMediaTimeline = accountId => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { only_media: true });
export const expandHashtagTimeline = hashtag => expandTimeline(`hashtag:${hashtag}`, `/api/v1/timelines/tag/${hashtag}`);
export const expandListTimeline = id => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`);

+ 3
- 2
app/javascript/mastodon/components/media_gallery.js View File

@ -283,8 +283,9 @@ export default class MediaGallery extends React.PureComponent {
if (width) {
style.height = width / this.props.media.getIn([0, 'meta', 'small', 'aspect']);
}
} else if (width) {
style.height = width / (16/9);
} else {
// crop the image
style.height = height;
}
@ -309,7 +310,7 @@ export default class MediaGallery extends React.PureComponent {
if (this.isStandaloneEligible()) {
children = <Item standalone onClick={this.handleClick} attachment={media.get(0)} />;
} else {
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} containerWidth={width} containerHeight={height} />);
children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} onClick={this.handleClick} attachment={attachment} index={i} size={size} containerWidth={width} containerHeight={style.height} />);
}
}

+ 1
- 0
app/javascript/mastodon/components/status.js View File

@ -184,6 +184,7 @@ export default class Status extends ImmutablePureComponent {
src={video.get('url')}
width={239}
height={110}
inline
sensitive={status.get('sensitive')}
onOpenVideo={this.handleOpenVideo}
/>

+ 2
- 2
app/javascript/mastodon/features/account/components/action_bar.js View File

@ -53,11 +53,11 @@ export default class ActionBar extends React.PureComponent {
let extraInfo = '';
menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention });
if ('share' in navigator) {
menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare });
}
menu.push(null);
menu.push({ text: intl.formatMessage(messages.media), to: `/accounts/${account.get('id')}/media` });
menu.push(null);
if (account.get('id') === me) {

+ 9
- 7
app/javascript/mastodon/features/account_gallery/components/media_item.js View File

@ -12,24 +12,26 @@ export default class MediaItem extends ImmutablePureComponent {
render () {
const { media } = this.props;
const status = media.get('status');
const focusX = media.getIn(['meta', 'focus', 'x']);
const focusY = media.getIn(['meta', 'focus', 'y']);
const x = ((focusX / 2) + .5) * 100;
const y = ((focusY / -2) + .5) * 100;
const style = {};
let content, style;
let content;
if (media.get('type') === 'gifv') {
content = <span className='media-gallery__gifv__label'>GIF</span>;
}
if (!status.get('sensitive')) {
style = { backgroundImage: `url(${media.get('preview_url')})` };
style.backgroundImage = `url(${media.get('preview_url')})`;
style.backgroundPosition = `${x}% ${y}%`;
}
return (
<div className='account-gallery__item'>
<Permalink
to={`/statuses/${status.get('id')}`}
href={status.get('url')}
style={style}
>
<Permalink to={`/statuses/${status.get('id')}`} href={status.get('url')} style={style}>
{content}
</Permalink>
</div>

+ 0
- 5
app/javascript/mastodon/features/account_gallery/index.js View File

@ -11,7 +11,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { getAccountGallery } from '../../selectors';
import MediaItem from './components/media_item';
import HeaderContainer from '../account_timeline/containers/header_container';
import { FormattedMessage } from 'react-intl';
import { ScrollContainer } from 'react-router-scroll-4';
import LoadMore from '../../components/load_more';
@ -89,10 +88,6 @@ export default class AccountGallery extends ImmutablePureComponent {
<div className='scrollable' onScroll={this.handleScroll}>
<HeaderContainer accountId={this.props.params.accountId} />
<div className='account-section-headline'>
<FormattedMessage id='account.media' defaultMessage='Media' />
</div>
<div className='account-gallery__container'>
{medias.map(media => (
<MediaItem

+ 8
- 0
app/javascript/mastodon/features/account_timeline/components/header.js View File

@ -6,6 +6,8 @@ import ActionBar from '../../account/components/action_bar';
import MissingIndicator from '../../../components/missing_indicator';
import ImmutablePureComponent from 'react-immutable-pure-component';
import MovedNote from './moved_note';
import { FormattedMessage } from 'react-intl';
import { NavLink } from 'react-router-dom';
export default class Header extends ImmutablePureComponent {
@ -91,6 +93,12 @@ export default class Header extends ImmutablePureComponent {
onBlockDomain={this.handleBlockDomain}
onUnblockDomain={this.handleUnblockDomain}
/>
<div className='account__section-headline'>
<NavLink exact to={`/accounts/${account.get('id')}`}><FormattedMessage id='account.posts' defaultMessage='Toots' /></NavLink>
<NavLink exact to={`/accounts/${account.get('id')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Toots with replies' /></NavLink>
<NavLink exact to={`/accounts/${account.get('id')}/media`}><FormattedMessage id='account.media' defaultMessage='Media' /></NavLink>
</div>
</div>
);
}

+ 14
- 9
app/javascript/mastodon/features/account_timeline/index.js View File

@ -12,11 +12,15 @@ import ColumnBackButton from '../../components/column_back_button';
import { List as ImmutableList } from 'immutable';
import ImmutablePureComponent from 'react-immutable-pure-component';
const mapStateToProps = (state, props) => ({
statusIds: state.getIn(['timelines', `account:${props.params.accountId}`, 'items'], ImmutableList()),
isLoading: state.getIn(['timelines', `account:${props.params.accountId}`, 'isLoading']),
hasMore: !!state.getIn(['timelines', `account:${props.params.accountId}`, 'next']),
});
const mapStateToProps = (state, { params: { accountId }, withReplies = false }) => {
const path = withReplies ? `${accountId}:with_replies` : accountId;
return {
statusIds: state.getIn(['timelines', `account:${path}`, 'items'], ImmutableList()),
isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']),
hasMore: !!state.getIn(['timelines', `account:${path}`, 'next']),
};
};
@connect(mapStateToProps)
export default class AccountTimeline extends ImmutablePureComponent {
@ -27,23 +31,24 @@ export default class AccountTimeline extends ImmutablePureComponent {
statusIds: ImmutablePropTypes.list,
isLoading: PropTypes.bool,
hasMore: PropTypes.bool,
withReplies: PropTypes.bool,
};
componentWillMount () {
this.props.dispatch(fetchAccount(this.props.params.accountId));
this.props.dispatch(refreshAccountTimeline(this.props.params.accountId));
this.props.dispatch(refreshAccountTimeline(this.props.params.accountId, this.props.withReplies));
}
componentWillReceiveProps (nextProps) {
if (nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) {
if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
this.props.dispatch(fetchAccount(nextProps.params.accountId));
this.props.dispatch(refreshAccountTimeline(nextProps.params.accountId));
this.props.dispatch(refreshAccountTimeline(nextProps.params.accountId, nextProps.params.withReplies));
}
}
handleScrollToBottom = () => {
if (!this.props.isLoading && this.props.hasMore) {
this.props.dispatch(expandAccountTimeline(this.props.params.accountId));
this.props.dispatch(expandAccountTimeline(this.props.params.accountId, this.props.withReplies));
}
}

+ 3
- 2
app/javascript/mastodon/features/compose/components/search.js View File

@ -4,6 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import Overlay from 'react-overlays/lib/Overlay';
import Motion from '../../ui/util/optional_motion';
import spring from 'react-motion/lib/spring';
import { searchEnabled } from '../../../initial_state';
const messages = defineMessages({
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
@ -17,7 +18,7 @@ class SearchPopout extends React.PureComponent {
render () {
const { style } = this.props;
const extraInformation = searchEnabled ? <FormattedMessage id='search_popout.tips.full_text' defaultMessage='Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.' /> : <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />;
return (
<div style={{ ...style, position: 'absolute', width: 285 }}>
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
@ -32,7 +33,7 @@ class SearchPopout extends React.PureComponent {
<li><em>URL</em> <FormattedMessage id='search_popout.tips.status' defaultMessage='status' /></li>
</ul>
<FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />
{extraInformation}
</div>
)}
</Motion>

+ 1
- 0
app/javascript/mastodon/features/status/components/detailed_status.js View File

@ -57,6 +57,7 @@ export default class DetailedStatus extends ImmutablePureComponent {
src={video.get('url')}
width={300}
height={150}
inline
onOpenVideo={this.handleOpenVideo}
sensitive={status.get('sensitive')}
/>

+ 5
- 6
app/javascript/mastodon/features/ui/components/bundle.js View File

@ -26,7 +26,7 @@ class Bundle extends React.Component {
onFetchFail: noop,
}
static cache = {}
static cache = new Map
state = {
mod: undefined,
@ -51,13 +51,12 @@ class Bundle extends React.Component {
load = (props) => {
const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props;
const cachedMod = Bundle.cache.get(fetchComponent);
onFetch();
if (Bundle.cache[fetchComponent.name]) {
const mod = Bundle.cache[fetchComponent.name];
this.setState({ mod: mod.default });
if (cachedMod) {
this.setState({ mod: cachedMod.default });
onFetchSuccess();
return Promise.resolve();
}
@ -71,7 +70,7 @@ class Bundle extends React.Component {
return fetchComponent()
.then((mod) => {
Bundle.cache[fetchComponent.name] = mod;
Bundle.cache.set(fetchComponent, mod);
this.setState({ mod: mod.default });
onFetchSuccess();
})

+ 13
- 4
app/javascript/mastodon/features/ui/components/columns_area.js View File

@ -6,6 +6,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import ReactSwipeableViews from 'react-swipeable-views';
import { links, getIndex, getLink } from './tabs_bar';
import { Link } from 'react-router-dom';
import BundleContainer from '../containers/bundle_container';
import ColumnLoading from './column_loading';
@ -152,11 +153,19 @@ export default class ColumnsArea extends ImmutablePureComponent {
this.pendingIndex = null;
if (singleColumn) {
return columnIndex !== -1 ? (
<ReactSwipeableViews index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}>
const floatingActionButton = this.context.router.history.location.pathname === '/statuses/new' ? null : <Link key='floating-action-button' to='/statuses/new' className='floating-action-button'><i className='fa fa-pencil' /></Link>;
return columnIndex !== -1 ? [
<ReactSwipeableViews key='content' index={columnIndex} onChangeIndex={this.handleSwipe} onTransitionEnd={this.handleAnimationEnd} animateTransitions={shouldAnimate} springConfig={{ duration: '400ms', delay: '0s', easeFunction: 'ease' }} style={{ height: '100%' }}>
{links.map(this.renderView)}
</ReactSwipeableViews>
) : <div className='columns-area'>{children}</div>;
</ReactSwipeableViews>,
floatingActionButton,
] : [
<div className='columns-area'>{children}</div>,
floatingActionButton,
];
}
return (

+ 35
- 12
app/javascript/mastodon/features/ui/components/report_modal.js View File

@ -1,6 +1,6 @@
import React from 'react';
import { connect } from 'react-redux';
import { changeReportComment, submitReport } from '../../../actions/reports';
import { changeReportComment, changeReportForward, submitReport } from '../../../actions/reports';
import { refreshAccountTimeline } from '../../../actions/timelines';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
@ -10,8 +10,11 @@ import StatusCheckBox from '../../report/containers/status_check_box_container';
import { OrderedSet } from 'immutable';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Button from '../../../components/button';
import Toggle from 'react-toggle';
import IconButton from '../../../components/icon_button';
const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' },
submit: { id: 'report.submit', defaultMessage: 'Submit' },
});
@ -26,6 +29,7 @@ const makeMapStateToProps = () => {
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
account: getAccount(state, accountId),
comment: state.getIn(['reports', 'new', 'comment']),
forward: state.getIn(['reports', 'new', 'forward']),
statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])),
};
};
@ -42,14 +46,19 @@ export default class ReportModal extends ImmutablePureComponent {
account: ImmutablePropTypes.map,
statusIds: ImmutablePropTypes.orderedSet.isRequired,
comment: PropTypes.string.isRequired,
forward: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
handleCommentChange = (e) => {
handleCommentChange = e => {
this.props.dispatch(changeReportComment(e.target.value));
}
handleForwardChange = e => {
this.props.dispatch(changeReportForward(e.target.checked));
}
handleSubmit = () => {
this.props.dispatch(submitReport());
}
@ -65,26 +74,25 @@ export default class ReportModal extends ImmutablePureComponent {
}
render () {
const { account, comment, intl, statusIds, isSubmitting } = this.props;
const { account, comment, intl, statusIds, isSubmitting, forward, onClose } = this.props;
if (!account) {
return null;
}
const domain = account.get('acct').split('@')[1];
return (
<div className='modal-root__modal report-modal'>
<div className='report-modal__target'>
<IconButton className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={16} />
<FormattedMessage id='report.target' defaultMessage='Report {target}' values={{ target: <strong>{account.get('acct')}</strong> }} />
</div>
<div className='report-modal__container'>
<div className='report-modal__statuses'>
<div>
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
</div>
</div>
<div className='report-modal__comment'>
<p><FormattedMessage id='report.hint' defaultMessage='The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:' /></p>
<textarea
className='setting-text light'
placeholder={intl.formatMessage(messages.placeholder)}
@ -92,11 +100,26 @@ export default class ReportModal extends ImmutablePureComponent {
onChange={this.handleCommentChange}
disabled={isSubmitting}
/>
{domain && (
<div>
<p><FormattedMessage id='report.forward_hint' defaultMessage='The account is from another server. Send an anonymized copy of the report there as well?' /></p>
<div className='setting-toggle'>
<Toggle id='report-forward' checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} />
<label htmlFor='report-forward' className='setting-toggle__label'><FormattedMessage id='report.forward' defaultMessage='Forward to {target}' values={{ target: domain }} /></label>
</div>
</div>
)}
<Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} />
</div>
</div>
<div className='report-modal__action-bar'>
<Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} />
<div className='report-modal__statuses'>
<div>
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
</div>
</div>
</div>
</div>
);

+ 1
- 2
app/javascript/mastodon/features/ui/components/tabs_bar.js View File

@ -6,14 +6,13 @@ import { debounce } from 'lodash';
import { isUserTouching } from '../../../is_mobile';
export const links = [
<NavLink className='tabs-bar__link primary' to='/statuses/new' data-preview-title-id='tabs_bar.compose' data-preview-icon='pencil' ><i className='fa fa-fw fa-pencil' /><FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></NavLink>,
<NavLink className='tabs-bar__link primary' to='/timelines/home' data-preview-title-id='column.home' data-preview-icon='home' ><i className='fa fa-fw fa-home' /><FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></NavLink>,
<NavLink className='tabs-bar__link primary' to='/notifications' data-preview-title-id='column.notifications' data-preview-icon='bell' ><i className='fa fa-fw fa-bell' /><FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></NavLink>,
<NavLink className='tabs-bar__link secondary' to='/timelines/public/local' data-preview-title-id='column.community' data-preview-icon='users' ><i className='fa fa-fw fa-users' /><FormattedMessage id='tabs_bar.local_timeline' defaultMessage='Local' /></NavLink>,
<NavLink className='tabs-bar__link secondary' exact to='/timelines/public' data-preview-title-id='column.public' data-preview-icon='globe' ><i className='fa fa-fw fa-globe' /><FormattedMessage id='tabs_bar.federated_timeline' defaultMessage='Federated' /></NavLink>,
<NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='asterisk' ><i className='fa fa-fw fa-asterisk' /></NavLink>,
<NavLink className='tabs-bar__link primary' style={{ flexGrow: '0', flexBasis: '30px' }} to='/getting-started' data-preview-title-id='getting_started.heading' data-preview-icon='bars' ><i className='fa fa-fw fa-bars' /></NavLink>,
];
export function getIndex (path) {

+ 1
- 0
app/javascript/mastodon/features/ui/index.js View File

@ -398,6 +398,7 @@ export default class UI extends React.Component {
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
<WrappedRoute path='/accounts/:accountId' exact component={AccountTimeline} content={children} />
<WrappedRoute path='/accounts/:accountId/with_replies' component={AccountTimeline} content={children} componentParams={{ withReplies: true }} />
<WrappedRoute path='/accounts/:accountId/followers' component={Followers} content={children} />
<WrappedRoute path='/accounts/:accountId/following' component={Following} content={children} />
<WrappedRoute path='/accounts/:accountId/media' component={AccountGallery} content={children} />

+ 8
- 3
app/javascript/mastodon/features/ui/util/react_router_helpers.js View File

@ -35,14 +35,19 @@ export class WrappedRoute extends React.Component {
component: PropTypes.func.isRequired,
content: PropTypes.node,
multiColumn: PropTypes.bool,
}
componentParams: PropTypes.object,
};
static defaultProps = {
componentParams: {},
};
renderComponent = ({ match }) => {
const { component, content, multiColumn } = this.props;
const { component, content, multiColumn, componentParams } = this.props;
return (
<BundleContainer fetchComponent={component} loading={this.renderLoading} error={this.renderError}>
{Component => <Component params={match.params} multiColumn={multiColumn}>{content}</Component>}
{Component => <Component params={match.params} multiColumn={multiColumn} {...componentParams}>{content}</Component>}
</BundleContainer>
);
}

+ 22
- 3
app/javascript/mastodon/features/video/index.js View File

@ -97,6 +97,7 @@ export default class Video extends React.PureComponent {
onOpenVideo: PropTypes.func,
onCloseVideo: PropTypes.func,
detailed: PropTypes.bool,
inline: PropTypes.bool,
intl: PropTypes.object.isRequired,
};
@ -105,6 +106,7 @@ export default class Video extends React.PureComponent {
duration: 0,
paused: true,
dragging: false,
containerWidth: false,
fullscreen: false,
hovered: false,
muted: false,
@ -113,6 +115,12 @@ export default class Video extends React.PureComponent {
setPlayerRef = c => {
this.player = c;
if (c) {
this.setState({
containerWidth: c.offsetWidth,
});
}
}
setVideoRef = c => {
@ -246,12 +254,23 @@ export default class Video extends React.PureComponent {
}
render () {
const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
const { currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
const playerStyle = {};
let { width, height } = this.props;
if (inline && containerWidth) {
width = containerWidth;
height = containerWidth / (16/9);
playerStyle.width = width;
playerStyle.height = height;
}
return (
<div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<div className={classNames('video-player', { inactive: !revealed, detailed, inline: inline && !fullscreen, fullscreen })} style={playerStyle} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<video
ref={this.setVideoRef}
src={src}

+ 1
- 0
app/javascript/mastodon/initial_state.js View File

@ -10,5 +10,6 @@ export const unfollowModal = getMeta('unfollow_modal');
export const boostModal = getMeta('boost_modal');
export const deleteModal = getMeta('delete_modal');
export const me = getMeta('me');
export const searchEnabled = getMeta('search_enabled');
export default initialState;

+ 10
- 2
app/javascript/mastodon/locales/ar.json View File

@ -13,7 +13,8 @@
"account.moved_to": "{name} إنتقل إلى :",
"account.mute": "أكتم @{name}",
"account.mute_notifications": "كتم إخطارات @{name}",
"account.posts": "المشاركات",
"account.posts": "التبويقات",
"account.posts_with_replies": "Toots with replies",
"account.report": "أبلغ عن @{name}",
"account.requested": "في انتظار الموافقة",
"account.share": "مشاركة @{name}'s profile",
@ -50,7 +51,7 @@
"column_header.unpin": "فك التدبيس",
"column_subheading.navigation": "التصفح",
"column_subheading.settings": "الإعدادات",
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"compose_form.hashtag_warning": "هذا التبويق لن يُدرَج تحت أي وسم كان بما أنه غير مُدرَج. لا يُسمح بالبحث إلّا عن التبويقات العمومية عن طريق الوسوم.",
"compose_form.lock_disclaimer": "حسابك ليس {locked}. يمكن لأي شخص متابعتك و عرض المنشورات.",
"compose_form.lock_disclaimer.lock": "مقفل",
"compose_form.placeholder": "فيمَ تفكّر؟",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "إلغاء",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "تعليقات إضافية",
"report.submit": "إرسال",
"report.target": "إبلاغ",
@ -216,6 +220,9 @@
"search_popout.tips.status": "حالة",
"search_popout.tips.text": "جملة قصيرة تُمكّنُك من عرض أسماء و حسابات و كلمات رمزية",
"search_popout.tips.user": "مستخدِم",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} و {results}}",
"standalone.public_title": "نظرة على ...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "إسحب ثم أفلت للرفع",
"upload_button.label": "إضافة وسائط",
"upload_form.description": "وصف للمعاقين بصريا",
"upload_form.focus": "Crop",
"upload_form.undo": "إلغاء",
"upload_progress.label": "يرفع...",
"video.close": "إغلاق الفيديو",

+ 8
- 0
app/javascript/mastodon/locales/bg.json View File

@ -14,6 +14,7 @@
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Публикации",
"account.posts_with_replies": "Toots with replies",
"account.report": "Report @{name}",
"account.requested": "В очакване на одобрение",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Отказ",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.submit": "Submit",
"report.target": "Reporting",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Добави медия",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Отмяна",
"upload_progress.label": "Uploading...",
"video.close": "Close video",

+ 42
- 34
app/javascript/mastodon/locales/ca.json View File

@ -1,29 +1,30 @@
{
"account.block": "Bloquejar @{name}",
"account.block_domain": "Amagar tot de {domain}",
"account.block": "Bloca @{name}",
"account.block_domain": "Amaga-ho tot de {domain}",
"account.disclaimer_full": "La informació següent pot reflectir incompleta el perfil de l'usuari.",
"account.edit_profile": "Editar perfil",
"account.follow": "Seguir",
"account.edit_profile": "Edita el perfil",
"account.follow": "Segueix",
"account.followers": "Seguidors",
"account.follows": "Seguint",
"account.follows_you": "et segueix",
"account.follows_you": "Et segueix",
"account.hide_reblogs": "Amaga els impulsos de @{name}",
"account.media": "Media",
"account.mention": "Esmentar @{name}",
"account.moved_to": "{name} s'ha mogut a:",
"account.mute": "Silenciar @{name}",
"account.mute": "Silencia @{name}",
"account.mute_notifications": "Notificacions desactivades de @{name}",
"account.posts": "Publicacions",
"account.posts": "Toots",
"account.posts_with_replies": "Toots with replies",
"account.report": "Informe @{name}",
"account.requested": "Esperant aprovació. Clic per a cancel·lar la petició de seguiment",
"account.share": "Compartir el perfil de @{name}",
"account.share": "Comparteix el perfil de @{name}",
"account.show_reblogs": "Mostra els impulsos de @{name}",
"account.unblock": "Desbloquejar @{name}",
"account.unblock": "Desbloca @{name}",
"account.unblock_domain": "Mostra {domain}",
"account.unfollow": "Deixar de seguir",
"account.unfollow": "Deixa de seguir",
"account.unmute": "Treure silenci de @{name}",
"account.unmute_notifications": "Activar notificacions de @{name}",
"account.view_full_profile": "Veure el perfil complet",
"account.view_full_profile": "Mostra el perfil complet",
"boost_modal.combo": "Pots premer {combo} per saltar-te això el proper cop",
"bundle_column_error.body": "S'ha produït un error en carregar aquest component.",
"bundle_column_error.retry": "Torna-ho a provar",
@ -31,7 +32,7 @@
"bundle_modal_error.close": "Tanca",
"bundle_modal_error.message": "S'ha produït un error en carregar aquest component.",
"bundle_modal_error.retry": "Torna-ho a provar",
"column.blocks": "Usuaris bloquejats",
"column.blocks": "Usuaris blocats",
"column.community": "Línia de temps local",
"column.favourites": "Favorits",
"column.follow_requests": "Peticions per seguir-te",
@ -45,46 +46,46 @@
"column_header.hide_settings": "Amaga la configuració",
"column_header.moveLeft_settings": "Mou la columna cap a l'esquerra",
"column_header.moveRight_settings": "Mou la columna cap a la dreta",
"column_header.pin": "Fixar",
"column_header.pin": "Fixa",
"column_header.show_settings": "Mostra la configuració",
"column_header.unpin": "Deslligar",
"column_header.unpin": "No fixis",
"column_subheading.navigation": "Navegació",
"column_subheading.settings": "Configuració",
"compose_form.hashtag_warning": "Aquest toot no es mostrarà en cap etiqueta ja que no està llistat. Només els toots públics poden ser cercats per etiqueta.",
"compose_form.lock_disclaimer": "El teu compte no està bloquejat {locked}. Tothom pot seguir-te i veure els teus missatges a seguidors.",
"compose_form.lock_disclaimer.lock": "bloquejat",
"compose_form.lock_disclaimer.lock": "blocat",
"compose_form.placeholder": "En què estàs pensant?",
"compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive": "Marcar multimèdia com a sensible",
"compose_form.spoiler": "Amagar text darrera l'advertència",
"compose_form.spoiler_placeholder": "Escriu l'advertència aquí",
"confirmation_modal.cancel": "Cancel·lar",
"confirmations.block.confirm": "Bloquejar",
"confirmations.block.message": "Estàs segur que vols bloquejar {name}?",
"confirmations.delete.confirm": "Esborrar",
"confirmations.delete.message": "Estàs segur que vols esborrar aquest estat?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Estàs segur que vols esborrar permanenment aquesta llista?",
"confirmations.domain_block.confirm": "Amagar tot el domini",
"confirmations.domain_block.message": "Estàs realment, realment segur que vols bloquejar totalment {domain}? En la majoria dels casos bloquejar o silenciar és suficient i preferible.",
"confirmations.mute.confirm": "Silenciar",
"compose_form.sensitive": "Marca el contingut multimèdia com a sensible",
"compose_form.spoiler": "Amaga el text darrera darrere un avís",
"compose_form.spoiler_placeholder": "Escriu l'avís aquí",
"confirmation_modal.cancel": "Cancel·la",
"confirmations.block.confirm": "Bloca",
"confirmations.block.message": "Estàs segur que vols blocar {name}?",
"confirmations.delete.confirm": "Suprimeix",
"confirmations.delete.message": "Estàs segur que vols suprimir aquest estat?",
"confirmations.delete_list.confirm": "Suprimeix",
"confirmations.delete_list.message": "Estàs segur que vols suprimir permanentment aquesta llista?",
"confirmations.domain_block.confirm": "Amaga tot el domini",
"confirmations.domain_block.message": "Estàs realment, realment segur que vols blocar totalment {domain}? En la majoria dels casos blocar o silenciar uns pocs objectius és suficient i preferible.",
"confirmations.mute.confirm": "Silencia",
"confirmations.mute.message": "Estàs segur que vols silenciar {name}?",
"confirmations.unfollow.confirm": "Deixar de seguir",
"confirmations.unfollow.confirm": "Deixa de seguir",
"confirmations.unfollow.message": "Estàs segur que vols deixar de seguir {name}?",
"embed.instructions": "Incrusta aquest estat al lloc web copiant el codi a continuació.",
"embed.preview": "Aquí tenim quin aspecte tindrá:",
"emoji_button.activity": "Activitat",
"emoji_button.custom": "Personalitzat",
"emoji_button.flags": "Marques",
"emoji_button.food": "Menjar i Beure",
"emoji_button.label": "Inserir emoji",
"emoji_button.flags": "Banderes",
"emoji_button.food": "Menjar i beure",
"emoji_button.label": "Insereix un emoji",
"emoji_button.nature": "Natura",
"emoji_button.not_found": "Emojos no!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objectes",
"emoji_button.people": "Gent",
"emoji_button.recent": "Freqüentment utilitzat",
"emoji_button.search": "Cercar...",
"emoji_button.recent": "Usats freqüentment",
"emoji_button.search": "Cerca...",
"emoji_button.search_results": "Resultats de la cerca",
"emoji_button.symbols": "Símbols",
"emoji_button.travel": "Viatges i Llocs",
@ -207,6 +208,9 @@
"relative_time.minutes": "fa {number} minuts",
"relative_time.seconds": "fa {number} segons",
"reply_indicator.cancel": "Cancel·lar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentaris addicionals",
"report.submit": "Enviar",
"report.target": "Informes",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "El text simple retorna coincidències amb els noms de visualització, els noms d'usuari i els hashtags",
"search_popout.tips.user": "usuari",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, un {result} altres {results}}",
"standalone.public_title": "Una mirada a l'interior ...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Arrossega i deixa anar per carregar",
"upload_button.label": "Afegir multimèdia",
"upload_form.description": "Descriure els problemes visuals",
"upload_form.focus": "Crop",
"upload_form.undo": "Desfer",
"upload_progress.label": "Pujant...",
"video.close": "Tancar el vídeo",

+ 8
- 0
app/javascript/mastodon/locales/de.json View File

@ -14,6 +14,7 @@
"account.mute": "@{name} stummschalten",
"account.mute_notifications": "Benachrichtigungen von @{name} verbergen",
"account.posts": "Beiträge",
"account.posts_with_replies": "Toots with replies",
"account.report": "@{name} melden",
"account.requested": "Warte auf Erlaubnis. Klicke zum Abbrechen",
"account.share": "Profil von @{name} teilen",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Abbrechen",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Zusätzliche Kommentare",
"report.submit": "Absenden",
"report.target": "{target} melden",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {Ergebnis} other {Ergebnisse}}",
"standalone.public_title": "Ein kleiner Einblick …",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Zum Hochladen hereinziehen",
"upload_button.label": "Mediendatei hinzufügen",
"upload_form.description": "Für Menschen mit Sehbehinderung beschreiben",
"upload_form.focus": "Crop",
"upload_form.undo": "Entfernen",
"upload_progress.label": "Wird hochgeladen …",
"video.close": "Video schließen",

+ 40
- 4
app/javascript/mastodon/locales/defaultMessages.json View File

@ -317,12 +317,20 @@
},
{
"descriptors": [
{
"defaultMessage": "Toots",
"id": "account.posts"
},
{
"defaultMessage": "Toots with replies",
"id": "account.posts_with_replies"
},
{
"defaultMessage": "Media",
"id": "account.media"
}
],
"path": "app/javascript/mastodon/features/account_gallery/index.json"
"path": "app/javascript/mastodon/features/account_timeline/components/header.json"
},
{
"descriptors": [
@ -650,6 +658,18 @@
},
{
"descriptors": [
{
"defaultMessage": "People",
"id": "search_results.accounts"
},
{
"defaultMessage": "Toots",
"id": "search_results.statuses"
},
{
"defaultMessage": "Hashtags",
"id": "search_results.hashtags"
},
{
"defaultMessage": "{count, number} {count, plural, one {result} other {results}}",
"id": "search_results.total"
@ -706,13 +726,17 @@
},
{
"descriptors": [
{
"defaultMessage": "Describe for the visually impaired",
"id": "upload_form.description"
},
{
"defaultMessage": "Undo",
"id": "upload_form.undo"
},
{
"defaultMessage": "Describe for the visually impaired",
"id": "upload_form.description"
"defaultMessage": "Crop",
"id": "upload_form.focus"
}
],
"path": "app/javascript/mastodon/features/compose/components/upload.json"
@ -1576,6 +1600,18 @@
{
"defaultMessage": "Report {target}",
"id": "report.target"
},
{
"defaultMessage": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"id": "report.hint"
},
{
"defaultMessage": "The account is from another server. Send an anonymized copy of the report there as well?",
"id": "report.forward_hint"
},
{
"defaultMessage": "Forward to {target}",
"id": "report.forward"
}
],
"path": "app/javascript/mastodon/features/ui/components/report_modal.json"
@ -1672,4 +1708,4 @@
],
"path": "app/javascript/mastodon/features/video/index.json"
}
]
]

+ 8
- 0
app/javascript/mastodon/locales/en.json View File

@ -14,6 +14,7 @@
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Toots",
"account.posts_with_replies": "Toots with replies",
"account.report": "Report @{name}",
"account.requested": "Awaiting approval. Click to cancel follow request",
"account.share": "Share @{name}'s profile",
@ -214,6 +215,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancel",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.submit": "Submit",
"report.target": "Reporting {target}",
@ -223,6 +227,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -259,6 +266,7 @@
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Undo",
"upload_progress.label": "Uploading...",
"video.close": "Close video",

+ 147
- 139
app/javascript/mastodon/locales/eo.json View File

@ -1,236 +1,243 @@
{
"account.block": "Bloki @{name}",
"account.block_domain": "Kaŝi ĉion el {domain}",
"account.disclaimer_full": "La ĉi-subaj informoj povas ne plene reflekti la profilon de la uzanto.",
"account.edit_profile": "Redakti la profilon",
"account.block_domain": "Kaŝi ĉion de {domain}",
"account.disclaimer_full": "Subaj informoj povas reflekti la profilon de la uzanto nekomplete.",
"account.edit_profile": "Redakti profilon",
"account.follow": "Sekvi",
"account.followers": "Sekvantoj",
"account.follows": "Sekvatoj",
"account.follows_you": "Sekvas vin",
"account.hide_reblogs": "Maski diskonigitaĵojn de @{name}",
"account.media": "Sonbildaĵoj",
"account.hide_reblogs": "Kaŝi diskonigojn de @{name}",
"account.media": "Aŭdovidaĵoj",
"account.mention": "Mencii @{name}",
"account.moved_to": "{name} movis al:",
"account.moved_to": "{name} moviĝis al:",
"account.mute": "Silentigi @{name}",
"account.mute_notifications": "Silentigi sciigojn el @{name}",
"account.posts": "Mesaĝoj",
"account.posts": "Hupoj",
"account.posts_with_replies": "Toots with replies",
"account.report": "Signali @{name}",
"account.requested": "Atendas aprobon",
"account.requested": "Atendo de aprobo. Alklaku por nuligi peton de sekvado",
"account.share": "Diskonigi la profilon de @{name}",
"account.show_reblogs": "Montri diskonigojn de @{name}",
"account.show_reblogs": "Montri diskonigojn de @{name}",
"account.unblock": "Malbloki @{name}",
"account.unblock_domain": "Malkaŝi {domain}",
"account.unfollow": "Ne plus sekvi",
"account.unfollow": "Ne plu sekvi",
"account.unmute": "Malsilentigi @{name}",
"account.unmute_notifications": "Malsilentigi sciigojn de @{name}",
"account.view_full_profile": "Vidi plenan profilon",
"boost_modal.combo": "La proksiman fojon, premu {combo} por pasigi",
"bundle_column_error.body": "Io malfunkciis ŝargante tiun ĉi komponanton.",
"boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje",
"bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.",
"bundle_column_error.retry": "Bonvolu reprovi",
"bundle_column_error.title": "Reta eraro",
"bundle_modal_error.close": "Fermi",
"bundle_modal_error.message": "Io malfunkciis ŝargante tiun ĉi komponanton.",
"bundle_modal_error.message": "Io misfunkciis en la ŝargado de ĉi tiu elemento.",
"bundle_modal_error.retry": "Bonvolu reprovi",
"column.blocks": "Blokitaj uzantoj",
"column.community": "Loka tempolinio",
"column.favourites": "Favoritoj",
"column.follow_requests": "Abonpetoj",
"column.favourites": "Stelumoj",
"column.follow_requests": "Petoj de sekvado",
"column.home": "Hejmo",
"column.lists": "Listoj",
"column.mutes": "Silentigitaj uzantoj",
"column.notifications": "Sciigoj",
"column.pins": "Alpinglitaj pepoj",
"column.pins": "Alpinglitaj mesaĝoj",
"column.public": "Fratara tempolinio",
"column_back_button.label": "Reveni",
"column_header.hide_settings": "Kaŝi agordojn",
"column_header.moveLeft_settings": "Movi kolumnon maldekstren",
"column_header.moveRight_settings": "Movi kolumnon dekstren",
"column_header.pin": "Alpingli",
"column_header.show_settings": "Malkaŝi agordojn",
"column_header.show_settings": "Montri agordojn",
"column_header.unpin": "Depingli",
"column_subheading.navigation": "Navigado",
"column_subheading.settings": "Agordoj",
"compose_form.hashtag_warning": "Ĉi tiu pepo ne estos listigita en iu ajn kradvorta listo pro ĝia videbleco estas “eksterlista”. Nur publikaj pepoj povas esti kradvorte trovitaj.",
"compose_form.lock_disclaimer": "Via konta ne estas ŝlosita. Iu ajn povas sekvi vin por vidi viajn privatajn pepojn.",
"compose_form.hashtag_warning": "Ĉi tiu mesaĝo ne estos listigita per ajna kradvorto. Nur publikaj mesaĝoj estas serĉeblaj per kradvortoj.",
"compose_form.lock_disclaimer": "Via konta ne estas {locked}. Iu ajn povas sekvi vin por vidi viajn mesaĝojn nur por sekvantoj.",
"compose_form.lock_disclaimer.lock": "ŝlosita",
"compose_form.placeholder": "Pri kio vi pensas?",
"compose_form.publish": "Hup",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive": "Marki ke la enhavo estas tikla",
"compose_form.spoiler": "Kaŝi la tekston malantaŭ averto",
"compose_form.spoiler_placeholder": "Skribu tie vian averton",
"confirmation_modal.cancel": "Malfari",
"compose_form.sensitive": "Marki aŭdovidaĵon tikla",
"compose_form.spoiler": "Kaŝi tekston malantaŭ averto",
"compose_form.spoiler_placeholder": "Skribu vian averton ĉi tie",
"confirmation_modal.cancel": "Nuligi",
"confirmations.block.confirm": "Bloki",
"confirmations.block.message": "Ĉu vi konfirmas la blokadon de {name}?",
"confirmations.delete.confirm": "Malaperigi",
"confirmations.delete.message": "Ĉu vi konfirmas la malaperigon de tiun pepon?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Ĉu vi certas forviŝi ĉi tiun liston por ĉiam?",
"confirmations.domain_block.confirm": "Kaŝi la tutan reton",
"confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas bloki {domain} tute? Plej ofte, kelkaj celitaj blokadoj aŭ silentigoj estas sufiĉaj kaj preferindaj.",
"confirmations.block.message": "Ĉu vi certas, ke vi volas bloki {name}?",
"confirmations.delete.confirm": "Forigi",
"confirmations.delete.message": "Ĉu vi certas, ke vi volas forigi ĉi tiun mesaĝon?",
"confirmations.delete_list.confirm": "Forigi",
"confirmations.delete_list.message": "Ĉu vi certas, ke vi volas porĉiame forigi ĉi tiun liston?",
"confirmations.domain_block.confirm": "Kaŝi la tutan domajnon",
"confirmations.domain_block.message": "Ĉu vi vere, vere certas, ke vi volas tute bloki {domain}? Plej ofte, trafa blokado kaj silentigado sufiĉas kaj preferindas.",
"confirmations.mute.confirm": "Silentigi",
"confirmations.mute.message": "Ĉu vi konfirmas la silentigon de {name}?",
"confirmations.mute.message": "Ĉu vi certas, ke vi volas silentigi {name}?",
"confirmations.unfollow.confirm": "Ne plu sekvi",
"confirmations.unfollow.message": "Ĉu vi volas ĉesi sekvi {name}?",
"embed.instructions": "Enmetu tiun statkonigon ĉe vian retejon kopiante la ĉi-suban kodon.",
"confirmations.unfollow.message": "Ĉu vi certas, ke vi volas ĉesi sekvi {name}?",
"embed.instructions": "Enkorpigu ĉi tiun mesaĝon en vian retejon per kopio de la suba kodo.",
"embed.preview": "Ĝi aperos tiel:",
"emoji_button.activity": "Aktivecoj",
"emoji_button.custom": "Personaj",
"emoji_button.activity": "Agadoj",
"emoji_button.custom": "Propraj",
"emoji_button.flags": "Flagoj",
"emoji_button.food": "Manĝi kaj trinki",
"emoji_button.label": "Enmeti mieneton",
"emoji_button.label": "Enmeti emion",
"emoji_button.nature": "Naturo",
"emoji_button.not_found": "Neniuj mienetoj!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objektoj",
"emoji_button.not_found": "Neniu emio!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "oj",
"emoji_button.people": "Homoj",
"emoji_button.recent": "Ofte uzataj",
"emoji_button.search": "Serĉo…",
"emoji_button.search_results": "Rezultatoj de serĉo",
"emoji_button.search_results": "Serĉaj rezultoj",
"emoji_button.symbols": "Simboloj",
"emoji_button.travel": "Vojaĝoj & lokoj",
"emoji_button.travel": "Vojaĝoj kaj lokoj",
"empty_column.community": "La loka tempolinio estas malplena. Skribu ion por plenigi ĝin!",
"empty_column.hashtag": "Ĝise, neniu enhavo estas asociita kun tiu kradvorto.",
"empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.",
"empty_column.home": "Via hejma tempolinio estas malplena! Vizitu {public} aŭ uzu la serĉilon por renkonti aliajn uzantojn.",
"empty_column.home.public_timeline": "la publika tempolinio",
"empty_column.list": "Estas ankoraŭ nenio en ĉi tiu listo. Tuj kiam anoj de ĉi tiu listo publikigos, ties pepoj aperos ĉi tie.",
"empty_column.notifications": "Vi dume ne havas sciigojn. Interagi kun aliajn uzantojn por komenci la konversacion.",
"empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj instancoj por plenigi la publikan tempolinion",
"follow_request.authorize": "Akcepti",
"empty_column.list": "Ankoraŭ estas nenio en ĉi tiu listo. Kiam membroj de ĉi tiu listo afiŝos novajn mesaĝojn, ili aperos ĉi tie.",
"empty_column.notifications": "Vi ankoraŭ ne havas sciigojn. Interagu kun aliaj por komenci konversacion.",
"empty_column.public": "Estas nenio ĉi tie! Publike skribu ion, aŭ mane sekvu uzantojn de aliaj nodoj por plenigi la publikan tempolinion",
"follow_request.authorize": "Rajtigi",
"follow_request.reject": "Rifuzi",
"getting_started.appsshort": "Aplikaĵoj",
"getting_started.faq": "Oftaj demandoj",
"getting_started.heading": "Por komenci",
"getting_started.open_source_notice": "Mastodono estas malfermkoda programo. Vi povas kontribui aŭ raporti problemojn en GitHub je {github}.",
"getting_started.open_source_notice": "Mastodon estas malfermitkoda programo. Vi povas kontribui aŭ raporti problemojn en GitHub je {github}.",
"getting_started.userguide": "Gvidilo de uzo",
"home.column_settings.advanced": "Precizaj agordoj",
"home.column_settings.basic": "Bazaj agordoj",
"home.column_settings.filter_regex": "Forfiltri per regulesprimo",
"home.column_settings.filter_regex": "Filtri per regulesprimoj",
"home.column_settings.show_reblogs": "Montri diskonigojn",
"home.column_settings.show_replies": "Montri respondojn",
"home.settings": "Agordoj de la kolumno",
"keyboard_shortcuts.back": "reeniri",
"keyboard_shortcuts.boost": "diskonigi",
"keyboard_shortcuts.column": "fokusigi statuson en unu el la columnoj",
"keyboard_shortcuts.compose": "por fokusigi la redaktujon",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.down": "subenmovi en la listo",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "ŝatitaren",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"home.settings": "Kolumnaj agordoj",
"keyboard_shortcuts.back": "por reveni",
"keyboard_shortcuts.boost": "por diskonigi",
"keyboard_shortcuts.column": "por fokusigi mesaĝon en unu el la kolumnoj",
"keyboard_shortcuts.compose": "por fokusigi la tekstujon",
"keyboard_shortcuts.description": "Priskribo",
"keyboard_shortcuts.down": "por iri suben en la listo",
"keyboard_shortcuts.enter": "por malfermi mesaĝon",
"keyboard_shortcuts.favourite": "por stelumi",
"keyboard_shortcuts.heading": "Klavaraj mallongigoj",
"keyboard_shortcuts.hotkey": "Rapidklavo",
"keyboard_shortcuts.legend": "por montri ĉi tiun legendon",
"keyboard_shortcuts.mention": "por sciigi ties aŭtoron",
"keyboard_shortcuts.legend": "por montri ĉi tiun noton",
"keyboard_shortcuts.mention": "por mencii la aŭtoron",
"keyboard_shortcuts.reply": "por respondi",
"keyboard_shortcuts.search": "por fokusigi la serĉadon",
"keyboard_shortcuts.toot": "por ekredakti tute novan pepon",
"keyboard_shortcuts.unfocus": "por malfokusigi la redaktujon aŭ la serĉilon",
"keyboard_shortcuts.up": "por suprenmovi en la listo",
"keyboard_shortcuts.search": "por fokusigi la serĉilon",
"keyboard_shortcuts.toot": "por komenci tute novan mesaĝon",
"keyboard_shortcuts.unfocus": "por malfokusigi la tekstujon aŭ la serĉilon",
"keyboard_shortcuts.up": "por iri supren en la listo",
"lightbox.close": "Fermi",
"lightbox.next": "Malantaŭa",
"lightbox.next": "Sekva",
"lightbox.previous": "Antaŭa",
"lists.account.add": "Aldoni al la listo",
"lists.account.remove": "Forviŝi de la listo",
"lists.delete": "Delete list",
"lists.account.remove": "Forigi de la listo",
"lists.delete": "Forigi la liston",
"lists.edit": "Redakti la liston",
"lists.new.create": "Aldoni liston",
"lists.new.title_placeholder": "Titulo de la nova listo",
"lists.search": "Serĉi el la homoj kiujn vi sekvas",
"lists.new.title_placeholder": "Titolo de la nova listo",
"lists.search": "Serĉi inter la homoj, kiujn vi sekvas",
"lists.subheading": "Viaj listoj",
"loading_indicator.label": "Ŝarganta…",
"media_gallery.toggle_visible": "Baskuli videblecon",
"loading_indicator.label": "Ŝargado…",
"media_gallery.toggle_visible": "Baskuligi videblecon",
"missing_indicator.label": "Ne trovita",
"missing_indicator.sublabel": "Ĉi tiu rimedo ne troviĝis",
"mute_modal.hide_notifications": "Ĉu kaŝi sciigojn el tiu ĉi uzanto?",
"missing_indicator.sublabel": "Ĉi tiu rimedo ne estis trovita",
"mute_modal.hide_notifications": "Ĉu kaŝi sciigojn el ĉi tiu uzanto?",
"navigation_bar.blocks": "Blokitaj uzantoj",
"navigation_bar.community_timeline": "Loka tempolinio",
"navigation_bar.edit_profile": "Redakti la profilon",
"navigation_bar.favourites": "Favoritaj",
"navigation_bar.follow_requests": "Abonpetoj",
"navigation_bar.info": "Plia informo",
"navigation_bar.keyboard_shortcuts": "Klavmallongigo",
"navigation_bar.edit_profile": "Redakti profilon",
"navigation_bar.favourites": "Stelumoj",
"navigation_bar.follow_requests": "Petoj de sekvado",
"navigation_bar.info": "Pri ĉiu tiu nodo",
"navigation_bar.keyboard_shortcuts": "Klavaraj mallongigoj",
"navigation_bar.lists": "Listoj",
"navigation_bar.logout": "Elsaluti",
"navigation_bar.mutes": "Silentigitaj uzantoj",
"navigation_bar.pins": "Alpinglitaj pepoj",
"navigation_bar.pins": "Alpinglitaj mesaĝoj",
"navigation_bar.preferences": "Preferoj",
"navigation_bar.public_timeline": "Fratara tempolinio",
"notification.favourite": "{name} favoris vian mesaĝon",
"notification.follow": "{name} sekvis vin",
"notification.favourite": "{name} stelumis vian mesaĝon",
"notification.follow": "{name} eksekvis vin",
"notification.mention": "{name} menciis vin",
"notification.reblog": "{name} diskonigis vian mesaĝon",
"notifications.clear": "Forviŝi la sciigojn",
"notifications.clear_confirmation": "Ĉu vi certe volas malaperigi ĉiujn viajn sciigojn?",
"notifications.column_settings.alert": "Retumilaj atentigoj",
"notifications.column_settings.favourite": "Favoritoj:",
"notifications.clear": "Forviŝi sciigojn",
"notifications.clear_confirmation": "Ĉu vi certas, ke vi volas porĉiame forviŝi ĉiujn viajn sciigojn?",
"notifications.column_settings.alert": "Retumilaj sciigoj",
"notifications.column_settings.favourite": "Stelumoj:",
"notifications.column_settings.follow": "Novaj sekvantoj:",
"notifications.column_settings.mention": "Mencioj:",
"notifications.column_settings.push": "Puŝsciigoj",
"notifications.column_settings.push_meta": "Tiu ĉi aparato",
"notifications.column_settings.push_meta": "Ĉi tiu aparato",
"notifications.column_settings.reblog": "Diskonigoj:",
"notifications.column_settings.show": "Montri en kolono",
"notifications.column_settings.show": "Montri en kolumno",
"notifications.column_settings.sound": "Eligi sonon",
"onboarding.done": "Farita",
"onboarding.next": "Malantaŭa",
"onboarding.page_five.public_timelines": "La loka tempolinio enhavas mesaĝojn de ĉiuj ĉe {domain}. La federacia tempolinio enhavas ĉiujn mesaĝojn de uzantoj, kiujn iu ĉe {domain} sekvas. Ambaŭ tre utilas por trovi novajn kunparolantojn.",
"onboarding.page_four.home": "La hejma tempolinio enhavas la mesaĝojn de ĉiuj uzantoj, kiuj vi sekvas.",
"onboarding.page_four.notifications": "La sciiga kolumno informas vin kiam iu interagas kun vi.",
"onboarding.page_one.federation": "Mastodono estas reto de nedependaj serviloj, unuiĝintaj por krei pligrandan socian retejon. Ni nomas tiujn servilojn instancoj.",
"onboarding.page_one.full_handle": "Via tuta uzantnomo",
"onboarding.page_one.handle_hint": "Jen kion vi dirintus al viaj amikoj por serĉi.",
"onboarding.page_one.welcome": "Bonvenon al Mastodono!",
"onboarding.page_six.admin": "Via instancestro estas {admin}.",
"onboarding.page_six.almost_done": "Estas preskaŭ finita…",
"onboarding.page_six.appetoot": "Bonan a‘pepi’ton!",
"onboarding.page_six.apps_available": "{apps} estas elŝuteblaj por iOS, Androido kaj alioj.",
"onboarding.page_six.github": "Mastodono estas libera, senpaga kaj malfermkoda programaro. Vi povas signali cimojn, proponi funkciojn aŭ kontribui al gîa kreskado ĉe {github}.",
"onboarding.page_six.guidelines": "komunreguloj",
"onboarding.page_six.read_guidelines": "Ni petas vin: ne forgesu legi la {guidelines}n de {domain}!",
"onboarding.page_six.various_app": "telefon-aplikaĵoj",
"onboarding.page_three.profile": "Redaktu vian profilon por ŝanĝi vian avataron, priskribon kaj vian nomon. Vi tie trovos ankoraŭ aliajn agordojn.",
"onboarding.page_three.search": "Uzu la serĉokampo por trovi uzantojn kaj esplori kradvortojn tiel ke {illustration} kaj {introductions}. Por trovi iun, kiu ne estas ĉe ĉi tiu instanco, uzu ĝian kompletan uznomon.",
"onboarding.page_two.compose": "Skribu pepojn en la verkkolumno. Vi povas aldoni bildojn, ŝanĝi la agordojn de privateco kaj aldoni tiklavertojn (« content warning ») dank' al la piktogramoj malsupre.",
"onboarding.skip": "Pasigi",
"privacy.change": "Alĝustigi la privateco de la mesaĝo",
"privacy.direct.long": "Vidigi nur al la menciitaj personoj",
"onboarding.next": "Sekva",
"onboarding.page_five.public_timelines": "La loka tempolinio montras publikajn mesaĝojn de ĉiuj en {domain}. La fratara tempolinio montras publikajn mesaĝojn de ĉiuj, kiuj estas sekvataj de homoj en {domain}. Tio estas la publikaj tempolinioj, kio estas bona maniero por malkovri novajn homojn.",
"onboarding.page_four.home": "La hejma tempolinio montras mesaĝojn de ĉiuj uzantoj, kiujn vi sekvas.",
"onboarding.page_four.notifications": "La sciiga kolumno montras kiam iu interagas kun vi.",
"onboarding.page_one.federation": "Mastodon estas reto de sendependaj serviloj, unuiĝintaj por krei pligrandan socian reton. Ni nomas tiujn servilojn nodoj.",
"onboarding.page_one.full_handle": "Via kompleta uzantnomo",
"onboarding.page_one.handle_hint": "Jen kion vi petus al viaj amikoj serĉi.",
"onboarding.page_one.welcome": "Bonvenon en Mastodon!",
"onboarding.page_six.admin": "Via noda administranto estas {admin}.",
"onboarding.page_six.almost_done": "Preskaŭ finita…",
"onboarding.page_six.appetoot": "Saĝan mesaĝadon!",
"onboarding.page_six.apps_available": "{apps} estas disponeblaj por iOS, Android kaj aliaj platformoj.",
"onboarding.page_six.github": "Mastodon estas libera, senpaga kaj malfermitkoda programo. Vi povas raporti cimojn, proponi funkciojn aŭ kontribui al la kodo en {github}.",
"onboarding.page_six.guidelines": "komunumaj gvidlinioj",
"onboarding.page_six.read_guidelines": "Bonvolu atenti pri la {guidelines} de {domain}!",
"onboarding.page_six.various_app": "telefonaj aplikaĵoj",
"onboarding.page_three.profile": "Redaktu vian profilon por ŝanĝi vian profilbildon, priskribon kaj nomon. Vi ankaŭ trovos tie aliajn agordojn.",
"onboarding.page_three.search": "Uzu la serĉilon por trovi uzantojn kaj esplori kradvortojn, tiel {illustration} kaj {introductions}. Por trovi iun, kiu ne estas en ĉi tiu nodo, uzu ties kompletan uzantnomon.",
"onboarding.page_two.compose": "Skribu mesaĝojn en la skriba kolumno. Vi povas alŝuti bildojn, ŝanĝi privatecajn agordojn, kaj aldoni avertojn pri la enhavo per la subaj bildetoj.",
"onboarding.skip": "Preterpasi",
"privacy.change": "Agordi mesaĝan privatecon",
"privacy.direct.long": "Afiŝi nur al menciitaj uzantoj",
"privacy.direct.short": "Rekta",
"privacy.private.long": "Vidigi nur al viaj sekvantoj",
"privacy.private.short": "Nursekvanta",
"privacy.public.long": "Vidigi en publikaj tempolinioj",
"privacy.private.long": "Afiŝi nur al sekvantoj",
"privacy.private.short": "Nur por sekvantoj",
"privacy.public.long": "Afiŝi en publikaj tempolinioj",
"privacy.public.short": "Publika",
"privacy.unlisted.long": "Ne vidigi en publikaj tempolinioj",
"privacy.unlisted.long": "Ne afiŝi en publikaj tempolinioj",
"privacy.unlisted.short": "Nelistigita",
"regeneration_indicator.label": "Elŝultanta…",
"regeneration_indicator.sublabel": "Via ĉefpaĝo estas preparanta!",
"regeneration_indicator.label": "Ŝargado…",
"regeneration_indicator.sublabel": "Via hejma fluo pretiĝas!",
"relative_time.days": "{number}t",
"relative_time.hours": "{number}h",
"relative_time.just_now": "nun",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Malfari",
"reply_indicator.cancel": "Nuligi",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Pliaj komentoj",
"report.submit": "Sendi",
"report.target": "Signalaĵo",
"report.target": "Signali {target}",
"search.placeholder": "Serĉi",
"search_popout.search_format": "Detala serĉo",
"search_popout.tips.hashtag": "kradvorto",
"search_popout.tips.status": "statkonigo",
"search_popout.tips.text": "Simpla teksto eligas la kongruajn afiŝnomojn, uznomojn kaj kradvortojn",
"search_popout.tips.status": "mesaĝoj",
"search_popout.tips.text": "Simpla teksto montras la kongruajn afiŝitajn nomojn, uzantnomojn kaj kradvortojn",
"search_popout.tips.user": "uzanto",
"search_results.total": "{count, number} {count, plural, one {rezultato} other {rezultatoj}}",
"standalone.public_title": "Rigardeti…",
"status.block": "Block @{name}",
"status.cannot_reblog": "Tiun publikaĵon oni ne povas diskonigi",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {rezulto} other {rezultoj}}",
"standalone.public_title": "Enrigardo…",
"status.block": "Bloki @{name}",
"status.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas",
"status.delete": "Forigi",
"status.embed": "Enmeti",
"status.favourite": "Favori",
"status.load_more": "Ŝargi plie",
"status.media_hidden": "Sonbildaĵo kaŝita",
"status.embed": "Enkorpigi",
"status.favourite": "Stelumi",
"status.load_more": "Ŝargi pli",
"status.media_hidden": "Aŭdovidaĵo kaŝita",
"status.mention": "Mencii @{name}",
"status.more": "Pli",
"status.mute": "Silentigi @{name}",
"status.mute_conversation": "Silentigi konversacion",
"status.open": "Disfaldi statkonigon",
"status.pin": "Pingli al la profilo",
"status.open": "Grandigi ĉi tiun mesaĝon",
"status.pin": "Alpingli en la profilo",
"status.reblog": "Diskonigi",
"status.reblogged_by": "{name} diskonigis",
"status.reply": "Respondi",
@ -239,28 +246,29 @@
"status.sensitive_toggle": "Alklaki por vidi",
"status.sensitive_warning": "Tikla enhavo",
"status.share": "Diskonigi",
"status.show_less": "Refaldi",
"status.show_more": "Disfaldi",
"status.show_less": "Malgrandigi",
"status.show_more": "Grandigi",
"status.unmute_conversation": "Malsilentigi konversacion",
"status.unpin": "Depingli de profilo",
"tabs_bar.compose": "Ekskribi",
"tabs_bar.federated_timeline": "Federacia tempolinio",
"tabs_bar.federated_timeline": "Fratara tempolinio",
"tabs_bar.home": "Hejmo",
"tabs_bar.local_timeline": "Loka tempolinio",
"tabs_bar.notifications": "Sciigoj",
"ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.",
"upload_area.title": "Algliti por alŝuti",
"upload_button.label": "Aldoni sonbildaĵon",
"upload_form.description": "Priskribi por la misvidantaj",
"upload_area.title": "Altreni kaj lasi por alŝuti",
"upload_button.label": "Aldoni aŭdovidaĵon",
"upload_form.description": "Priskribi por misvidantaj homoj",
"upload_form.focus": "Crop",
"upload_form.undo": "Malfari",
"upload_progress.label": "Alŝutanta…",
"upload_progress.label": "Alŝutado…",
"video.close": "Fermi videon",
"video.exit_fullscreen": "Eliri el plenekrano",
"video.expand": "Vastigi videon",
"video.fullscreen": "Igi plenekrane",
"video.exit_fullscreen": "Eksigi plenekrana",
"video.expand": "Grandigi videon",
"video.fullscreen": "Igi plenekrana",
"video.hide": "Kaŝi videon",
"video.mute": "Silentigi",
"video.pause": "Paŭzi",
"video.play": "Legi",
"video.play": "Ekigi",
"video.unmute": "Malsilentigi"
}

+ 8
- 0
app/javascript/mastodon/locales/es.json View File

@ -14,6 +14,7 @@
"account.mute": "Silenciar a @{name}",
"account.mute_notifications": "Silenciar notificaciones de @{name}",
"account.posts": "Publicaciones",
"account.posts_with_replies": "Toots with replies",
"account.report": "Reportar a @{name}",
"account.requested": "Esperando aprobación",
"account.share": "Compartir el perfil de @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancelar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentarios adicionales",
"report.submit": "Publicar",
"report.target": "Reportando",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "El texto simple devuelve correspondencias de nombre, usuario y hashtag",
"search_popout.tips.user": "usuario",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Un pequeño vistazo...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Arrastra y suelta para subir",
"upload_button.label": "Subir multimedia",
"upload_form.description": "Describir para los usuarios con dificultad visual",
"upload_form.focus": "Crop",
"upload_form.undo": "Deshacer",
"upload_progress.label": "Subiendo…",
"video.close": "Cerrar video",

+ 8
- 0
app/javascript/mastodon/locales/fa.json View File

@ -14,6 +14,7 @@
"account.mute": "بی‌صدا کردن @{name}",
"account.mute_notifications": "بی‌صداکردن اعلان‌ها از طرف @{name}",
"account.posts": "نوشته‌ها",
"account.posts_with_replies": "Toots with replies",
"account.report": "گزارش @{name}",
"account.requested": "در انتظار پذیرش",
"account.share": "هم‌رسانی نمایهٔ @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "لغو",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "توضیح اضافه",
"report.submit": "بفرست",
"report.target": "گزارش‌دادن",
@ -216,6 +220,9 @@
"search_popout.tips.status": "نوشته",
"search_popout.tips.text": "جستجوی متنی ساده برای نام‌ها، نام‌های کاربری، و هشتگ‌ها",
"search_popout.tips.user": "کاربر",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {نتیجه} other {نتیجه}}",
"standalone.public_title": "نگاهی به کاربران این سرور...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "برای بارگذاری به این‌جا بکشید",
"upload_button.label": "افزودن تصویر",
"upload_form.description": "نوشتهٔ توضیحی برای کم‌بینایان و نابینایان",
"upload_form.focus": "Crop",
"upload_form.undo": "واگردانی",
"upload_progress.label": "بارگذاری...",
"video.close": "بستن ویدیو",

+ 196
- 188
app/javascript/mastodon/locales/fi.json View File

@ -1,266 +1,274 @@
{
"account.block": "Estä @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}",
"account.disclaimer_full": "Alla olevat käyttäjän profiilitiedot saattavat olla epätäydellisiä.",
"account.edit_profile": "Muokkaa",
"account.follow": "Seuraa",
"account.followers": "Seuraajia",
"account.follows": "Seuraa",
"account.follows_you": "Seuraa sinua",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.hide_reblogs": "Piilota buustaukset käyttäjältä @{name}",
"account.media": "Media",
"account.mention": "Mainitse @{name}",
"account.moved_to": "{name} has moved to:",
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Postit",
"account.moved_to": "{name} on muuttanut instanssiin:",
"account.mute": "Mykistä @{name}",
"account.mute_notifications": "Mykistä ilmoitukset käyttäjältä @{name}",
"account.posts": "Töötit",
"account.posts_with_replies": "Toots with replies",
"account.report": "Report @{name}",
"account.requested": "Odottaa hyväksyntää",
"account.share": "Share @{name}'s profile",
"account.show_reblogs": "Show boosts from @{name}",
"account.requested": "Odottaa hyväksyntää. Klikkaa peruuttaaksesi seurauspyynnön",
"account.share": "Jaa käyttäjän @{name} profiili",
"account.show_reblogs": "Näytä boostaukset käyttäjältä @{name}",
"account.unblock": "Salli @{name}",
"account.unblock_domain": "Unhide {domain}",
"account.unfollow": "Lopeta seuraaminen",
"account.unmute": "Unmute @{name}",
"account.unmute_notifications": "Unmute notifications from @{name}",
"account.view_full_profile": "View full profile",
"boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.",
"bundle_column_error.retry": "Try again",
"account.unblock_domain": "Näytä {domain}",
"account.unfollow": "Lakkaa seuraamasta",
"account.unmute": "Poista mykistys käyttäjältä @{name}",
"account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta",
"account.view_full_profile": "Näytä koko profiili",
"boost_modal.combo": "Voit painaa näppäimiä {combo} ohittaaksesi tämän ensi kerralla",
"bundle_column_error.body": "Jokin meni vikaan tätä komponenttia ladatessa.",
"bundle_column_error.retry": "Yritä uudestaan",
"bundle_column_error.title": "Network error",
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"bundle_modal_error.close": "Sulje",
"bundle_modal_error.message": "Jokin meni vikaan tätä komponenttia ladatessa.",
"bundle_modal_error.retry": "Yritä uudestaan",
"column.blocks": "Estetyt käyttäjät",
"column.community": "Paikallinen aikajana",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
"column.favourites": "Suosikit",
"column.follow_requests": "Seurauspyynnöt",
"column.home": "Koti",
"column.lists": "Lists",
"column.mutes": "Muted users",
"column.lists": "Listat",
"column.mutes": "Mykistetyt käyttäjät",
"column.notifications": "Ilmoitukset",
"column.pins": "Pinned toot",
"column.public": "Yleinen aikajana",
"column_back_button.label": "Takaisin",
"column_header.hide_settings": "Hide settings",
"column_header.moveLeft_settings": "Move column to the left",
"column_header.moveRight_settings": "Move column to the right",
"column_header.pin": "Pin",
"column_header.show_settings": "Show settings",
"column_header.unpin": "Unpin",
"column_subheading.navigation": "Navigation",
"column_subheading.settings": "Settings",
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
"column_header.hide_settings": "Piilota asetukset",
"column_header.moveLeft_settings": "Siirrä saraketta vasemmalle",
"column_header.moveRight_settings": "Siirrä saraketta oikealle",
"column_header.pin": "Kiinnitä",
"column_header.show_settings": "Näytä asetukset",
"column_header.unpin": "Poista kiinnitys",
"column_subheading.navigation": "Navigaatio",
"column_subheading.settings": "Asetukset",
"compose_form.hashtag_warning": "Tämä töötti ei tule näkymään hashtag-hauissa, koska se ei näy julkisilla aikajanoilla. Vain julkisia tööttejä voi hakea hashtageilla.",
"compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille -postauksesi.",
"compose_form.lock_disclaimer.lock": "lukittu",
"compose_form.placeholder": "Mitä sinulla on mielessä?",
"compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive": "Merkitse media herkäksi",
"compose_form.spoiler": "Piiloita teksti varoituksen taakse",
"compose_form.spoiler_placeholder": "Content warning",
"confirmation_modal.cancel": "Cancel",
"confirmations.block.confirm": "Block",
"confirmations.block.message": "Are you sure you want to block {name}?",
"confirmation_modal.cancel": "Peruuta",
"confirmations.block.confirm": "Estä",
"confirmations.block.message": "Oletko varma, että haluat estää käyttäjän {name}?",
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete.message": "Oletko varma, että haluat poistaa tämän statuspäivityksen?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Here is what it will look like:",
"emoji_button.activity": "Activity",
"emoji_button.custom": "Custom",
"emoji_button.flags": "Flags",
"emoji_button.food": "Food & Drink",
"emoji_button.label": "Insert emoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objects",
"emoji_button.people": "People",
"emoji_button.recent": "Frequently used",
"emoji_button.search": "Search...",
"emoji_button.search_results": "Search results",
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.",
"empty_column.home.public_timeline": "the public timeline",
"empty_column.list": "There is nothing in this list yet.",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
"follow_request.authorize": "Authorize",
"follow_request.reject": "Reject",
"getting_started.appsshort": "Apps",
"confirmations.delete_list.message": "Oletko varma, että haluat poistaa tämän listan pysyvästi?",
"confirmations.domain_block.confirm": "Piilota koko verkko-osoite",
"confirmations.domain_block.message": "Oletko aivan oikeasti varma että haluat estää koko verkko-osoitteen {domain}? Useimmissa tapauksissa muutamat kohdistetut estot ja mykistykset ovat riittäviä ja suositeltavampia.",
"confirmations.mute.confirm": "Mykistä",
"confirmations.mute.message": "Oletko varma että haluat mykistää käyttäjän {name}?",
"confirmations.unfollow.confirm": "Lakkaa seuraamasta",
"confirmations.unfollow.message": "Oletko varma, että haluat lakata seuraamasta käyttäjää {name}?",
"embed.instructions": "Upota tämä statuspäivitys sivullesi kopioimalla alla oleva koodi.",
"embed.preview": "Tältä se tulee näyttämään:",
"emoji_button.activity": "Aktiviteetit",
"emoji_button.custom": "Mukautetut",
"emoji_button.flags": "Liput",
"emoji_button.food": "Ruoka ja juoma",
"emoji_button.label": "Lisää emoji",
"emoji_button.nature": "Luonto",
"emoji_button.not_found": "Ei emojeja!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objektit",
"emoji_button.people": "Ihmiset",
"emoji_button.recent": "Usein käytetyt",
"emoji_button.search": "Etsi...",
"emoji_button.search_results": "Hakutulokset",
"emoji_button.symbols": "Symbolit",
"emoji_button.travel": "Matkailu",
"empty_column.community": "Paikallinen aikajana on tyhjä. Kirjoita jotain julkista saadaksesi pyörät pyörimään!",
"empty_column.hashtag": "Tässä hashtagissa ei ole vielä mitään.",
"empty_column.home": "Kotiaikajanasi on tyhjä! Käy vierailemassa {public}ssa tai käytä hakutoimintoa aloittaaksesi ja tavataksesi muita käyttäjiä.",
"empty_column.home.public_timeline": "yleinen aikajana",
"empty_column.list": "Tämä lista on vielä tyhjä. Kun listan jäsenet julkaisevat statuspäivityksiä, ne näkyvät tässä.",
"empty_column.notifications": "Sinulle ei ole vielä ilmoituksia. Juttele muille aloittaaksesi keskustelun.",
"empty_column.public": "Täällä ei ole mitään! Kirjoita jotain julkisesti, tai käy manuaalisesti seuraamassa käyttäjiä muista instansseista saadaksesi sisältöä",
"follow_request.authorize": "Valtuuta",
"follow_request.reject": "Hylkää",
"getting_started.appsshort": "Sovellukset",
"getting_started.faq": "FAQ",
"getting_started.heading": "Aloitus",
"getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}.",
"getting_started.userguide": "User Guide",
"home.column_settings.advanced": "Advanced",
"home.column_settings.basic": "Basic",
"home.column_settings.filter_regex": "Filter out by regular expressions",
"home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies",
"home.settings": "Column settings",
"keyboard_shortcuts.back": "to navigate back",
"keyboard_shortcuts.boost": "to boost",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"getting_started.open_source_notice": "Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}.",
"getting_started.userguide": "Käyttöopas",
"home.column_settings.advanced": "Tarkemmat asetukset",
"home.column_settings.basic": "Perusasetukset",
"home.column_settings.filter_regex": "Suodata säännöllisten lauseiden avulla",
"home.column_settings.show_reblogs": "Näytä buustaukset",
"home.column_settings.show_replies": "Näytä vastaukset",
"home.settings": "Sarakeasetukset",
"keyboard_shortcuts.back": "liikkuaksesi taaksepäin",
"keyboard_shortcuts.boost": "buustataksesi",
"keyboard_shortcuts.column": "keskittääksesi statuspäivitykseen yhdessä sarakkeista",
"keyboard_shortcuts.compose": "aktivoidaksesi tekstinkirjoitusalueen",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.down": "liikkuaksesi listassa alaspäin",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"keyboard_shortcuts.favourite": "tykätäksesi",
"keyboard_shortcuts.heading": "Näppäinoikotiet",
"keyboard_shortcuts.hotkey": "Pikanäppäin",
"keyboard_shortcuts.legend": "näyttääksesi tämän selitteen",
"keyboard_shortcuts.mention": "mainitaksesi julkaisijan",
"keyboard_shortcuts.reply": "vastataksesi",
"keyboard_shortcuts.search": "aktivoidaksesi hakukentän",
"keyboard_shortcuts.toot": "aloittaaksesi uuden töötin kirjoittamisen",
"keyboard_shortcuts.unfocus": "poistaaksesi aktivoinnin tekstikentästä/hakukentästä",
"keyboard_shortcuts.up": "liikkuaksesi listassa ylöspäin",
"lightbox.close": "Sulje",
"lightbox.next": "Next",
"lightbox.previous": "Previous",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lightbox.next": "Seuraava",
"lightbox.previous": "Edellinen",
"lists.account.add": "Lisää listaan",
"lists.account.remove": "Poista listalta",
"lists.delete": "Delete list",
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.subheading": "Your lists",
"lists.edit": "Muokkaa listaa",
"lists.new.create": "Lisää lista",
"lists.new.title_placeholder": "Uuden listan otsikko",
"lists.search": "Etsi seuraamiesi henkilöiden joukosta",
"lists.subheading": "Omat listat",
"loading_indicator.label": "Ladataan...",
"media_gallery.toggle_visible": "Toggle visibility",
"missing_indicator.label": "Not found",
"missing_indicator.sublabel": "This resource could not be found",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.blocks": "Blocked users",
"media_gallery.toggle_visible": "Säädä näkyvyyttä",
"missing_indicator.label": "Ei löydetty",
"missing_indicator.sublabel": "Tätä resurssia ei löytynyt",
"mute_modal.hide_notifications": "Piilota ilmoitukset tältä käyttäjältä?",
"navigation_bar.blocks": "Estetyt käyttäjät",
"navigation_bar.community_timeline": "Paikallinen aikajana",
"navigation_bar.edit_profile": "Muokkaa profiilia",
"navigation_bar.favourites": "Favourites",
"navigation_bar.follow_requests": "Follow requests",
"navigation_bar.info": "Extended information",
"navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
"navigation_bar.lists": "Lists",
"navigation_bar.favourites": "Suosikit",
"navigation_bar.follow_requests": "Seurauspyynnöt",
"navigation_bar.info": "Tietoa tästä instanssista",
"navigation_bar.keyboard_shortcuts": "Näppäinoikotiet",
"navigation_bar.lists": "Listat",
"navigation_bar.logout": "Kirjaudu ulos",
"navigation_bar.mutes": "Muted users",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.mutes": "Mykistetyt käyttäjät",
"navigation_bar.pins": "Kiinnitetyt töötit",
"navigation_bar.preferences": "Ominaisuudet",
"navigation_bar.public_timeline": "Yleinen aikajana",
"notification.favourite": "{name} tykkäsi statuksestasi",
"notification.follow": "{name} seurasi sinua",
"notification.mention": "{name} mainitsi sinut",
"notification.reblog": "{name} buustasi statustasi",
"notifications.clear": "Clear notifications",
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
"notifications.clear": "Tyhjennä ilmoitukset",
"notifications.clear_confirmation": "Oletko varma, että haluat lopullisesti tyhjentää kaikki ilmoituksesi?",
"notifications.column_settings.alert": "Työpöytä ilmoitukset",
"notifications.column_settings.favourite": "Tykkäyksiä:",
"notifications.column_settings.follow": "Uusia seuraajia:",
"notifications.column_settings.mention": "Mainintoja:",
"notifications.column_settings.push": "Push notifications",
"notifications.column_settings.push_meta": "This device",
"notifications.column_settings.push": "Push-ilmoitukset",
"notifications.column_settings.push_meta": "Tämä laite",
"notifications.column_settings.reblog": "Buusteja:",
"notifications.column_settings.show": "Näytä sarakkeessa",
"notifications.column_settings.sound": "Play sound",
"onboarding.done": "Done",
"onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
"onboarding.page_four.home": "The home timeline shows posts from people you follow.",
"onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
"onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
"onboarding.page_one.full_handle": "Your full handle",
"notifications.column_settings.sound": "Soita ääni",
"onboarding.done": "Valmis",
"onboarding.next": "Seuraava",
"onboarding.page_five.public_timelines": "Paikallinen aikajana näyttää kaikki julkiset julkaisut kaikilta, jotka ovat verkko-osoitteessa {domain}. Yleinen aikajana näyttää julkiset julkaisut kaikilta niiltä, joita käyttäjät verkko-osoitteessa {domain} seuraavat. Nämä ovat julkiset aikajanat, ja ne ovat hyviä tapoja löytää uusia ihmisiä.",
"onboarding.page_four.home": "Kotiaikajana näyttää julkaisut ihmisiltä joita seuraat.",
"onboarding.page_four.notifications": "Ilmoitukset-sarake näyttää sinulle, kun joku on viestii kanssasi.",
"onboarding.page_one.federation": "Mastodon on yhteisöpalvelu, joka toimii monen itsenäisen palvelimen muodostamassa verkossa. Me kutsumme näitä palvelimia instansseiksi.",
"onboarding.page_one.full_handle": "Koko käyttäjänimesi",
"onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
"onboarding.page_one.welcome": "Welcome to Mastodon!",
"onboarding.page_six.admin": "Your instance's admin is {admin}.",
"onboarding.page_six.almost_done": "Almost done...",
"onboarding.page_six.appetoot": "Bon Appetoot!",
"onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.",
"onboarding.page_one.welcome": "Tervetuloa Mastodoniin!",
"onboarding.page_six.admin": "Instanssisi ylläpitäjä on {admin}.",
"onboarding.page_six.almost_done": "Melkein valmista...",
"onboarding.page_six.appetoot": "Bon Appetööt!",
"onboarding.page_six.apps_available": "{apps} on saatavilla iOS:lle, Androidille ja muille alustoille.",
"onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
"onboarding.page_six.guidelines": "community guidelines",
"onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
"onboarding.page_six.various_app": "mobile apps",
"onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
"onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
"onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
"onboarding.skip": "Skip",
"privacy.change": "Adjust status privacy",
"privacy.direct.long": "Post to mentioned users only",
"privacy.direct.short": "Direct",
"privacy.private.long": "Post to followers only",
"privacy.private.short": "Followers-only",
"privacy.public.long": "Post to public timelines",
"privacy.public.short": "Public",
"privacy.unlisted.long": "Do not show in public timelines",
"privacy.unlisted.short": "Unlisted",
"regeneration_indicator.label": "Loading…",
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
"onboarding.page_six.guidelines": "yhteisön säännöt",
"onboarding.page_six.read_guidelines": "Ole hyvä ja lue {domain}:n {guidelines}!",
"onboarding.page_six.various_app": "mobiilisovellukset",
"onboarding.page_three.profile": "Muokkaa profiiliasi muuttaaksesi kuvakettasi, esittelyäsi ja nimimerkkiäsi. Löydät sieltä myös muita henkilökohtaisia asetuksia.",
"onboarding.page_three.search": "Käytä hakukenttää löytääksesi ihmisiä ja etsiäksesi hashtageja, kuten {illustration} tai {introductions}. Hakeaksesi henkilöä joka on toisessa instanssissa, käytä hänen käyttäjänimeään kokonaisuudessaan.",
"onboarding.page_two.compose": "Kirjoita postauksia kirjoita-sarakkeessa. Voit ladata kuvia, vaihtaa yksityisyysasetuksia ja lisätä sisältövaroituksia alla olevista painikkeista.",
"onboarding.skip": "Ohita",
"privacy.change": "Säädä töötin yksityisyysasetuksia",
"privacy.direct.long": "Julkaise vain mainituille käyttäjille",
"privacy.direct.short": "Yksityisviesti",
"privacy.private.long": "Julkaise vain seuraajille",
"privacy.private.short": "Vain seuraajat",
"privacy.public.long": "Julkaise julkisille aikajanoille",
"privacy.public.short": "Julkinen",
"privacy.unlisted.long": "Älä julkaise yleisillä aikajanoilla",
"privacy.unlisted.short": "Julkinen, mutta älä näytä julkisella aikajanalla",
"regeneration_indicator.label": "Ladataan…",
"regeneration_indicator.sublabel": "Kotinäkymääsi valmistellaan!",
"relative_time.days": "{number}d",
"relative_time.hours": "{number}h",
"relative_time.just_now": "now",
"relative_time.just_now": "nyt",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Peruuta",
"report.placeholder": "Additional comments",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Lisäkommentit",
"report.submit": "Submit",
"report.target": "Reporting",
"search.placeholder": "Hae",
"search_popout.search_format": "Advanced search format",
"search_popout.tips.hashtag": "hashtag",
"search_popout.search_format": "Tarkennettu haku",
"search_popout.tips.hashtag": "hashtagi",
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_popout.tips.text": "Pelkkä tekstihaku palauttaa hakua vastaavat nimimerkit, käyttäjänimet ja hastagit",
"search_popout.tips.user": "käyttäjä",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"standalone.public_title": "Kurkistus sisälle...",
"status.block": "Block @{name}",
"status.cannot_reblog": "This post cannot be boosted",
"status.cannot_reblog": "Tätä postausta ei voi buustata",
"status.delete": "Poista",
"status.embed": "Embed",
"status.embed": "Upota",
"status.favourite": "Tykkää",
"status.load_more": "Load more",
"status.media_hidden": "Media hidden",
"status.load_more": "Lataa lisää",
"status.media_hidden": "Media piilotettu",
"status.mention": "Mainitse @{name}",
"status.more": "More",
"status.mute": "Mute @{name}",
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this status",
"status.pin": "Pin on profile",
"status.more": "Lisää",
"status.mute": "Mykistä @{name}",
"status.mute_conversation": "Mykistä keskustelu",
"status.open": "Laajenna statuspäivitys",
"status.pin": "Kiinnitä profiiliin",
"status.reblog": "Buustaa",
"status.reblogged_by": "{name} buustasi",
"status.reply": "Vastaa",
"status.replyAll": "Reply to thread",
"status.replyAll": "Vastaa ketjuun",
"status.report": "Report @{name}",
"status.sensitive_toggle": "Klikkaa nähdäksesi",
"status.sensitive_warning": "Arkaluontoista sisältöä",
"status.share": "Share",
"status.show_less": "Show less",
"status.show_more": "Show more",
"status.unmute_conversation": "Unmute conversation",
"status.unpin": "Unpin from profile",
"status.share": "Jaa",
"status.show_less": "Näytä vähemmän",
"status.show_more": "Näytä lisää",
"status.unmute_conversation": "Poista mykistys keskustelulta",
"status.unpin": "Irrota profiilista",
"tabs_bar.compose": "Luo",
"tabs_bar.federated_timeline": "Federated",
"tabs_bar.home": "Koti",
"tabs_bar.local_timeline": "Local",
"tabs_bar.local_timeline": "Paikallinen",
"tabs_bar.notifications": "Ilmoitukset",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
"ui.beforeunload": "Luonnoksesi menetetään, jos poistut Mastodonista.",
"upload_area.title": "Raahaa ja pudota tähän ladataksesi",
"upload_button.label": "Lisää mediaa",
"upload_form.description": "Describe for the visually impaired",
"upload_form.description": "Anna kuvaus näkörajoitteisia varten",
"upload_form.focus": "Crop",
"upload_form.undo": "Peru",
"upload_progress.label": "Uploading...",
"video.close": "Close video",
"video.exit_fullscreen": "Exit full screen",
"video.expand": "Expand video",
"upload_progress.label": "Ladataan...",
"video.close": "Sulje video",
"video.exit_fullscreen": "Poistu koko näytön tilasta",
"video.expand": "Laajenna video",
"video.fullscreen": "Full screen",
"video.hide": "Hide video",
"video.mute": "Mute sound",
"video.pause": "Pause",
"video.play": "Play",
"video.unmute": "Unmute sound"
"video.hide": "Piilota video",
"video.mute": "Mykistä ääni",
"video.pause": "Keskeytä",
"video.play": "Toista",
"video.unmute": "Poista mykistys ääneltä"
}

+ 10
- 2
app/javascript/mastodon/locales/fr.json View File

@ -14,6 +14,7 @@
"account.mute": "Masquer @{name}",
"account.mute_notifications": "Ignorer les notifications de @{name}",
"account.posts": "Statuts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Signaler",
"account.requested": "Invitation envoyée",
"account.share": "Partager le profil de @{name}",
@ -163,7 +164,7 @@
"notifications.column_settings.alert": "Notifications locales",
"notifications.column_settings.favourite": "Favoris :",
"notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e·s :",
"notifications.column_settings.mention": "Mentions:",
"notifications.column_settings.mention": "Mentions :",
"notifications.column_settings.push": "Notifications push",
"notifications.column_settings.push_meta": "Cet appareil",
"notifications.column_settings.reblog": "Partages :",
@ -200,13 +201,16 @@
"privacy.unlisted.long": "Ne pas afficher dans les fils publics",
"privacy.unlisted.short": "Non-listé",
"regeneration_indicator.label": "Chargement…",
"regeneration_indicator.sublabel": "Votre page principale est en cours de préparation!",
"regeneration_indicator.sublabel": "Le flux de votre page principale est en cours de préparation !",
"relative_time.days": "{number} j",
"relative_time.hours": "{number} h",
"relative_time.just_now": "à l’instant",
"relative_time.minutes": "{number} min",
"relative_time.seconds": "{number} s",
"reply_indicator.cancel": "Annuler",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Commentaires additionnels",
"report.submit": "Envoyer",
"report.target": "Signalement",
@ -216,6 +220,9 @@
"search_popout.tips.status": "statuts",
"search_popout.tips.text": "Un texte simple renvoie les noms affichés, les noms d’utilisateur⋅ice et les hashtags correspondants",
"search_popout.tips.user": "utilisateur⋅ice",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {résultat} other {résultats}}",
"standalone.public_title": "Jeter un coup d’œil…",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Glissez et déposez pour envoyer",
"upload_button.label": "Joindre un média",
"upload_form.description": "Décrire pour les malvoyants",
"upload_form.focus": "Crop",
"upload_form.undo": "Annuler",
"upload_progress.label": "Envoi en cours…",
"video.close": "Fermer la vidéo",

+ 9
- 1
app/javascript/mastodon/locales/gl.json View File

@ -13,7 +13,8 @@
"account.moved_to": "{name} marchou a:",
"account.mute": "Acalar @{name}",
"account.mute_notifications": "Acalar as notificacións de @{name}",
"account.posts": "Publicacións",
"account.posts": "Toots",
"account.posts_with_replies": "Toots with replies",
"account.report": "Informar sobre @{name}",
"account.requested": "Agardando aceptación. Pulse para cancelar a solicitude de seguimento",
"account.share": "Compartir o perfil de @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancelar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentarios adicionais",
"report.submit": "Enviar",
"report.target": "Informar {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "estado",
"search_popout.tips.text": "Texto simple devolve coincidencias con nomes públicos, nomes de usuaria e etiquetas",
"search_popout.tips.user": "usuaria",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count,plural,one {result} outros {results}}",
"standalone.public_title": "Ollada dentro...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Arrastre e solte para subir",
"upload_button.label": "Engadir medios",
"upload_form.description": "Describa para deficientes visuais",
"upload_form.focus": "Crop",
"upload_form.undo": "Desfacer",
"upload_progress.label": "Subindo...",
"video.close": "Pechar video",

+ 8
- 0
app/javascript/mastodon/locales/he.json View File

@ -14,6 +14,7 @@
"account.mute": "להשתיק את @{name}",
"account.mute_notifications": "להסתיר התראות מאת @{name}",
"account.posts": "הודעות",
"account.posts_with_replies": "Toots with replies",
"account.report": "לדווח על @{name}",
"account.requested": "בהמתנה לאישור",
"account.share": "לשתף את אודות @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "ביטול",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "הערות נוספות",
"report.submit": "שליחה",
"report.target": "דיווח",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "טקסט פשוט מחזיר כינויים, שמות משתמש והאשתגים",
"search_popout.tips.user": "משתמש(ת)",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {תוצאה} other {תוצאות}}",
"standalone.public_title": "הצצה פנימה...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "ניתן להעלות על ידי Drag & drop",
"upload_button.label": "הוספת מדיה",
"upload_form.description": "תיאור לכבדי ראיה",
"upload_form.focus": "Crop",
"upload_form.undo": "ביטול",
"upload_progress.label": "עולה...",
"video.close": "סגירת וידאו",

+ 8
- 0
app/javascript/mastodon/locales/hr.json View File

@ -14,6 +14,7 @@
"account.mute": "Utišaj @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Postovi",
"account.posts_with_replies": "Toots with replies",
"account.report": "Prijavi @{name}",
"account.requested": "Čeka pristanak",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Otkaži",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Dodatni komentari",
"report.submit": "Pošalji",
"report.target": "Prijavljivanje",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Povuci i spusti kako bi uploadao",
"upload_button.label": "Dodaj media",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Poništi",
"upload_progress.label": "Uploadam...",
"video.close": "Close video",

+ 9
- 1
app/javascript/mastodon/locales/hu.json View File

@ -7,13 +7,14 @@
"account.followers": "Követők",
"account.follows": "Követve",
"account.follows_you": "Követnek téged",
"account.hide_reblogs": "@{name} kedvenceinek elrejtése",
"account.hide_reblogs": "Rejtsd el a tülkölést @{name}-tól/től",
"account.media": "Média",
"account.mention": "@{name} említése",
"account.moved_to": "{name} átköltözött:",
"account.mute": "@{name} némítása",
"account.mute_notifications": "@{name} értesítések némítása",
"account.posts": "Státuszok",
"account.posts_with_replies": "Toots with replies",
"account.report": "@{name} jelentése",
"account.requested": "Engedélyre vár. Kattintson a követési kérés visszavonására",
"account.share": "@{name} profiljának megosztása",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Mégsem",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "További kommentek",
"report.submit": "Submit",
"report.target": "Reporting",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "felhasználó",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Betekintés...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Húzza ide a feltöltéshez",
"upload_button.label": "Média hozzáadása",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Mégsem",
"upload_progress.label": "Uploading...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/hy.json View File

@ -14,6 +14,7 @@
"account.mute": "Լռեցնել @{name}֊ին",
"account.mute_notifications": "Անջատել ծանուցումները @{name}֊ից",
"account.posts": "Գրառումներ",
"account.posts_with_replies": "Toots with replies",
"account.report": "Բողոքել @{name}֊ից",
"account.requested": "Հաստատման կարիք ունի։ Սեղմիր՝ հետեւելու հայցը չեղարկելու համար։",
"account.share": "Կիսվել @{name}֊ի էջով",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}ր",
"relative_time.seconds": "{number}վ",
"reply_indicator.cancel": "Չեղարկել",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Լրացուցիչ մեկնաբանություններ",
"report.submit": "Ուղարկել",
"report.target": "Բողոքել {target}֊ի մասին",
@ -216,6 +220,9 @@
"search_popout.tips.status": "թութ",
"search_popout.tips.text": "Հասարակ տեքստը կվերադարձնի համընկնող անուններ, օգտանուններ ու պիտակներ",
"search_popout.tips.user": "օգտատեր",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "Այս պահին…",
"status.block": "Արգելափակել @{name}֊ին",
@ -252,6 +259,7 @@
"upload_area.title": "Քաշիր ու նետիր՝ վերբեռնելու համար",
"upload_button.label": "Ավելացնել մեդիա",
"upload_form.description": "Նկարագրություն ավելացրու տեսողական խնդիրներ ունեցողների համար",
"upload_form.focus": "Crop",
"upload_form.undo": "Հետարկել",
"upload_progress.label": "Վերբեռնվում է…",
"video.close": "Փակել տեսագրությունը",

+ 8
- 0
app/javascript/mastodon/locales/id.json View File

@ -14,6 +14,7 @@
"account.mute": "Bisukan @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Postingan",
"account.posts_with_replies": "Toots with replies",
"account.report": "Laporkan @{name}",
"account.requested": "Menunggu persetujuan",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Batal",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Komentar tambahan",
"report.submit": "Kirim",
"report.target": "Melaporkan",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count} {count, plural, one {hasil} other {hasil}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Seret & lepaskan untuk mengunggah",
"upload_button.label": "Tambahkan media",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Undo",
"upload_progress.label": "Mengunggah...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/io.json View File

@ -14,6 +14,7 @@
"account.mute": "Celar @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Mesaji",
"account.posts_with_replies": "Toots with replies",
"account.report": "Denuncar @{name}",
"account.requested": "Vartante aprobo",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Nihiligar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Plusa komenti",
"report.submit": "Sendar",
"report.target": "Denuncante",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {rezulto} other {rezulti}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Tranar faligar por kargar",
"upload_button.label": "Adjuntar kontenajo",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Desfacar",
"upload_progress.label": "Kargante...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/it.json View File

@ -14,6 +14,7 @@
"account.mute": "Silenzia @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Posts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Segnala @{name}",
"account.requested": "In attesa di approvazione",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Annulla",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Commenti aggiuntivi",
"report.submit": "Invia",
"report.target": "Invio la segnalazione",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count} {count, plural, one {risultato} other {risultati}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Trascina per caricare",
"upload_button.label": "Aggiungi file multimediale",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Annulla",
"upload_progress.label": "Sto caricando...",
"video.close": "Close video",

+ 11
- 3
app/javascript/mastodon/locales/ja.json View File

@ -14,11 +14,12 @@
"account.mute": "@{name}さんをミュート",
"account.mute_notifications": "@{name}さんからの通知を受け取らない",
"account.posts": "投稿",
"account.posts_with_replies": "トゥートと返信",
"account.report": "@{name}さんを通報",
"account.requested": "フォロー承認待ちです。クリックしてキャンセル",
"account.share": "@{name}さんのプロフィールを共有する",
"account.show_reblogs": "@{name}さんからのブーストを表示",
"account.unblock": "@{name}さんのブロック解除",
"account.unblock": "@{name}さんのブロック解除",
"account.unblock_domain": "{domain}を表示",
"account.unfollow": "フォロー解除",
"account.unmute": "@{name}さんのミュートを解除",
@ -71,7 +72,7 @@
"confirmations.delete_list.confirm": "削除",
"confirmations.delete_list.message": "本当にこのリストを完全に削除しますか?",
"confirmations.domain_block.confirm": "ドメイン全体を非表示",
"confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。",
"confirmations.domain_block.message": "本当に{domain}全体を非表示にしますか? 多くの場合は個別にブロックやミュートするだけで充分であり、また好ましいです。",
"confirmations.mute.confirm": "ミュート",
"confirmations.mute.message": "本当に{name}さんをミュートしますか?",
"confirmations.unfollow.confirm": "フォロー解除",
@ -207,13 +208,16 @@
"privacy.unlisted.long": "公開TLで表示しない",
"privacy.unlisted.short": "未収載",
"regeneration_indicator.label": "読み込み中…",
"regeneration_indicator.sublabel": "ホームタイムラインは準備中です!",
"regeneration_indicator.sublabel": "ホームタイムラインは準備中です",
"relative_time.days": "{number}日前",
"relative_time.hours": "{number}時間前",
"relative_time.just_now": "今",
"relative_time.minutes": "{number}分前",
"relative_time.seconds": "{number}秒前",
"reply_indicator.cancel": "キャンセル",
"report.forward": "{target} に転送する",
"report.forward_hint": "このアカウントは別のインスタンスに所属しています。通報内容を匿名で転送しますか?",
"report.hint": "通報内容はあなたのインスタンスのモデレーターへ送信されます。通報理由を入力してください。:",
"report.placeholder": "追加コメント",
"report.submit": "通報する",
"report.target": "{target}さんを通報する",
@ -223,6 +227,9 @@
"search_popout.tips.status": "トゥート",
"search_popout.tips.text": "表示名やユーザー名、ハッシュタグに一致する単純なテキスト",
"search_popout.tips.user": "ユーザー",
"search_results.accounts": "人々",
"search_results.hashtags": "ハッシュタグ",
"search_results.statuses": "トゥート",
"search_results.total": "{count, number}件の結果",
"standalone.public_title": "今こんな話をしています...",
"status.block": "@{name}さんをブロック",
@ -259,6 +266,7 @@
"upload_area.title": "ドラッグ&ドロップでアップロード",
"upload_button.label": "メディアを追加",
"upload_form.description": "視覚障害者のための説明",
"upload_form.focus": "焦点",
"upload_form.undo": "やり直す",
"upload_progress.label": "アップロード中...",
"video.close": "動画を閉じる",

+ 8
- 0
app/javascript/mastodon/locales/ko.json View File

@ -14,6 +14,7 @@
"account.mute": "@{name} 뮤트",
"account.mute_notifications": "@{name}의 알림을 뮤트",
"account.posts": "게시물",
"account.posts_with_replies": "Toots with replies",
"account.report": "@{name} 신고",
"account.requested": "승인 대기 중. 클릭해서 취소하기",
"account.share": "@{name}의 프로파일 공유",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}분 전",
"relative_time.seconds": "{number}초 전",
"reply_indicator.cancel": "취소",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "코멘트",
"report.submit": "신고하기",
"report.target": "문제가 된 사용자",
@ -216,6 +220,9 @@
"search_popout.tips.status": "툿",
"search_popout.tips.text": "단순한 텍스트 검색은 관계된 프로필 이름, 유저 이름 그리고 해시태그를 표시합니다",
"search_popout.tips.user": "유저",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number}건의 결과",
"standalone.public_title": "지금 이런 이야기를 하고 있습니다…",
"status.block": "@{name} 차단",
@ -252,6 +259,7 @@
"upload_area.title": "드래그 & 드롭으로 업로드",
"upload_button.label": "미디어 추가",
"upload_form.description": "시각장애인을 위한 설명",
"upload_form.focus": "Crop",
"upload_form.undo": "재시도",
"upload_progress.label": "업로드 중...",
"video.close": "동영상 닫기",

+ 9
- 1
app/javascript/mastodon/locales/nl.json View File

@ -14,6 +14,7 @@
"account.mute": "Negeer @{name}",
"account.mute_notifications": "Negeer meldingen van @{name}",
"account.posts": "Toots",
"account.posts_with_replies": "Toots with replies",
"account.report": "Rapporteer @{name}",
"account.requested": "Wacht op goedkeuring. Klik om het volgverzoek te annuleren",
"account.share": "Profiel van @{name} delen",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Annuleren",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Extra opmerkingen",
"report.submit": "Verzenden",
"report.target": "Rapporteer {target}",
@ -216,9 +220,12 @@
"search_popout.tips.status": "toot",
"search_popout.tips.text": "Gebruik gewone tekst om te zoeken op weergavenamen, gebruikersnamen en hashtags",
"search_popout.tips.user": "gebruiker",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultaat} other {resultaten}}",
"standalone.public_title": "Een kijkje binnenin...",
"status.block": "Block @{name}",
"status.block": "Blokkeer @{name}",
"status.cannot_reblog": "Deze toot kan niet geboost worden",
"status.delete": "Verwijderen",
"status.embed": "Embed",
@ -252,6 +259,7 @@
"upload_area.title": "Hierin slepen om te uploaden",
"upload_button.label": "Media toevoegen",
"upload_form.description": "Omschrijf dit voor mensen met een visuele beperking",
"upload_form.focus": "Crop",
"upload_form.undo": "Ongedaan maken",
"upload_progress.label": "Uploaden...",
"video.close": "Video sluiten",

+ 8
- 0
app/javascript/mastodon/locales/no.json View File

@ -14,6 +14,7 @@
"account.mute": "Demp @{name}",
"account.mute_notifications": "Ignorer varsler fra @{name}",
"account.posts": "Innlegg",
"account.posts_with_replies": "Toots with replies",
"account.report": "Rapportér @{name}",
"account.requested": "Venter på godkjennelse",
"account.share": "Del @{name}s profil",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Avbryt",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Tilleggskommentarer",
"report.submit": "Send inn",
"report.target": "Rapporterer",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Enkel tekst returnerer matchende visningsnavn, brukernavn og emneknagger",
"search_popout.tips.user": "bruker",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultater}}",
"standalone.public_title": "En titt inni...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Dra og slipp for å laste opp",
"upload_button.label": "Legg til media",
"upload_form.description": "Beskriv for synshemmede",
"upload_form.focus": "Crop",
"upload_form.undo": "Angre",
"upload_progress.label": "Laster opp...",
"video.close": "Lukk video",

+ 8
- 0
app/javascript/mastodon/locales/oc.json View File

@ -14,6 +14,7 @@
"account.mute": "Rescondre @{name}",
"account.mute_notifications": "Rescondre las notificacions de @{name}",
"account.posts": "Estatuts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Senhalar @{name}",
"account.requested": "Invitacion mandada. Clicatz per anullar",
"account.share": "Partejar lo perfil a @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "fa {number}min",
"relative_time.seconds": "fa {number}s",
"reply_indicator.cancel": "Anullar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentaris addicionals",
"report.submit": "Mandar",
"report.target": "Senhalar {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "estatut",
"search_popout.tips.text": "Lo tèxt brut tòrna escais, noms d’utilizaire e etiquetas correspondents",
"search_popout.tips.user": "utilizaire",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}",
"standalone.public_title": "Una ulhada dedins…",
"status.block": "Blocar @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Lisatz e depausatz per mandar",
"upload_button.label": "Ajustar un mèdia",
"upload_form.description": "Descripcion pels mal vesents",
"upload_form.focus": "Crop",
"upload_form.undo": "Anullar",
"upload_progress.label": "Mandadís…",
"video.close": "Tampar la vidèo",

+ 9
- 4
app/javascript/mastodon/locales/pl.json View File

@ -14,6 +14,7 @@
"account.mute": "Wycisz @{name}",
"account.mute_notifications": "Wycisz powiadomienia o @{name}",
"account.posts": "Wpisy",
"account.posts_with_replies": "Wpisy z odpowiedziami",
"account.report": "Zgłoś @{name}",
"account.requested": "Oczekująca prośba, kliknij aby anulować",
"account.share": "Udostępnij profil @{name}",
@ -99,7 +100,7 @@
"empty_column.home.public_timeline": "publiczna oś czasu",
"empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.",
"empty_column.notifications": "Nie masz żadnych powiadomień. Rozpocznij interakcje z innymi użytkownikami.",
"empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić.",
"empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych instancji, aby to wyświetlić",
"follow_request.authorize": "Autoryzuj",
"follow_request.reject": "Odrzuć",
"getting_started.appsshort": "Aplikacje",
@ -134,11 +135,11 @@
"lightbox.next": "Następne",
"lightbox.previous": "Poprzednie",
"lists.account.add": "Dodaj do listy",
"lists.account.remove": "Usuń z listy",
"lists.account.remove": "Usunąć z listy",
"lists.delete": "Usuń listę",
"lists.edit": "Edytuj listę",
"lists.new.create": "Utwórz listę",
"lists.new.title_placeholder": "Wprowadź tytuł listy",
"lists.new.title_placeholder": "Wprowadź tytuł listy",
"lists.search": "Szukaj wśród osób które śledzisz",
"lists.subheading": "Twoje listy",
"loading_indicator.label": "Ładowanie…",
@ -206,7 +207,7 @@
"privacy.public.short": "Publiczny",
"privacy.unlisted.long": "Niewidoczny na publicznych osiach czasu",
"privacy.unlisted.short": "Niewidoczny",
"regeneration_indicator.label": "Ładowanie…",
"regeneration_indicator.label": "Ładuję…",
"regeneration_indicator.sublabel": "Twoja oś czasu jest przygotowywana!",
"relative_time.days": "{number} dni",
"relative_time.hours": "{number} godz.",
@ -214,6 +215,9 @@
"relative_time.minutes": "{number} min.",
"relative_time.seconds": "{number} s.",
"reply_indicator.cancel": "Anuluj",
"report.forward": "Przekaż na {target}",
"report.forward_hint": "To konto znajduje się na innej instancji. Czy chcesz wysłać anonimową kopię zgłoszenia rnież na nią?",
"report.hint": "Zgłoszenie zostanie wysłane moderatorom Twojej instancji. Poniżej możesz też umieścić wyjaśnieni dlaczego zgłaszasz to konto:",
"report.placeholder": "Dodatkowe komentarze",
"report.submit": "Wyślij",
"report.target": "Zgłaszanie {target}",
@ -262,6 +266,7 @@
"upload_area.title": "Przeciągnij i upuść aby wysłać",
"upload_button.label": "Dodaj zawartość multimedialną",
"upload_form.description": "Wprowadź opis dla niewidomych i niedowidzących",
"upload_form.focus": "Crop",
"upload_form.undo": "Cofnij",
"upload_progress.label": "Wysyłanie",
"video.close": "Zamknij film",

+ 9
- 1
app/javascript/mastodon/locales/pt-BR.json View File

@ -14,6 +14,7 @@
"account.mute": "Silenciar @{name}",
"account.mute_notifications": "Silenciar notificações de @{name}",
"account.posts": "Posts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Denunciar @{name}",
"account.requested": "Aguardando aprovação. Clique para cancelar a solicitação",
"account.share": "Compartilhar perfil de @{name}",
@ -90,7 +91,7 @@
"emoji_button.travel": "Viagens & Lugares",
"empty_column.community": "A timeline local está vazia. Escreva algo publicamente para começar!",
"empty_column.hashtag": "Ainda não há qualquer conteúdo com essa hashtag.",
"empty_column.home": "Você ainda não segue usuário algo. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.",
"empty_column.home": "Você ainda não segue usuário algum. Visite a timeline {public} ou use o buscador para procurar e conhecer outros usuários.",
"empty_column.home.public_timeline": "global",
"empty_column.list": "Ainda não há nada nesta lista. Quando membros dessa lista fizerem novas postagens, elas aparecerão aqui.",
"empty_column.notifications": "Você ainda não possui notificações. Interaja com outros usuários para começar a conversar.",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancelar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentários adicionais",
"report.submit": "Enviar",
"report.target": "Denunciar",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Texto simples retorna nomes de exibição, usuários e hashtags correspondentes",
"search_popout.tips.user": "usuário",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Dê uma espiada...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",
"upload_form.description": "Descreva a imagem para deficientes visuais",
"upload_form.focus": "Crop",
"upload_form.undo": "Desfazer",
"upload_progress.label": "Salvando...",
"video.close": "Fechar vídeo",

+ 8
- 0
app/javascript/mastodon/locales/pt.json View File

@ -14,6 +14,7 @@
"account.mute": "Silenciar @{name}",
"account.mute_notifications": "Silenciar notificações de @{name}",
"account.posts": "Posts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Denunciar @{name}",
"account.requested": "A aguardar aprovação",
"account.share": "Partilhar o perfil @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancelar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Comentários adicionais",
"report.submit": "Enviar",
"report.target": "Denunciar",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "O texto simples retorna a correspondência de nomes, utilizadores e hashtags",
"search_popout.tips.user": "utilizador",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
"standalone.public_title": "Espreitar lá dentro...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar media",
"upload_form.description": "Descrição da imagem para pessoas com dificuldades visuais",
"upload_form.focus": "Crop",
"upload_form.undo": "Anular",
"upload_progress.label": "A gravar...",
"video.close": "Fechar vídeo",

+ 8
- 0
app/javascript/mastodon/locales/ru.json View File

@ -14,6 +14,7 @@
"account.mute": "Заглушить",
"account.mute_notifications": "Скрыть уведомления от @{name}",
"account.posts": "Посты",
"account.posts_with_replies": "Toots with replies",
"account.report": "Пожаловаться",
"account.requested": "Ожидает подтверждения",
"account.share": "Поделиться профилем @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}м",
"relative_time.seconds": "{number}с",
"reply_indicator.cancel": "Отмена",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Комментарий",
"report.submit": "Отправить",
"report.target": "Жалуемся на",
@ -216,6 +220,9 @@
"search_popout.tips.status": "статус",
"search_popout.tips.text": "Простой ввод текста покажет совпадающие имена пользователей, отображаемые имена и хэштеги",
"search_popout.tips.user": "пользователь",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {результат} few {результата} many {результатов} other {результатов}}",
"standalone.public_title": "Прямо сейчас",
"status.block": "Заблокировать @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Перетащите сюда, чтобы загрузить",
"upload_button.label": "Добавить медиаконтент",
"upload_form.description": "Описать для людей с нарушениями зрения",
"upload_form.focus": "Crop",
"upload_form.undo": "Отменить",
"upload_progress.label": "Загрузка...",
"video.close": "Закрыть видео",

+ 25
- 17
app/javascript/mastodon/locales/sk.json View File

@ -4,7 +4,7 @@
"account.disclaimer_full": "Inofrmácie nižšie nemusia byť úplným odrazom uživateľovho účtu.",
"account.edit_profile": "Upraviť profil",
"account.follow": "Následovať",
"account.followers": "Následovaťelia",
"account.followers": "Sledujúci",
"account.follows": "Sledujete",
"account.follows_you": "Následuje vás",
"account.hide_reblogs": "Skryť povýšenia od @{name}",
@ -13,7 +13,8 @@
"account.moved_to": "{name} sa presunul/a na:",
"account.mute": "Ignorovať @{name}",
"account.mute_notifications": "Stĺmiť notifikácie od @{name}",
"account.posts": "Správy",
"account.posts": "Hlášky",
"account.posts_with_replies": "Toots with replies",
"account.report": "Nahlásiť @{name}",
"account.requested": "Čaká na schválenie. Kliknite pre zrušenie žiadosti",
"account.share": "Zdieľať @{name} profil",
@ -72,7 +73,7 @@
"confirmations.mute.message": "Naozaj chcete ignorovať {name}?",
"confirmations.unfollow.confirm": "Nesledovať",
"confirmations.unfollow.message": "Naozaj chcete prestať sledovať {name}?",
"embed.instructions": "Skopírujte kód uvedený nižšie pre pridanie tohto statusu na vašu web stránku.",
"embed.instructions": "Umiestnite kód uvedený nižšie pre pridanie tohto statusu na vašu web stránku.",
"embed.preview": "Tu je ako to bude vyzerať:",
"emoji_button.activity": "Aktivita",
"emoji_button.custom": "Vlastné",
@ -100,7 +101,7 @@
"getting_started.appsshort": "Aplikácie",
"getting_started.faq": "FAQ",
"getting_started.heading": "Začíname",
"getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžeš na GitHube v {github}.",
"getting_started.open_source_notice": "Mastodon má otvorený kód. Nahlásiť chyby, alebo prispievať vlastným kódom môžete na GitHube v {github}.",
"getting_started.userguide": "Používateľská príručka",
"home.column_settings.advanced": "Rozšírené",
"home.column_settings.basic": "Základné",
@ -122,11 +123,11 @@
"keyboard_shortcuts.mention": "spomenúť autora",
"keyboard_shortcuts.reply": "odpovedať",
"keyboard_shortcuts.search": "zamerať sa na vyhľadávanie",
"keyboard_shortcuts.toot": "začať úplne nový toot",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.toot": "začať úplne novú hlášku",
"keyboard_shortcuts.unfocus": "nesústrediť sa na písaciu plochu, alebo hľadanie",
"keyboard_shortcuts.up": "posunúť sa vyššie v zozname",
"lightbox.close": "Zatvoriť",
"lightbox.next": "Ďalší",
"lightbox.next": "Ďalšie",
"lightbox.previous": "Predchádzajúci",
"lists.account.add": "Pridať do zoznamu",
"lists.account.remove": "Odobrať zo zoznamu",
@ -159,10 +160,10 @@
"notification.mention": "{name} vás spomenul",
"notification.reblog": "{name} re-tootol tvoj status",
"notifications.clear": "Vyčistiť zoznam notifikácii",
"notifications.clear_confirmation": "Naozaj chcete nenávratne vymazať všetky vaše notifikácie?",
"notifications.clear_confirmation": "Naozaj chcete nenávratne prečistiť všetky vaše notifikácie?",
"notifications.column_settings.alert": "Notifikácie na ploche",
"notifications.column_settings.favourite": "Obľúbené:",
"notifications.column_settings.follow": "Nový nasledujúci:",
"notifications.column_settings.follow": "Noví následujúci:",
"notifications.column_settings.mention": "Zmienenia:",
"notifications.column_settings.push": "Push notifikácie",
"notifications.column_settings.push_meta": "Toto zariadenie",
@ -175,7 +176,7 @@
"onboarding.page_four.home": "Domovská časová os zobrazí správy od ľudí ktorých sledujete.",
"onboarding.page_four.notifications": "Stĺpec s notifikáciami zobrazí keď budete s niekým komunikovať.",
"onboarding.page_one.federation": "Mastodon je sieť nezávislých serverov, spojením ktorých vzniká jedna veľká federovaná sociálna sieť.",
"onboarding.page_one.full_handle": "Your full handle",
"onboarding.page_one.full_handle": "Vaša celá prezývka aj s adresou",
"onboarding.page_one.handle_hint": "Toto je čo by ste povedali vaším priateľom že majú hľadať.",
"onboarding.page_one.welcome": "Vitajte na Mastodone!",
"onboarding.page_six.admin": "Správca tohto servera je {admin}.",
@ -193,7 +194,7 @@
"privacy.change": "Zmeňiť viditeľnosť statusu",
"privacy.direct.long": "Poslať priamo iba spomenutým používateľom",
"privacy.direct.short": "Súkromne",
"privacy.private.long": "Poslať iba sledujúcim",
"privacy.private.long": "Poslať iba následovateľom",
"privacy.private.short": "Iba pre sledujúcich",
"privacy.public.long": "Poslať všetkým verejne",
"privacy.public.short": "Verejné",
@ -207,23 +208,29 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Zrušiť",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Ďalšie komentáre",
"report.submit": "Poslať",
"report.target": "Nahlásenie {target}",
"search.placeholder": "Hľadať",
"search_popout.search_format": "Pokročilý tvar vyhľadávania",
"search_popout.tips.hashtag": "hashtag",
"search_popout.search_format": "Pokročilý formát vyhľadávania",
"search_popout.tips.hashtag": "haštag",
"search_popout.tips.status": "status",
"search_popout.tips.text": "Jednoduchý text vráti zhodujúce sa mená, prezývky a hashtagy",
"search_popout.tips.user": "používateľ",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} ostatné {results}}",
"standalone.public_title": "Pohľad dovnútra...",
"status.block": "Blokovať @{name}",
"status.cannot_reblog": "Tento príspevok nemôže byť re-tootnutý",
"status.delete": "Zmazať",
"status.embed": "Embed",
"status.embed": "Vložiť",
"status.favourite": "Páči sa mi",
"status.load_more": "Zobraz viac",
"status.load_more": "Zobraz viac",
"status.media_hidden": "Skryté médiá",
"status.mention": "Napísať @{name}",
"status.more": "Viac",
@ -239,8 +246,8 @@
"status.sensitive_toggle": "Kliknite pre zobrazenie",
"status.sensitive_warning": "Chúlostivý obsah",
"status.share": "Zdieľať",
"status.show_less": "Zobraz menej",
"status.show_more": "Zobraz viac",
"status.show_less": "Zobraz menej",
"status.show_more": "Zobraz viac",
"status.unmute_conversation": "Prestať ignorovať konverzáciu",
"status.unpin": "Odopnúť z profilu",
"tabs_bar.compose": "Napísať",
@ -252,6 +259,7 @@
"upload_area.title": "Ťahaj a pusti pre nahratie",
"upload_button.label": "Pridať médiá",
"upload_form.description": "Opis pre slabo vidiacich",
"upload_form.focus": "Crop",
"upload_form.undo": "Navrátiť",
"upload_progress.label": "Nahráva sa...",
"video.close": "Zavrieť video",

+ 8
- 0
app/javascript/mastodon/locales/sr-Latn.json View File

@ -14,6 +14,7 @@
"account.mute": "Ućutkaj korisnika @{name}",
"account.mute_notifications": "Isključi obaveštenja od korisnika @{name}",
"account.posts": "Statusa",
"account.posts_with_replies": "Toots with replies",
"account.report": "Prijavi @{name}",
"account.requested": "Čekam odobrenje. Kliknite da poništite zahtev za praćenje",
"account.share": "Podeli profil korisnika @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Poništi",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Dodatni komentari",
"report.submit": "Pošalji",
"report.target": "Prijavljujem {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Traženjem običnog teksta ćete dobiti sva pronađena imena, sva korisnička imena i sve nađene heštegove",
"search_popout.tips.user": "korisnik",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {rezultat} few {rezultata} other {rezultata}}",
"standalone.public_title": "Pogled iznutra...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Prevucite ovde da otpremite",
"upload_button.label": "Dodaj multimediju",
"upload_form.description": "Opiši za slabovide osobe",
"upload_form.focus": "Crop",
"upload_form.undo": "Opozovi",
"upload_progress.label": "Otpremam...",
"video.close": "Zatvori video",

+ 8
- 0
app/javascript/mastodon/locales/sr.json View File

@ -14,6 +14,7 @@
"account.mute": "Ућуткај корисника @{name}",
"account.mute_notifications": "Искључи обавештења од корисника @{name}",
"account.posts": "Статуса",
"account.posts_with_replies": "Toots with replies",
"account.report": "Пријави @{name}",
"account.requested": "Чекам одобрење. Кликните да поништите захтев за праћење",
"account.share": "Подели профил корисника @{name}",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Поништи",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Додатни коментари",
"report.submit": "Пошаљи",
"report.target": "Пријављујем {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "статус",
"search_popout.tips.text": "Тражењем обичног текста ћете добити сва пронађена имена, сва корисничка имена и све нађене хештегове",
"search_popout.tips.user": "корисник",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {резултат} few {резултата} other {резултата}}",
"standalone.public_title": "Поглед изнутра...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Превуците овде да отпремите",
"upload_button.label": "Додај мултимедију",
"upload_form.description": "Опиши за слабовиде особе",
"upload_form.focus": "Crop",
"upload_form.undo": "Опозови",
"upload_progress.label": "Отпремам...",
"video.close": "Затвори видео",

+ 8
- 0
app/javascript/mastodon/locales/sv.json View File

@ -14,6 +14,7 @@
"account.mute": "Tysta @{name}",
"account.mute_notifications": "Stäng av notifieringar från @{name}",
"account.posts": "Inlägg",
"account.posts_with_replies": "Toots with replies",
"account.report": "Rapportera @{name}",
"account.requested": "Inväntar godkännande. Klicka för att avbryta följförfrågan",
"account.share": "Dela @{name}'s profil",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Ångra",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Ytterligare kommentarer",
"report.submit": "Skicka",
"report.target": "Rapporterar {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Enkel text returnerar matchande visningsnamn, användarnamn och hashtags",
"search_popout.tips.user": "användare",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, ett {result} andra {results}}",
"standalone.public_title": "En titt inuti...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Dra & släpp för att ladda upp",
"upload_button.label": "Lägg till media",
"upload_form.description": "Beskriv för synskadade",
"upload_form.focus": "Crop",
"upload_form.undo": "Ångra",
"upload_progress.label": "Laddar upp...",
"video.close": "Stäng video",

+ 8
- 0
app/javascript/mastodon/locales/th.json View File

@ -14,6 +14,7 @@
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Posts",
"account.posts_with_replies": "Toots with replies",
"account.report": "Report @{name}",
"account.requested": "Awaiting approval",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancel",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.submit": "Submit",
"report.target": "Reporting",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Undo",
"upload_progress.label": "Uploading...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/tr.json View File

@ -14,6 +14,7 @@
"account.mute": "Sustur @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Gönderiler",
"account.posts_with_replies": "Toots with replies",
"account.report": "Rapor et @{name}",
"account.requested": "Onay bekleniyor",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "İptal",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Ek yorumlar",
"report.submit": "Gönder",
"report.target": "Raporlama",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {sonuç} other {sonuçlar}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Upload için sürükle bırak yapınız",
"upload_button.label": "Görsel ekle",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Geri al",
"upload_progress.label": "Yükleniyor...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/uk.json View File

@ -14,6 +14,7 @@
"account.mute": "Заглушити",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "Пости",
"account.posts_with_replies": "Toots with replies",
"account.report": "Поскаржитися",
"account.requested": "Очікує підтвердження",
"account.share": "Share @{name}'s profile",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Відмінити",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Додаткові коментарі",
"report.submit": "Відправити",
"report.target": "Скаржимося на",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {результат} few {результати} many {результатів} other {результатів}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "Перетягніть сюди, щоб завантажити",
"upload_button.label": "Додати медіаконтент",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Відмінити",
"upload_progress.label": "Завантаження...",
"video.close": "Close video",

+ 8
- 0
app/javascript/mastodon/locales/zh-CN.json View File

@ -14,6 +14,7 @@
"account.mute": "隐藏 @{name}",
"account.mute_notifications": "隐藏来自 @{name} 的通知",
"account.posts": "嘟文",
"account.posts_with_replies": "Toots with replies",
"account.report": "举报 @{name}",
"account.requested": "正在等待对方同意。点击以取消发送关注请求",
"account.share": "分享 @{name} 的个人资料",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}分",
"relative_time.seconds": "{number}秒",
"reply_indicator.cancel": "取消",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "附言",
"report.submit": "提交",
"report.target": "举报 {target}",
@ -216,6 +220,9 @@
"search_popout.tips.status": "嘟文",
"search_popout.tips.text": "使用普通字符进行搜索将会返回昵称、用户名和话题标签",
"search_popout.tips.user": "用户",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "共 {count, number} 个结果",
"standalone.public_title": "大家都在干啥?",
"status.block": "屏蔽 @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "将文件拖放到此处开始上传",
"upload_button.label": "上传媒体文件",
"upload_form.description": "为视觉障碍人士添加文字说明",
"upload_form.focus": "Crop",
"upload_form.undo": "取消上传",
"upload_progress.label": "上传中…",
"video.close": "关闭视频",

+ 8
- 0
app/javascript/mastodon/locales/zh-HK.json View File

@ -14,6 +14,7 @@
"account.mute": "將 @{name} 靜音",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "文章",
"account.posts_with_replies": "Toots with replies",
"account.report": "舉報 @{name}",
"account.requested": "等候審批",
"account.share": "分享 @{name} 的個人資料",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "取消",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "額外訊息",
"report.submit": "提交",
"report.target": "舉報",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "將檔案拖放至此上載",
"upload_button.label": "上載媒體檔案",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "還原",
"upload_progress.label": "上載中……",
"video.close": "關閉影片",

+ 8
- 0
app/javascript/mastodon/locales/zh-TW.json View File

@ -14,6 +14,7 @@
"account.mute": "消音 @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.posts": "貼文",
"account.posts_with_replies": "Toots with replies",
"account.report": "檢舉 @{name}",
"account.requested": "正在等待許可",
"account.share": "分享 @{name} 的用者資訊",
@ -207,6 +208,9 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "取消",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "更多訊息",
"report.submit": "送出",
"report.target": "通報中",
@ -216,6 +220,9 @@
"search_popout.tips.status": "status",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} 項結果",
"standalone.public_title": "站點一瞥…",
"status.block": "Block @{name}",
@ -252,6 +259,7 @@
"upload_area.title": "拖放來上傳",
"upload_button.label": "增加媒體",
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "復原",
"upload_progress.label": "上傳中...",
"video.close": "關閉影片",

+ 4
- 0
app/javascript/mastodon/reducers/reports.js View File

@ -6,6 +6,7 @@ import {
REPORT_CANCEL,
REPORT_STATUS_TOGGLE,
REPORT_COMMENT_CHANGE,
REPORT_FORWARD_CHANGE,
} from '../actions/reports';
import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable';
@ -15,6 +16,7 @@ const initialState = ImmutableMap({
account_id: null,
status_ids: ImmutableSet(),
comment: '',
forward: false,
}),
});
@ -42,6 +44,8 @@ export default function reports(state = initialState, action) {
});
case REPORT_COMMENT_CHANGE:
return state.setIn(['new', 'comment'], action.comment);
case REPORT_FORWARD_CHANGE:
return state.setIn(['new', 'forward'], action.forward);
case REPORT_SUBMIT_REQUEST:
return state.setIn(['new', 'isSubmitting'], true);
case REPORT_SUBMIT_FAIL:

+ 197
- 166
app/javascript/styles/mastodon/about.scss View File

@ -15,117 +15,169 @@ $small-breakpoint: 960px;
}
}
.show-xs,
.show-sm {
display: none;
}
.landing-page {
.grid {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 2fr;
grid-auto-columns: 25%;
grid-auto-rows: max-content;
.column-0 {
display: none;
}
.show-m {
display: block;
}
.column-1 {
grid-column: 1;
grid-row: 1;
}
@media screen and (max-width: $small-breakpoint) {
.hide-sm {
display: none !important;
}
.column-2 {
grid-column: 2;
grid-row: 1;
}
.show-sm {
display: block !important;
}
}
.column-3 {
grid-column: 3;
grid-row: 1 / 3;
}
@media screen and (max-width: $column-breakpoint) {
.hide-xs {
display: none !important;
.column-4 {
grid-column: 1 / 3;
grid-row: 2;
}
}
.show-xs {
display: block !important;
}
}
@media screen and (max-width: $small-breakpoint) {
.grid {
grid-template-columns: 40% 60%;
.row {
display: flex;
flex-wrap: wrap;
margin: 0 -5px;
.column-0 {
display: none;
}
@for $i from 1 through 15 {
.column-#{$i} {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
.column-1 {
grid-column: 1;
grid-row: 1;
@media screen and (max-width: $small-breakpoint) {
&-sm {
box-sizing: border-box;
min-height: 1px;
flex: 0 0 percentage($i / 15);
max-width: percentage($i / 15);
padding: 0 5px;
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
&.non-preview .landing-page__forms {
height: 100%;
}
}
@media screen and (max-width: $column-breakpoint) {
max-width: 100%;
flex: 0 0 100%;
margin-bottom: 10px;
.column-2 {
grid-column: 2;
grid-row: 1 / 3;
&:last-child {
margin-bottom: 0;
&.non-preview {
grid-column: 2;
grid-row: 1;
}
}
.column-3 {
grid-column: 1;
grid-row: 2 / 4;
}
.column-4 {
grid-column: 2;
grid-row: 3;
&.non-preview {
grid-column: 1 / 3;
grid-row: 2;
}
}
}
}
}
.column-flex {
display: flex;
flex-direction: column;
}
@media screen and (max-width: $column-breakpoint) {
.grid {
grid-template-columns: auto;
.separator-or {
position: relative;
margin: 40px 0;
text-align: center;
.column-0 {
display: block;
grid-column: 1;
grid-row: 1;
}
&::before {
content: "";
display: block;
width: 100%;
height: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
position: absolute;
top: 50%;
left: 0;
.column-1 {
grid-column: 1;
grid-row: 3;
.brand {
display: none;
}
}
.column-2 {
grid-column: 1;
grid-row: 2;
.landing-page__logo,
.landing-page__call-to-action {
display: none;
}
&.non-preview {
grid-column: 1;
grid-row: 2;
}
}
.column-3 {
grid-column: 1;
grid-row: 5;
}
.column-4 {
grid-column: 1;
grid-row: 4;
&.non-preview {
grid-column: 1;
grid-row: 4;
}
}
}
}
span {
display: inline-block;
background: $ui-base-color;
font-size: 12px;
font-weight: 500;
color: $ui-primary-color;
text-transform: uppercase;
.column-flex {
display: flex;
flex-direction: column;
}
.separator-or {
position: relative;
z-index: 1;
padding: 0 8px;
cursor: default;
margin: 40px 0;
text-align: center;
&::before {
content: "";
display: block;
width: 100%;
height: 0;
border-bottom: 1px solid rgba($ui-base-lighter-color, .6);
position: absolute;
top: 50%;
left: 0;
}
span {
display: inline-block;
background: $ui-base-color;
font-size: 12px;
font-weight: 500;
color: $ui-primary-color;
text-transform: uppercase;
position: relative;
z-index: 1;
padding: 0 8px;
cursor: default;
}
}
}
.landing-page {
p,
li {
font-family: 'mastodon-font-sans-serif', sans-serif;
@ -539,6 +591,7 @@ $small-breakpoint: 960px;
img {
position: static;
padding: 10px 0;
}
@media screen and (max-width: $small-breakpoint) {
@ -558,18 +611,33 @@ $small-breakpoint: 960px;
}
&__call-to-action {
margin-bottom: 10px;
background: darken($ui-base-color, 4%);
border-radius: 4px;
padding: 25px 40px;
overflow: hidden;
.row {
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.information-board__section {
padding: 0;
.row__information-board {
display: flex;
justify-content: flex-end;
align-items: flex-end;
.information-board__section {
flex: 1 0 auto;
padding: 0 10px;
}
}
.row__mascot {
flex: 1;
margin: 10px -50px 0 0;
}
}
@ -619,6 +687,8 @@ $small-breakpoint: 960px;
&__short-description {
.row {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-bottom: 40px;
}
@ -668,7 +738,6 @@ $small-breakpoint: 960px;
height: 100%;
@media screen and (max-width: $small-breakpoint) {
margin-bottom: 10px;
height: auto;
}
@ -717,6 +786,7 @@ $small-breakpoint: 960px;
width: 100%;
flex: 1 1 auto;
overflow: hidden;
height: 100%;
.column-header {
color: inherit;
@ -942,93 +1012,54 @@ $small-breakpoint: 960px;
}
&.tag-page {
.features {
padding: 30px 0;
.container-alt {
max-width: 820px;
#mastodon-timeline {
margin-right: 0;
border-top-right-radius: 0;
}
.about-mastodon {
.about-hashtag {
background: darken($ui-base-color, 4%);
padding: 0 20px 20px 30px;
border-radius: 0 5px 5px 0;
.brand {
padding-top: 20px;
margin-bottom: 20px;
img {
height: 48px;
width: auto;
}
}
p {
strong {
color: $ui-secondary-color;
font-weight: 700;
}
}
.grid {
@media screen and (min-width: $small-breakpoint) {
grid-template-columns: 33% 67%;
}
.cta {
margin: 0;
.column-2 {
grid-column: 2;
grid-row: 1;
}
}
.button {
margin-right: 4px;
}
}
}
.brand {
text-align: unset;
padding: 0;
.features-list {
margin-left: 30px;
margin-right: 10px;
}
}
img {
height: 48px;
width: auto;
}
}
@media screen and (max-width: 675px) {
.features {
padding: 10px 0;
.cta {
margin: 0;
.container-alt {
display: flex;
flex-direction: column;
#mastodon-timeline {
order: 2;
flex: 0 0 auto;
height: 60vh;
margin-bottom: 20px;
border-top-right-radius: 4px;
}
.button {
margin-right: 4px;
}
}
.about-mastodon {
order: 1;
flex: 0 0 auto;
max-width: 100%;
@media screen and (max-width: $column-breakpoint) {
.grid {
.column-1 {
grid-column: 1;
grid-row: 2;
}
.about-hashtag {
background: unset;
padding: 0;
border-radius: 0;
.column-2 {
grid-column: 1;
grid-row: 1;
}
}
.cta {
margin: 20px 0;
}
}
.brand {
margin: 0;
}
.features-list {
display: none;
}
}
}
.landing-page__features {
display: none;
}
}
}

+ 46
- 37
app/javascript/styles/mastodon/accounts.scss View File

@ -97,32 +97,6 @@
}
}
.controls {
position: absolute;
top: 15px;
left: 15px;
z-index: 2;
.icon-button {
color: rgba($white, 0.8);
text-decoration: none;
font-size: 13px;
line-height: 13px;
font-weight: 500;
.fa {
font-weight: 400;
margin-right: 5px;
}
&:hover,
&:active,
&:focus {
color: $white;
}
}
}
.roles {
margin-bottom: 30px;
padding: 0 15px;
@ -226,6 +200,40 @@
}
}
.card,
.account-grid-card {
.controls {
position: absolute;
top: 15px;
left: 15px;
z-index: 2;
.icon-button {
color: rgba($white, 0.8);
text-decoration: none;
font-size: 13px;
line-height: 13px;
font-weight: 500;
.fa {
font-weight: 400;
margin-right: 5px;
}
&:hover,
&:active,
&:focus {
color: $white;
}
}
}
}
.account-grid-card .controls {
left: auto;
right: 15px;
}
.pagination {
padding: 30px 0;
text-align: center;
@ -233,8 +241,8 @@
a,
.current,
.next,
.prev,
.newer,
.older,
.page,
.gap {
font-size: 14px;
@ -257,13 +265,13 @@
cursor: default;
}
.prev,
.next {
.older,
.newer {
text-transform: uppercase;
color: $ui-secondary-color;
}
.prev {
.older {
float: left;
padding-left: 0;
@ -273,7 +281,7 @@
}
}
.next {
.newer {
float: right;
padding-right: 0;
@ -295,8 +303,8 @@
display: none;
}
.next,
.prev {
.newer,
.older {
display: inline-block;
}
}
@ -411,13 +419,14 @@
font-weight: 400;
}
.note {
.account__header__content {
padding: 10px 15px;
padding-top: 15px;
box-sizing: border-box;
color: lighten($ui-base-color, 26%);
word-wrap: break-word;
min-height: 80px;
overflow: hidden;
text-overflow: ellipsis;
height: 5.5em;
}
}
}

+ 176
- 39
app/javascript/styles/mastodon/components.scss View File

@ -1878,7 +1878,7 @@
font-size: 14px;
font-weight: 500;
border-bottom: 2px solid lighten($ui-base-color, 8%);
transition: all 200ms linear;
transition: all 50ms linear;
.fa {
font-weight: 400;
@ -1895,7 +1895,6 @@
&:active {
@media screen and (min-width: 631px) {
background: lighten($ui-base-color, 14%);
transition: all 100ms linear;
}
}
@ -3891,8 +3890,7 @@ a.status-card {
.boost-modal__action-bar,
.confirmation-modal__action-bar,
.mute-modal__action-bar,
.report-modal__action-bar {
.mute-modal__action-bar {
display: flex;
justify-content: space-between;
background: $ui-secondary-color;
@ -3936,21 +3934,94 @@ a.status-card {
vertical-align: middle;
}
.report-modal {
width: 90vw;
max-width: 700px;
}
.report-modal__container {
display: flex;
border-top: 1px solid $ui-secondary-color;
@media screen and (max-width: 480px) {
flex-wrap: wrap;
overflow-y: auto;
}
}
.report-modal__statuses,
.report-modal__comment {
padding: 10px;
box-sizing: border-box;
width: 50%;
@media screen and (max-width: 480px) {
width: 100%;
}
}
.report-modal__statuses {
flex: 1 1 auto;
min-height: 20vh;
max-height: 40vh;
overflow-y: auto;
overflow-x: hidden;
@media screen and (max-width: 480px) {
max-height: 10vh;
}
}
.report-modal__comment {
padding: 20px;
border-right: 1px solid $ui-secondary-color;
max-width: 320px;
p {
font-size: 14px;
line-height: 20px;
margin-bottom: 20px;
}
.setting-text {
margin-top: 10px;
display: block;
box-sizing: border-box;
width: 100%;
margin: 0;
color: $ui-base-color;
background: $white;
padding: 10px;
font-family: inherit;
font-size: 14px;
resize: vertical;
border: 0;
outline: 0;
border-radius: 4px;
border: 1px solid $ui-secondary-color;
margin-bottom: 20px;
&:focus {
border: 1px solid darken($ui-secondary-color, 8%);
}
}
.setting-toggle {
margin-top: 20px;
margin-bottom: 24px;
&__label {
color: $ui-base-color;
font-size: 14px;
}
}
@media screen and (max-width: 480px) {
padding: 10px;
max-width: 100%;
order: 2;
.setting-toggle {
margin-bottom: 4px;
}
}
}
@ -4043,6 +4114,15 @@ a.status-card {
}
}
.report-modal__target {
padding: 20px;
.media-modal__close {
top: 19px;
right: 15px;
}
}
.loading-bar {
background-color: $ui-highlight-color;
height: 3px;
@ -4154,6 +4234,7 @@ a.status-card {
&.standalone {
.media-gallery__item-gifv-thumbnail {
transform: none;
top: 0;
}
}
}
@ -4283,7 +4364,7 @@ a.status-card {
&.inline {
video {
object-fit: cover;
object-fit: contain;
position: relative;
top: 50%;
transform: translateY(-50%);
@ -4503,64 +4584,96 @@ a.status-card {
/* End Video Player */
.account-gallery__container {
margin: -2px;
padding: 4px;
display: flex;
justify-content: center;
flex-wrap: wrap;
padding: 2px;
}
.account-gallery__item {
flex: 1 1 auto;
width: calc(100% / 3 - 4px);
height: 95px;
margin: 2px;
flex-grow: 1;
width: 50%;
overflow: hidden;
position: relative;
&::before {
content: "";
display: block;
padding-top: 100%;
}
a {
display: block;
width: 100%;
height: 100%;
width: calc(100% - 4px);
height: calc(100% - 4px);
margin: 2px;
top: 0;
left: 0;
background-color: $base-overlay-background;
background-size: cover;
background-position: center;
position: relative;
position: absolute;
color: inherit;
text-decoration: none;
border-radius: 4px;
&:hover,
&:active,
&:focus {
outline: 0;
&::before {
content: "";
display: block;
width: 100%;
height: 100%;
background: rgba($base-overlay-background, 0.3);
border-radius: 4px;
}
}
}
}
.account-section-headline {
color: $ui-base-lighter-color;
background: lighten($ui-base-color, 2%);
border-bottom: 1px solid lighten($ui-base-color, 4%);
padding: 15px 10px;
font-size: 14px;
font-weight: 500;
position: relative;
.account__section-headline {
background: darken($ui-base-color, 4%);
border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: default;
display: flex;
&::before,
&::after {
a {
display: block;
content: "";
position: absolute;
bottom: 0;
left: 18px;
width: 0;
height: 0;
border-style: solid;
border-width: 0 10px 10px;
border-color: transparent transparent lighten($ui-base-color, 4%);
}
flex: 1 1 auto;
color: $ui-primary-color;
padding: 15px 0;
font-size: 14px;
font-weight: 500;
text-align: center;
text-decoration: none;
position: relative;
&::after {
bottom: -1px;
border-color: transparent transparent $ui-base-color;
&.active {
color: $ui-secondary-color;
&::before,
&::after {
display: block;
content: "";
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 0;
transform: translateX(-50%);
border-style: solid;
border-width: 0 10px 10px;
border-color: transparent transparent lighten($ui-base-color, 8%);
}
&::after {
bottom: -1px;
border-color: transparent transparent $ui-base-color;
}
}
}
}
@ -4910,3 +5023,27 @@ noscript {
left: 0;
}
}
.floating-action-button {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
width: 3.9375rem;
height: 3.9375rem;
bottom: 1.3125rem;
right: 1.3125rem;
background: darken($ui-highlight-color, 3%);
color: $white;
border-radius: 50%;
font-size: 21px;
line-height: 21px;
text-decoration: none;
box-shadow: 2px 3px 9px rgba($base-shadow-color, 0.4);
&:hover,
&:focus,
&:active {
background: lighten($ui-highlight-color, 7%);
}
}

+ 5
- 0
app/javascript/styles/mastodon/forms.scss View File

@ -278,6 +278,11 @@ code {
.actions {
margin-top: 30px;
display: flex;
&.actions--top {
margin-top: 0;
margin-bottom: 30px;
}
}
button,

+ 2
- 0
app/lib/activitypub/activity.rb View File

@ -44,6 +44,8 @@ class ActivityPub::Activity
ActivityPub::Activity::Accept
when 'Reject'
ActivityPub::Activity::Reject
when 'Flag'
ActivityPub::Activity::Flag
end
end
end

+ 25
- 0
app/lib/activitypub/activity/flag.rb View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class ActivityPub::Activity::Flag < ActivityPub::Activity
def perform
target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?)
target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id)
target_accounts.each do |target_account|
next if Report.where(account: @account, target_account: target_account).exists?
target_statuses = target_statuses_by_account[target_account.id]
ReportService.new.call(
@account,
target_account,
status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id),
comment: @json['content'] || ''
)
end
end
def object_uris
@object_uris ||= Array(@object.is_a?(Array) ? @object.map { |item| value_or_id(item) } : value_or_id(@object))
end
end

+ 2
- 0
app/lib/activitypub/activity/reject.rb View File

@ -17,6 +17,8 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity
follow_request = FollowRequest.find_by(account: target_account, target_account: @account)
follow_request&.reject!
UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
end
def target_uri

+ 1
- 0
app/lib/exceptions.rb View File

@ -4,6 +4,7 @@ module Mastodon
class Error < StandardError; end
class NotPermittedError < Error; end
class ValidationError < Error; end
class HostValidationError < ValidationError; end
class RaceConditionError < Error; end
class UnexpectedResponseError < Error

+ 18
- 1
app/lib/request.rb View File

@ -1,5 +1,8 @@
# frozen_string_literal: true
require 'ipaddr'
require 'socket'
class Request
REQUEST_TARGET = '(request-target)'
@ -8,7 +11,7 @@ class Request
def initialize(verb, url, **options)
@verb = verb
@url = Addressable::URI.parse(url).normalize
@options = options
@options = options.merge(socket_class: Socket)
@headers = {}
set_common_headers!
@ -87,4 +90,18 @@ class Request
def http_client
HTTP.timeout(:per_operation, timeout).follow(max_hops: 2)
end
class Socket < TCPSocket
class << self
def open(host, *args)
address = IPSocket.getaddress(host)
raise Mastodon::HostValidationError if PrivateAddressCheck.private_address? IPAddr.new(address)
super address, *args
end
alias new open
end
end
private_constant :Socket
end

+ 11
- 0
app/lib/sidekiq_error_handler.rb View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class SidekiqErrorHandler
def call(*)
yield
rescue Mastodon::HostValidationError => e
Rails.logger.error "#{e.class}: #{e.message}"
Rails.logger.error e.backtrace.join("\n")
# Do not retry
end
end

+ 9
- 0
app/models/concerns/paginable.rb View File

@ -10,5 +10,14 @@ module Paginable
query = query.where(arel_table[:id].gt(since_id)) if since_id.present?
query
}
# Differs from :paginate_by_max_id in that it gives the results immediately following min_id,
# whereas since_id gives the items with largest id, but with since_id as a cutoff.
# Results will be in ascending order by id.
scope :paginate_by_min_id, ->(limit, min_id = nil) {
query = reorder(arel_table[:id]).limit(limit)
query = query.where(arel_table[:id].gt(min_id)) if min_id.present?
query
}
end
end

+ 1
- 1
app/models/import.rb View File

@ -26,7 +26,7 @@ class Import < ApplicationRecord
validates :type, presence: true
has_attached_file :data, url: '/system/:hash.:extension', hash_secret: ENV['PAPERCLIP_SECRET']
has_attached_file :data
validates_attachment_content_type :data, content_type: FILE_TYPES
validates_attachment_presence :data
end

+ 4
- 0
app/models/report.rb View File

@ -24,6 +24,10 @@ class Report < ApplicationRecord
validates :comment, length: { maximum: 1000 }
def object_type
:flag
end
def statuses
Status.where(id: status_ids).includes(:account, :media_attachments, :mentions)
end

+ 21
- 5
app/models/user.rb View File

@ -44,7 +44,7 @@ class User < ApplicationRecord
ACTIVE_DURATION = 14.days
devise :two_factor_authenticatable,
otp_secret_encryption_key: ENV['OTP_SECRET']
otp_secret_encryption_key: ENV.fetch('OTP_SECRET')
devise :two_factor_backupable,
otp_number_of_backup_codes: 10
@ -52,7 +52,6 @@ class User < ApplicationRecord
devise :registerable, :recoverable, :rememberable, :trackable, :validatable,
:confirmable
devise :pam_authenticatable if Devise.pam_authentication
devise :omniauthable
belongs_to :account, inverse_of: :user
@ -117,6 +116,12 @@ class User < ApplicationRecord
acc.destroy! unless save
end
def ldap_setup(_attributes)
self.confirmed_at = Time.now.utc
self.admin = false
save!
end
def confirmed?
confirmed_at.present?
end
@ -247,17 +252,17 @@ class User < ApplicationRecord
end
def password_required?
return false if Devise.pam_authentication
return false if Devise.pam_authentication || Devise.ldap_authentication
super
end
def send_reset_password_instructions
return false if encrypted_password.blank? && Devise.pam_authentication
return false if encrypted_password.blank? && (Devise.pam_authentication || Devise.ldap_authentication)
super
end
def reset_password!(new_password, new_password_confirmation)
return false if encrypted_password.blank? && Devise.pam_authentication
return false if encrypted_password.blank? && (Devise.pam_authentication || Devise.ldap_authentication)
super
end
@ -280,6 +285,17 @@ class User < ApplicationRecord
end
end
def self.ldap_get_user(attributes = {})
resource = joins(:account).find_by(accounts: { username: attributes[Devise.ldap_uid.to_sym].first })
if resource.blank?
resource = new(email: attributes[:mail].first, account_attributes: { username: attributes[Devise.ldap_uid.to_sym].first })
resource.ldap_setup(attributes)
end
resource
end
def self.authenticate_with_pam(attributes = {})
return nil unless Devise.pam_authentication
super

+ 27
- 0
app/serializers/activitypub/flag_serializer.rb View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class ActivityPub::FlagSerializer < ActiveModel::Serializer
attributes :id, :type, :actor, :content
attribute :virtual_object, key: :object
def id
# This is nil for now
ActivityPub::TagManager.instance.uri_for(object)
end
def type
'Flag'
end
def actor
ActivityPub::TagManager.instance.uri_for(instance_options[:account] || object.account)
end
def virtual_object
[ActivityPub::TagManager.instance.uri_for(object.target_account)] + object.statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
end
def content
object.comment
end
end

+ 1
- 0
app/serializers/initial_state_serializer.rb View File

@ -22,6 +22,7 @@ class InitialStateSerializer < ActiveModel::Serializer
locale: I18n.locale,
domain: Rails.configuration.x.local_domain,
admin: object.admin&.id&.to_s,
search_enabled: Chewy.enabled?,
}
if object.current_account

+ 10
- 1
app/serializers/rest/instance_serializer.rb View File

@ -4,7 +4,12 @@ class REST::InstanceSerializer < ActiveModel::Serializer
include RoutingHelper
attributes :uri, :title, :description, :email,
:version, :urls, :stats, :thumbnail, :max_toot_chars
:version, :urls, :stats, :thumbnail, :max_toot_chars,
:languages
has_one :contact_account, serializer: REST::AccountSerializer
delegate :contact_account, to: :instance_presenter
def uri
Rails.configuration.x.local_domain
@ -46,6 +51,10 @@ class REST::InstanceSerializer < ActiveModel::Serializer
{ streaming_api: Rails.configuration.x.streaming_api_base_url }
end
def languages
[ENV.fetch('DEFAULT_LOCALE', I18n.default_locale)]
end
private
def instance_presenter

+ 54
- 0
app/services/report_service.rb View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
class ReportService < BaseService
def call(source_account, target_account, options = {})
@source_account = source_account
@target_account = target_account
@status_ids = options.delete(:status_ids) || []
@comment = options.delete(:comment) || ''
@options = options
create_report!
notify_staff!
forward_to_origin! if !@target_account.local? && ActiveModel::Type::Boolean.new.cast(@options[:forward])
@report
end
private
def create_report!
@report = @source_account.reports.create!(
target_account: @target_account,
status_ids: @status_ids,
comment: @comment
)
end
def notify_staff!
User.staff.includes(:account).each do |u|
AdminMailer.new_report(u.account, @report).deliver_later
end
end
def forward_to_origin!
ActivityPub::DeliveryWorker.perform_async(
payload,
some_local_account.id,
@target_account.inbox_url
)
end
def payload
Oj.dump(ActiveModelSerializers::SerializableResource.new(
@report,
serializer: ActivityPub::FlagSerializer,
adapter: ActivityPub::Adapter,
account: some_local_account
).as_json)
end
def some_local_account
@some_local_account ||= Account.local.where(suspended: false).first
end
end

+ 101
- 47
app/views/about/show.html.haml View File

@ -7,51 +7,100 @@
.landing-page.alternative
.container
.row
.column-4.hide-sm.show-xs.show-m
.landing-page__forms
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
.hide-xs
.grid
.column-0
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
- if Setting.timeline_preview
.column-1
.landing-page__forms
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
= render 'forms'
.column-7.column-9-sm
.landing-page__hero
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title
- else
.column-1.non-preview
.landing-page__forms
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
.landing-page__information
.landing-page__short-description
= render 'forms'
- if Setting.timeline_preview
.column-2
.landing-page__hero
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title
.landing-page__information
.landing-page__short-description
.row
.landing-page__logo
= image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon'
%h1
= @instance_presenter.site_title
%small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname)
%p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
.landing-page__call-to-action
.row
.landing-page__logo.hide-xs
= image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon'
.row__information-board
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.row__mascot
.landing-page__mascot
= image_tag asset_pack_path('elephant_ui_plane.svg')
%h1
= @instance_presenter.site_title
%small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname)
- else
.column-2.non-preview
.landing-page__hero
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('preview.jpg'), alt: @instance_presenter.site_title
%p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
.landing-page__information
.landing-page__short-description
.row
.landing-page__logo
= image_tag asset_pack_path('logo_transparent.svg'), alt: 'Mastodon'
.show-xs
.landing-page__forms
= render 'forms'
.landing-page__call-to-action.hide-xs
.row
.column-5
.landing-page__mascot
= image_tag asset_pack_path('elephant_ui_plane.svg')
.column-5
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.column-5
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.landing-page__information
%h1
= @instance_presenter.site_title
%small!= t 'about.hosted_on', domain: content_tag(:span, site_hostname)
%p= @instance_presenter.site_description.html_safe.presence || t('about.generic_description', domain: site_hostname)
.landing-page__call-to-action
.row
.row__information-board
.information-board__section
%span= t 'about.user_count_before'
%strong= number_with_delimiter @instance_presenter.user_count
%span= t 'about.user_count_after'
.information-board__section
%span= t 'about.status_count_before'
%strong= number_with_delimiter @instance_presenter.status_count
%span= t 'about.status_count_after'
.row__mascot
.landing-page__mascot
= image_tag asset_pack_path('elephant_ui_plane.svg')
- if Setting.timeline_preview
.column-3
#mastodon-timeline{ data: { props: Oj.dump(default_props) } }
- if Setting.timeline_preview
.column-4.landing-page__information
.landing-page__features
%h3= t 'about.what_is_mastodon'
%p= t 'about.about_mastodon_html'
@ -66,13 +115,18 @@
= link_to t('about.source_code'), @instance_presenter.source_url
= " (#{@instance_presenter.version_number})"
.column-4.column-6-sm.column-flex
.show-sm.hide-xs
.landing-page__forms
.brand
= link_to root_url do
= image_tag asset_pack_path('logo_full.svg'), alt: 'Mastodon'
- else
.column-4.non-preview.landing-page__information
.landing-page__features
%h3= t 'about.what_is_mastodon'
%p= t 'about.about_mastodon_html'
= render 'forms'
- if Setting.timeline_preview
#mastodon-timeline{ data: { props: Oj.dump(default_props) } }
= render 'features'
.landing-page__features__action
= link_to t('about.learn_more'), 'https://joinmastodon.org/', class: 'button button-alternative'
.landing-page__footer
%p
= link_to t('about.source_code'), @instance_presenter.source_url
= " (#{@instance_presenter.version_number})"

+ 23
- 0
app/views/accounts/_follow_button.html.haml View File

@ -0,0 +1,23 @@
- relationships ||= nil
- unless account.memorial? || account.moved?
- if user_signed_in?
- requested = relationships ? relationships.requested[account.id].present? : current_account.requested?(account)
- following = relationships ? relationships.following[account.id].present? : current_account.following?(account)
- if user_signed_in? && current_account.id != account.id && !requested
.controls
- if following
= link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-times'
= t('accounts.unfollow')
- else
= link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.follow')
- elsif !user_signed_in?
.controls
.remote-follow
= link_to account_remote_follow_path(account), class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.remote_follow')

+ 5
- 2
app/views/accounts/_grid_card.html.haml View File

@ -1,9 +1,12 @@
.account-grid-card
.account-grid-card__header{ style: "background-image: url(#{account.header.url(:original)})" }
= render 'accounts/follow_button', account: account, relationships: @relationships
.account-grid-card__avatar
.avatar= image_tag account.avatar.url(:original)
.name
= link_to TagManager.instance.url_for(account) do
%span.display_name.emojify= display_name(account)
%span.username @#{account.acct}
%p.note.emojify= truncate(strip_tags(account.note), length: 150)
%span.username
@#{account.local? ? account.local_username_and_domain : account.acct}
= fa_icon('lock') if account.locked?
.account__header__content.p-note.emojify= Formatter.instance.simplified_format(account)

+ 1
- 18
app/views/accounts/_header.html.haml View File

@ -1,24 +1,7 @@
- processed_bio = FrontmatterHandler.instance.process_bio Formatter.instance.simplified_format account
.card.h-card.p-author{ style: "background-image: url(#{account.header.url(:original)})" }
.card__illustration
- unless account.memorial? || account.moved?
- if user_signed_in? && current_account.id != account.id && !current_account.requested?(account)
.controls
- if current_account.following?(account)
= link_to account_unfollow_path(account), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-times'
= t('accounts.unfollow')
- else
= link_to account_follow_path(account), data: { method: :post }, class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.follow')
- elsif !user_signed_in?
.controls
.remote-follow
= link_to account_remote_follow_path(account), class: 'icon-button' do
= fa_icon 'user-plus'
= t('accounts.remote_follow')
= render 'accounts/follow_button', account: account
.avatar= image_tag account.avatar.url(:original), class: 'u-photo'
.card__bio

+ 5
- 2
app/views/accounts/show.html.haml View File

@ -39,6 +39,9 @@
= render partial: 'stream_entries/status', collection: @statuses, as: :status
- if @statuses.size == 20
- if @newer_url || @older_url
.pagination
= link_to safe_join([t('pagination.next'), fa_icon('chevron-right')], ' '), @next_url, class: 'next', rel: 'next'
- if @older_url
= link_to safe_join([fa_icon('chevron-left'), t('pagination.older')], ' '), @older_url, class: 'older', rel: 'older'
- if @newer_url
= link_to safe_join([t('pagination.newer'), fa_icon('chevron-right')], ' '), @newer_url, class: 'newer', rel: 'newer'

+ 2
- 2
app/views/auth/passwords/edit.html.haml View File

@ -4,7 +4,7 @@
= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f|
= render 'shared/error_messages', object: resource
- if !use_pam? || resource.encrypted_password.present?
- if !use_seamless_external_login?? || resource.encrypted_password.present?
= f.input :reset_password_token, as: :hidden
= f.input :password, autofocus: true, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }
@ -13,6 +13,6 @@
.actions
= f.button :button, t('auth.set_new_password'), type: :submit
- else
= t('simple_form.labels.defaults.pam_account')
%p.hint= t('users.seamless_external_login')
.form-footer= render 'auth/shared/links'

+ 2
- 2
app/views/auth/registrations/edit.html.haml View File

@ -4,7 +4,7 @@
= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, class: 'auth_edit' }) do |f|
= render 'shared/error_messages', object: resource
- if !use_pam? || resource.encrypted_password.present?
- if !use_seamless_external_login? || resource.encrypted_password.present?
= f.input :email, placeholder: t('simple_form.labels.defaults.email'), input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
= f.input :password, placeholder: t('simple_form.labels.defaults.new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.new_password'), :autocomplete => 'off' }
= f.input :password_confirmation, placeholder: t('simple_form.labels.defaults.confirm_new_password'), input_html: { 'aria-label' => t('simple_form.labels.defaults.confirm_new_password'), :autocomplete => 'off' }
@ -13,7 +13,7 @@
.actions
= f.button :button, t('generic.save_changes'), type: :submit
- else
= t('simple_form.labels.defaults.pam_account')
%p.hint= t('users.seamless_external_login')
%hr/

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

Loading…
Cancel
Save