mirror of
https://github.com/glitch-soc/mastodon.git
synced 2026-03-29 19:21:36 +02:00
Compare commits
106 Commits
flavour-ur
...
list-filte
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f8819e8a5 | ||
|
|
40afadfb01 | ||
|
|
a29432f0cd | ||
|
|
e0a573a2ce | ||
|
|
e9a5bde9a0 | ||
|
|
61ed5b972c | ||
|
|
37254c4f5d | ||
|
|
098c7d27fe | ||
|
|
3d3b403359 | ||
|
|
25b0d7538e | ||
|
|
a3b2ea599d | ||
|
|
573414f728 | ||
|
|
aa273a2718 | ||
|
|
e5a9831a56 | ||
|
|
0d3ffa691e | ||
|
|
5ad45552b3 | ||
|
|
dc313f27bb | ||
|
|
10f800ab46 | ||
|
|
7cad926401 | ||
|
|
3487460f00 | ||
|
|
82236a3703 | ||
|
|
72314d26ae | ||
|
|
cc75d47926 | ||
|
|
8bf4cc72b6 | ||
|
|
ad941f5a21 | ||
|
|
0aeec0390b | ||
|
|
fef6625496 | ||
|
|
775c3056b6 | ||
|
|
ccf4f170de | ||
|
|
90e7da16a0 | ||
|
|
ad75ec8b5b | ||
|
|
57fcc21a86 | ||
|
|
6855baa0c5 | ||
|
|
07b4427865 | ||
|
|
a8deb6648b | ||
|
|
20a6584d2d | ||
|
|
155e211dd0 | ||
|
|
81923f88ba | ||
|
|
5706fe18c2 | ||
|
|
71965cbef2 | ||
|
|
0128b86d30 | ||
|
|
0370ba7b0a | ||
|
|
c986218c3a | ||
|
|
0c8b1eb577 | ||
|
|
cfa3f55221 | ||
|
|
f9f6918148 | ||
|
|
65d083338d | ||
|
|
2a61b9f000 | ||
|
|
cfea28216f | ||
|
|
19257d91bf | ||
|
|
fe180f18ff | ||
|
|
1486fd64cc | ||
|
|
504c3d650f | ||
|
|
be33247235 | ||
|
|
a057ed5cfe | ||
|
|
b93ad3d0e8 | ||
|
|
c0c4526283 | ||
|
|
04eaa1943f | ||
|
|
c95af71da5 | ||
|
|
14c4a33cd9 | ||
|
|
30d2ea03b0 | ||
|
|
1356ed72cd | ||
|
|
481fac7c84 | ||
|
|
0a52e37648 | ||
|
|
44992df257 | ||
|
|
c588fcf4bc | ||
|
|
8aa527434c | ||
|
|
7d024a6b68 | ||
|
|
d8206d1931 | ||
|
|
771b950feb | ||
|
|
feed07227b | ||
|
|
0cd5f2a61f | ||
|
|
e56323a4dd | ||
|
|
204688e803 | ||
|
|
9d5ecdbf41 | ||
|
|
ed7231947c | ||
|
|
bdca1614d5 | ||
|
|
dabf66e676 | ||
|
|
84d5bfb35e | ||
|
|
6a82939adb | ||
|
|
98aa96b8d6 | ||
|
|
3caec1ecc2 | ||
|
|
2950de86c6 | ||
|
|
7d4ebeecbd | ||
|
|
6e3f176b8e | ||
|
|
a4710f9af8 | ||
|
|
fcc0795a40 | ||
|
|
0f8140d26a | ||
|
|
e7d55df38d | ||
|
|
a72d03f43c | ||
|
|
4bce376fdc | ||
|
|
a865b62efc | ||
|
|
84cebad49d | ||
|
|
931e66e572 | ||
|
|
cdae7e4c8b | ||
|
|
3a52c90de1 | ||
|
|
17e26f8afe | ||
|
|
2526ef10c2 | ||
|
|
99242b92bc | ||
|
|
ec3b449baa | ||
|
|
2f4c5f504f | ||
|
|
f08e6e9ab5 | ||
|
|
86b4d5439c | ||
|
|
c36b9cc5a6 | ||
|
|
70ce2a2095 | ||
|
|
b0db4dad79 |
0
CODEOWNERS → .github/CODEOWNERS
vendored
0
CODEOWNERS → .github/CODEOWNERS
vendored
3
Gemfile
3
Gemfile
@@ -14,12 +14,13 @@ gem 'pg', '~> 0.20'
|
||||
gem 'pghero', '~> 1.7'
|
||||
gem 'dotenv-rails', '~> 2.2'
|
||||
|
||||
gem 'fog-aws', '~> 1.4', require: false
|
||||
gem 'aws-sdk', '~> 2.10', require: false
|
||||
gem 'fog-core', '~> 1.45'
|
||||
gem 'fog-local', '~> 0.4', require: false
|
||||
gem 'fog-openstack', '~> 0.1', require: false
|
||||
gem 'paperclip', '~> 5.1'
|
||||
gem 'paperclip-av-transcoder', '~> 0.6'
|
||||
gem 'posix-spawn'
|
||||
|
||||
gem 'active_model_serializers', '~> 0.10'
|
||||
gem 'addressable', '~> 2.5'
|
||||
|
||||
21
Gemfile.lock
21
Gemfile.lock
@@ -57,6 +57,14 @@ GEM
|
||||
encryptor (~> 3.0.0)
|
||||
av (0.9.0)
|
||||
cocaine (~> 0.5.3)
|
||||
aws-sdk (2.10.100)
|
||||
aws-sdk-resources (= 2.10.100)
|
||||
aws-sdk-core (2.10.100)
|
||||
aws-sigv4 (~> 1.0)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-resources (2.10.100)
|
||||
aws-sdk-core (= 2.10.100)
|
||||
aws-sigv4 (1.0.2)
|
||||
bcrypt (3.1.11)
|
||||
better_errors (2.4.0)
|
||||
coderay (>= 1.0.0)
|
||||
@@ -152,11 +160,6 @@ GEM
|
||||
i18n (~> 0.5)
|
||||
fast_blank (1.0.0)
|
||||
ffi (1.9.18)
|
||||
fog-aws (1.4.1)
|
||||
fog-core (~> 1.38)
|
||||
fog-json (~> 1.0)
|
||||
fog-xml (~> 0.1)
|
||||
ipaddress (~> 0.8)
|
||||
fog-core (1.45.0)
|
||||
builder
|
||||
excon (~> 0.58)
|
||||
@@ -170,9 +173,6 @@ GEM
|
||||
fog-core (>= 1.40)
|
||||
fog-json (>= 1.0)
|
||||
ipaddress (>= 0.8)
|
||||
fog-xml (0.1.3)
|
||||
fog-core
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
formatador (0.2.5)
|
||||
fuubar (2.2.0)
|
||||
rspec-core (~> 3.0)
|
||||
@@ -228,6 +228,7 @@ GEM
|
||||
idn-ruby (0.1.0)
|
||||
ipaddress (0.8.3)
|
||||
iso-639 (0.2.8)
|
||||
jmespath (1.3.1)
|
||||
json (2.1.0)
|
||||
json-ld (2.1.7)
|
||||
multi_json (~> 1.12)
|
||||
@@ -324,6 +325,7 @@ GEM
|
||||
pghero (1.7.0)
|
||||
activerecord
|
||||
pkg-config (1.2.8)
|
||||
posix-spawn (0.3.13)
|
||||
powerpack (0.1.1)
|
||||
pry (0.11.3)
|
||||
coderay (~> 1.1.0)
|
||||
@@ -544,6 +546,7 @@ DEPENDENCIES
|
||||
active_record_query_trace (~> 1.5)
|
||||
addressable (~> 2.5)
|
||||
annotate (~> 2.7)
|
||||
aws-sdk (~> 2.10)
|
||||
better_errors (~> 2.4)
|
||||
binding_of_caller (~> 0.7)
|
||||
bootsnap
|
||||
@@ -566,7 +569,6 @@ DEPENDENCIES
|
||||
fabrication (~> 2.18)
|
||||
faker (~> 1.7)
|
||||
fast_blank (~> 1.0)
|
||||
fog-aws (~> 1.4)
|
||||
fog-core (~> 1.45)
|
||||
fog-local (~> 0.4)
|
||||
fog-openstack (~> 0.1)
|
||||
@@ -601,6 +603,7 @@ DEPENDENCIES
|
||||
pg (~> 0.20)
|
||||
pghero (~> 1.7)
|
||||
pkg-config (~> 1.2)
|
||||
posix-spawn
|
||||
pry-rails (~> 0.3)
|
||||
puma (~> 3.10)
|
||||
pundit (~> 1.1)
|
||||
|
||||
@@ -89,7 +89,8 @@ module Admin
|
||||
:username,
|
||||
:display_name,
|
||||
:email,
|
||||
:ip
|
||||
:ip,
|
||||
:staff
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,7 +92,9 @@ module Admin
|
||||
def filter_params
|
||||
params.permit(
|
||||
:local,
|
||||
:remote
|
||||
:remote,
|
||||
:by_domain,
|
||||
:shortcode
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -72,19 +72,4 @@ class Api::BaseController < ApplicationController
|
||||
def render_empty
|
||||
render json: {}, status: 200
|
||||
end
|
||||
|
||||
def set_maps(statuses) # rubocop:disable Style/AccessorMethodName
|
||||
if current_account.nil?
|
||||
@reblogs_map = {}
|
||||
@favourites_map = {}
|
||||
@mutes_map = {}
|
||||
return
|
||||
end
|
||||
|
||||
status_ids = statuses.compact.flat_map { |s| [s.id, s.reblog_of_id] }.uniq
|
||||
conversation_ids = statuses.compact.map(&:conversation_id).compact.uniq
|
||||
@reblogs_map = Status.reblogs_map(status_ids, current_account)
|
||||
@favourites_map = Status.favourites_map(status_ids, current_account)
|
||||
@mutes_map = Status.mutes_map(conversation_ids, current_account)
|
||||
end
|
||||
end
|
||||
|
||||
20
app/controllers/api/v1/accounts/lists_controller.rb
Normal file
20
app/controllers/api/v1/accounts/lists_controller.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::Accounts::ListsController < Api::BaseController
|
||||
before_action -> { doorkeeper_authorize! :read }
|
||||
before_action :require_user!
|
||||
before_action :set_account
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@lists = @account.lists.where(account: current_account)
|
||||
render json: @lists, each_serializer: REST::ListSerializer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_account
|
||||
@account = Account.find(params[:account_id])
|
||||
end
|
||||
end
|
||||
@@ -1,18 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::V1::ListsController < Api::BaseController
|
||||
LISTS_LIMIT = 50
|
||||
|
||||
before_action -> { doorkeeper_authorize! :read }, only: [:index, :show]
|
||||
before_action -> { doorkeeper_authorize! :write }, except: [:index, :show]
|
||||
|
||||
before_action :require_user!
|
||||
before_action :set_list, except: [:index, :create]
|
||||
|
||||
after_action :insert_pagination_headers, only: :index
|
||||
|
||||
def index
|
||||
@lists = List.where(account: current_account).paginate_by_max_id(limit_param(LISTS_LIMIT), params[:max_id], params[:since_id])
|
||||
@lists = List.where(account: current_account).all
|
||||
render json: @lists, each_serializer: REST::ListSerializer
|
||||
end
|
||||
|
||||
@@ -44,36 +40,4 @@ class Api::V1::ListsController < Api::BaseController
|
||||
def list_params
|
||||
params.permit(:title)
|
||||
end
|
||||
|
||||
def insert_pagination_headers
|
||||
set_pagination_headers(next_path, prev_path)
|
||||
end
|
||||
|
||||
def next_path
|
||||
if records_continue?
|
||||
api_v1_lists_url pagination_params(max_id: pagination_max_id)
|
||||
end
|
||||
end
|
||||
|
||||
def prev_path
|
||||
unless @lists.empty?
|
||||
api_v1_lists_url pagination_params(since_id: pagination_since_id)
|
||||
end
|
||||
end
|
||||
|
||||
def pagination_max_id
|
||||
@lists.last.id
|
||||
end
|
||||
|
||||
def pagination_since_id
|
||||
@lists.first.id
|
||||
end
|
||||
|
||||
def records_continue?
|
||||
@lists.size == limit_param(LISTS_LIMIT)
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.permit(:limit).merge(core_params)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,6 +28,8 @@ class Api::Web::PushSubscriptionsController < Api::BaseController
|
||||
},
|
||||
}
|
||||
|
||||
data.deep_merge!(params[:data]) if params[:data]
|
||||
|
||||
web_subscription = ::Web::PushSubscription.create!(
|
||||
endpoint: params[:subscription][:endpoint],
|
||||
key_p256dh: params[:subscription][:keys][:p256dh],
|
||||
|
||||
@@ -44,7 +44,8 @@ module RateLimitHeaders
|
||||
end
|
||||
|
||||
def api_throttle_data
|
||||
request.env['rack.attack.throttle_data']['api']
|
||||
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
|
||||
request.env['rack.attack.throttle_data'][most_limited_type]
|
||||
end
|
||||
|
||||
def request_time
|
||||
|
||||
@@ -5,6 +5,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
||||
|
||||
before_action :store_current_location
|
||||
before_action :authenticate_resource_owner!
|
||||
before_action :set_pack
|
||||
|
||||
include Localized
|
||||
|
||||
@@ -13,4 +14,8 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
|
||||
def store_current_location
|
||||
store_location_for(:user, request.url)
|
||||
end
|
||||
|
||||
def set_pack
|
||||
use_pack 'auth'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||
|
||||
before_action :store_current_location
|
||||
before_action :authenticate_resource_owner!
|
||||
before_action :set_pack
|
||||
|
||||
include Localized
|
||||
|
||||
@@ -13,4 +14,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
|
||||
def store_current_location
|
||||
store_location_for(:user, request.url)
|
||||
end
|
||||
|
||||
def set_pack
|
||||
use_pack 'settings'
|
||||
end
|
||||
end
|
||||
|
||||
35
app/controllers/settings/flavours_controller.rb
Normal file
35
app/controllers/settings/flavours_controller.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Settings::FlavoursController < Settings::BaseController
|
||||
|
||||
def index
|
||||
redirect_to action: 'show', flavour: current_flavour
|
||||
end
|
||||
|
||||
def show
|
||||
unless Themes.instance.flavours.include?(params[:flavour]) or params[:flavour] == current_flavour
|
||||
redirect_to action: 'show', flavour: current_flavour
|
||||
end
|
||||
|
||||
@listing = Themes.instance.flavours
|
||||
@selected = params[:flavour]
|
||||
end
|
||||
|
||||
def update
|
||||
user_settings.update(user_settings_params(params[:flavour]).to_h)
|
||||
redirect_to action: 'show', flavour: params[:flavour]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_settings
|
||||
UserSettingsDecorator.new(current_user)
|
||||
end
|
||||
|
||||
def user_settings_params(flavour)
|
||||
params.require(:user).merge({ setting_flavour: flavour }).permit(
|
||||
:setting_flavour,
|
||||
:setting_skin
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -28,6 +28,7 @@ class Settings::MigrationsController < ApplicationController
|
||||
end
|
||||
|
||||
def migration_account_changed?
|
||||
current_account.moved_to_account_id != @migration.account&.id
|
||||
current_account.moved_to_account_id != @migration.account&.id &&
|
||||
current_account.id != @migration.account&.id
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,8 +39,6 @@ class Settings::PreferencesController < Settings::BaseController
|
||||
:setting_reduce_motion,
|
||||
:setting_system_font_ui,
|
||||
:setting_noindex,
|
||||
:setting_flavour,
|
||||
:setting_skin,
|
||||
notification_emails: %i(follow follow_request reblog favourite mention digest),
|
||||
interactions: %i(must_be_follower must_be_following)
|
||||
)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin::FilterHelper
|
||||
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip).freeze
|
||||
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
|
||||
INVITE_FILTER = %i(available expired).freeze
|
||||
ACCOUNT_FILTERS = %i(local remote by_domain silenced suspended recent username display_name email ip staff).freeze
|
||||
REPORT_FILTERS = %i(resolved account_id target_account_id).freeze
|
||||
INVITE_FILTER = %i(available expired).freeze
|
||||
CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
|
||||
|
||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER
|
||||
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS
|
||||
|
||||
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
|
||||
new_url = filtered_url_for(link_to_params)
|
||||
|
||||
@@ -10,6 +10,7 @@ module SettingsHelper
|
||||
eo: 'Esperanto',
|
||||
es: 'Español',
|
||||
fa: 'فارسی',
|
||||
gl: 'Galego',
|
||||
fi: 'Suomi',
|
||||
fr: 'Français',
|
||||
he: 'עברית',
|
||||
|
||||
@@ -37,7 +37,3 @@ delegate(document, '#account_header', 'change', ({ target }) => {
|
||||
|
||||
header.style.backgroundImage = `url(${url})`;
|
||||
});
|
||||
|
||||
delegate(document, '#user_setting_flavour, #user_setting_skin', 'change', ({ target }) => {
|
||||
target.form.submit();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import SettingToggle from 'flavours/glitch/features/notifications/components/setting_toggle';
|
||||
import SettingText from 'flavours/glitch/components/setting_text';
|
||||
|
||||
const messages = defineMessages({
|
||||
filter_regex: { id: 'list_timeline.column_settings.filter_regex', defaultMessage: 'Filter out by regular expressions' },
|
||||
settings: { id: 'list_timeline.settings', defaultMessage: 'Column settings' },
|
||||
});
|
||||
|
||||
@injectIntl
|
||||
export default class ColumnSettings extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { settings, onChange, intl } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<span className='column-settings__section'><FormattedMessage id='list_timeline.column_settings.basic' defaultMessage='Basic' /></span>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<SettingToggle prefix='list_timeline' settings={settings} settingKey={['shows', 'reblog']} onChange={onChange} label={<FormattedMessage id='list_timeline.column_settings.show_reblogs' defaultMessage='Show boosts' />} />
|
||||
</div>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<SettingToggle prefix='list_timeline' settings={settings} settingKey={['shows', 'reply']} onChange={onChange} label={<FormattedMessage id='list_timeline.column_settings.show_replies' defaultMessage='Show replies' />} />
|
||||
</div>
|
||||
|
||||
<span className='column-settings__section'><FormattedMessage id='list_timeline.column_settings.advanced' defaultMessage='Advanced' /></span>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<SettingText prefix='list_timeline' settings={settings} settingKey={['regex', 'body']} onChange={onChange} label={intl.formatMessage(messages.filter_regex)} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ColumnSettings from '../components/column_settings';
|
||||
import { changeSetting, saveSettings } from 'flavours/glitch/actions/settings';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
settings: state.getIn(['settings', 'list_timeline']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
||||
onChange (key, checked) {
|
||||
dispatch(changeSetting(['list_timeline', ...key], checked));
|
||||
},
|
||||
|
||||
onSave () {
|
||||
dispatch(saveSettings());
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ColumnSettings);
|
||||
@@ -13,6 +13,7 @@ import { fetchList, deleteList } from 'flavours/glitch/actions/lists';
|
||||
import { openModal } from 'flavours/glitch/actions/modal';
|
||||
import MissingIndicator from 'flavours/glitch/components/missing_indicator';
|
||||
import LoadingIndicator from 'flavours/glitch/components/loading_indicator';
|
||||
import ColumnSettingsContainer from './containers/column_settings_container';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||
@@ -143,6 +144,7 @@ export default class ListTimeline extends React.PureComponent {
|
||||
pinned={pinned}
|
||||
multiColumn={multiColumn}
|
||||
>
|
||||
<ColumnSettingsContainer />
|
||||
<div className='column-header__links'>
|
||||
<button className='text-btn column-header__setting-btn' tabIndex='0' onClick={this.handleEditClick}>
|
||||
<i className='fa fa-pencil' /> <FormattedMessage id='lists.edit' defaultMessage='Edit list' />
|
||||
|
||||
BIN
app/javascript/flavours/glitch/images/glitch-preview.jpg
Normal file
BIN
app/javascript/flavours/glitch/images/glitch-preview.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 193 KiB |
@@ -23,11 +23,11 @@ const messages = {
|
||||
'settings.enable_collapsed': 'トゥート折りたたみを有効にする',
|
||||
'settings.general': '一般',
|
||||
'settings.image_backgrounds': '画像背景',
|
||||
'settings.image_backgrounds_media': '折りたまれたメディア付きテゥートをプレビュー',
|
||||
'settings.image_backgrounds_media': '折りたまれたメディア付きトゥートをプレビュー',
|
||||
'settings.image_backgrounds_users': '折りたまれたトゥートの背景を変更する',
|
||||
'settings.media': 'メディア',
|
||||
'settings.media_letterbox': 'メディアをレターボックス式で表示',
|
||||
'settings.media_fullwidth': '全幅メディアプリビュー',
|
||||
'settings.media_fullwidth': '全幅メディアプレビュー',
|
||||
'settings.preferences': 'ユーザー設定',
|
||||
'settings.wide_view': 'ワイドビュー(Desktopレイアウトのみ)',
|
||||
'settings.navbar_under': 'ナビを画面下部に移動させる(Mobileレイアウトのみ)',
|
||||
@@ -37,6 +37,10 @@ const messages = {
|
||||
'status.collapse': '折りたたむ',
|
||||
'status.uncollapse': '折りたたみを解除',
|
||||
|
||||
'favourite_modal.combo': '次からは {combo} を押せば、これをスキップできます。',
|
||||
|
||||
'home.column_settings.show_direct': 'DMを表示',
|
||||
|
||||
'notification.markForDeletion': '選択',
|
||||
'notifications.clear': '通知を全てクリアする',
|
||||
'notifications.marked_clear_confirmation': '削除した全ての通知を完全に削除してもよろしいですか?',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
en:
|
||||
flavours:
|
||||
glitch: Glitch Edition
|
||||
glitch:
|
||||
description: The default flavour for GlitchSoc instances.
|
||||
name: Glitch Edition
|
||||
skins:
|
||||
glitch:
|
||||
default: Default
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
import 'flavours/glitch/styles/index.scss';
|
||||
|
||||
// This ensures that webpack compiles our images.
|
||||
require.context('../images', true);
|
||||
|
||||
@@ -14,6 +14,17 @@ const initialState = ImmutableMap({
|
||||
|
||||
skinTone: 1,
|
||||
|
||||
list_timeline: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
reblog: true,
|
||||
reply: true,
|
||||
}),
|
||||
|
||||
regex: ImmutableMap({
|
||||
body: '',
|
||||
}),
|
||||
}),
|
||||
|
||||
home: ImmutableMap({
|
||||
shows: ImmutableMap({
|
||||
reblog: true,
|
||||
|
||||
@@ -246,6 +246,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.flavour-screen {
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.flavour-description {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
margin: 10px 0;
|
||||
|
||||
& > p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.report-accounts {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -2286,7 +2286,6 @@
|
||||
.getting-started {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 235px;
|
||||
background: url('~images/mastodon-getting-started.png') no-repeat 0 100%;
|
||||
flex: 1 0 auto;
|
||||
|
||||
p {
|
||||
|
||||
@@ -26,6 +26,12 @@ pack:
|
||||
# language tags and whose default exports are a messages object.
|
||||
locales: locales
|
||||
|
||||
# (OPTIONAL) A file to use as the preview screenshot for the flavour,
|
||||
# or an array thereof. These filenames must be unique across all
|
||||
# images (regardless of path), so it's a good idea to namespace them
|
||||
# to your theme. It's up to you to let webpack know to compile them.
|
||||
screenshot: glitch-preview.jpg
|
||||
|
||||
# (OPTIONAL) The directory which contains the pack files.
|
||||
# Defaults to the theme directory (`app/javascript/themes/[theme]`),
|
||||
# which should be sufficient for like 99% of use-cases lol.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
en:
|
||||
flavours:
|
||||
vanilla: Vanilla Mastodon
|
||||
vanilla:
|
||||
description: The theme used by vanilla Mastodon instances. This theme might not support all of the features of GlitchSoc.
|
||||
name: Vanilla Mastodon
|
||||
skins:
|
||||
vanilla:
|
||||
default: Default
|
||||
|
||||
@@ -24,6 +24,12 @@ pack:
|
||||
# the flavour, relative to this directory.
|
||||
locales: ../../mastodon/locales
|
||||
|
||||
# (OPTIONAL) A file to use as the preview screenshot for the flavour,
|
||||
# or an array thereof. These filenames must be unique across all
|
||||
# images (regardless of path), so it's a good idea to namespace them
|
||||
# to your theme. It's up to you to let webpack know to compile them.
|
||||
screenshot: screenshot.jpg
|
||||
|
||||
# (OPTIONAL) The directory which contains the pack files.
|
||||
# Defaults to this directory (`app/javascript/flavour/[flavour]`),
|
||||
# but in the case of the vanilla Mastodon flavour the pack files are
|
||||
|
||||
BIN
app/javascript/images/screenshot.jpg
Normal file
BIN
app/javascript/images/screenshot.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 234 KiB |
@@ -10,6 +10,10 @@ export const FAVOURITED_STATUSES_EXPAND_FAIL = 'FAVOURITED_STATUSES_EXPAND_FA
|
||||
|
||||
export function fetchFavouritedStatuses() {
|
||||
return (dispatch, getState) => {
|
||||
if (getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(fetchFavouritedStatusesRequest());
|
||||
|
||||
api(getState).get('/api/v1/favourites').then(response => {
|
||||
@@ -46,7 +50,7 @@ export function expandFavouritedStatuses() {
|
||||
return (dispatch, getState) => {
|
||||
const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
|
||||
|
||||
if (url === null) {
|
||||
if (url === null || getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import { pushNotificationsSetting } from '../settings';
|
||||
|
||||
export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
|
||||
export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
|
||||
@@ -42,11 +43,15 @@ export function saveSettings() {
|
||||
const state = getState().get('push_notifications');
|
||||
const subscription = state.get('subscription');
|
||||
const alerts = state.get('alerts');
|
||||
const data = { alerts };
|
||||
|
||||
axios.put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
|
||||
data: {
|
||||
alerts,
|
||||
},
|
||||
data,
|
||||
}).then(() => {
|
||||
const me = getState().getIn(['meta', 'me']);
|
||||
if (me) {
|
||||
pushNotificationsSetting.set(me, data);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { autoPlayGif } from '../initial_state';
|
||||
|
||||
export default class Avatar extends React.PureComponent {
|
||||
|
||||
@@ -8,12 +9,12 @@ export default class Avatar extends React.PureComponent {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
size: PropTypes.number.isRequired,
|
||||
style: PropTypes.object,
|
||||
animate: PropTypes.bool,
|
||||
inline: PropTypes.bool,
|
||||
animate: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
animate: false,
|
||||
animate: autoPlayGif,
|
||||
size: 20,
|
||||
inline: false,
|
||||
};
|
||||
|
||||
@@ -1,22 +1,29 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { autoPlayGif } from '../initial_state';
|
||||
|
||||
export default class AvatarOverlay extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
friend: ImmutablePropTypes.map.isRequired,
|
||||
animate: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
animate: autoPlayGif,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { account, friend } = this.props;
|
||||
const { account, friend, animate } = this.props;
|
||||
|
||||
const baseStyle = {
|
||||
backgroundImage: `url(${account.get('avatar_static')})`,
|
||||
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
|
||||
};
|
||||
|
||||
const overlayStyle = {
|
||||
backgroundImage: `url(${friend.get('avatar_static')})`,
|
||||
backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -156,6 +156,8 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<div className='compose-form'>
|
||||
<WarningContainer />
|
||||
|
||||
<Collapsable isVisible={this.props.spoiler} fullHeight={50}>
|
||||
<div className='spoiler-input'>
|
||||
<label>
|
||||
@@ -165,8 +167,6 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||
</div>
|
||||
</Collapsable>
|
||||
|
||||
<WarningContainer />
|
||||
|
||||
<ReplyIndicatorContainer />
|
||||
|
||||
<div className='compose-form__autosuggest-wrapper'>
|
||||
@@ -199,11 +199,11 @@ export default class ComposeForm extends ImmutablePureComponent {
|
||||
<SensitiveButtonContainer />
|
||||
<SpoilerButtonContainer />
|
||||
</div>
|
||||
<div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div>
|
||||
</div>
|
||||
|
||||
<div className='compose-form__publish'>
|
||||
<div className='character-counter__wrapper'><CharacterCounter max={500} text={text} /></div>
|
||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0)} block /></div>
|
||||
</div>
|
||||
<div className='compose-form__publish'>
|
||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabled || this.props.is_uploading || length(text) > 500 || (text.length !== 0 && text.trim().length === 0)} block /></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import IconButton from '../../../components/icon_button';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { isRtl } from '../../../rtl';
|
||||
|
||||
const messages = defineMessages({
|
||||
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
|
||||
@@ -42,7 +43,10 @@ export default class ReplyIndicator extends ImmutablePureComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = { __html: status.get('contentHtml') };
|
||||
const content = { __html: status.get('contentHtml') };
|
||||
const style = {
|
||||
direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='reply-indicator'>
|
||||
@@ -55,7 +59,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className='reply-indicator__content' dangerouslySetInnerHTML={content} />
|
||||
<div className='reply-indicator__content' style={style} dangerouslySetInnerHTML={content} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export default class Upload extends ImmutablePureComponent {
|
||||
render () {
|
||||
const { intl, media } = this.props;
|
||||
const active = this.state.hovered || this.state.focused;
|
||||
const description = this.state.dirtyDescription || media.get('description') || '';
|
||||
const description = this.state.dirtyDescription || (this.state.dirtyDescription !== '' && media.get('description')) || '';
|
||||
|
||||
return (
|
||||
<div className='compose-form__upload' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||
import StatusList from '../../components/status_list';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.favourites', defaultMessage: 'Favourites' },
|
||||
@@ -16,6 +17,7 @@ const messages = defineMessages({
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
statusIds: state.getIn(['status_lists', 'favourites', 'items']),
|
||||
isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true),
|
||||
hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
|
||||
});
|
||||
|
||||
@@ -30,6 +32,7 @@ export default class Favourites extends ImmutablePureComponent {
|
||||
columnId: PropTypes.string,
|
||||
multiColumn: PropTypes.bool,
|
||||
hasMore: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
@@ -59,12 +62,12 @@ export default class Favourites extends ImmutablePureComponent {
|
||||
this.column = c;
|
||||
}
|
||||
|
||||
handleScrollToBottom = () => {
|
||||
handleScrollToBottom = debounce(() => {
|
||||
this.props.dispatch(expandFavouritedStatuses());
|
||||
}
|
||||
}, 300, { leading: true })
|
||||
|
||||
render () {
|
||||
const { intl, statusIds, columnId, multiColumn, hasMore } = this.props;
|
||||
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
|
||||
const pinned = !!columnId;
|
||||
|
||||
return (
|
||||
@@ -85,6 +88,7 @@ export default class Favourites extends ImmutablePureComponent {
|
||||
statusIds={statusIds}
|
||||
scrollKey={`favourited_statuses-${columnId}`}
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
onScrollToBottom={this.handleScrollToBottom}
|
||||
/>
|
||||
</Column>
|
||||
|
||||
@@ -161,7 +161,7 @@ export default class ListTimeline extends React.PureComponent {
|
||||
scrollKey={`list_timeline-${columnId}`}
|
||||
timelineId={`list:${id}`}
|
||||
loadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet.' />}
|
||||
emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />}
|
||||
/>
|
||||
</Column>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from '../../../actions/timelines';
|
||||
import Column from '../../../components/column';
|
||||
import ColumnHeader from '../../../components/column_header';
|
||||
import { connectHashtagStream } from '../../../actions/streaming';
|
||||
|
||||
@connect()
|
||||
export default class HashtagTimeline extends React.PureComponent {
|
||||
@@ -29,16 +30,13 @@ export default class HashtagTimeline extends React.PureComponent {
|
||||
const { dispatch, hashtag } = this.props;
|
||||
|
||||
dispatch(refreshHashtagTimeline(hashtag));
|
||||
|
||||
this.polling = setInterval(() => {
|
||||
dispatch(refreshHashtagTimeline(hashtag));
|
||||
}, 10000);
|
||||
this.disconnect = dispatch(connectHashtagStream(hashtag));
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
if (typeof this.polling !== 'undefined') {
|
||||
clearInterval(this.polling);
|
||||
this.polling = null;
|
||||
if (this.disconnect) {
|
||||
this.disconnect();
|
||||
this.disconnect = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import Column from '../../../components/column';
|
||||
import ColumnHeader from '../../../components/column_header';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { connectPublicStream } from '../../../actions/streaming';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
|
||||
@@ -35,16 +36,13 @@ export default class PublicTimeline extends React.PureComponent {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(refreshPublicTimeline());
|
||||
|
||||
this.polling = setInterval(() => {
|
||||
dispatch(refreshPublicTimeline());
|
||||
}, 3000);
|
||||
this.disconnect = dispatch(connectPublicStream());
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
if (typeof this.polling !== 'undefined') {
|
||||
clearInterval(this.polling);
|
||||
this.polling = null;
|
||||
if (this.disconnect) {
|
||||
this.disconnect();
|
||||
this.disconnect = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ export default class Card extends React.PureComponent {
|
||||
Immutable.fromJS([
|
||||
{
|
||||
type: 'image',
|
||||
url: card.get('url'),
|
||||
url: card.get('embed_url'),
|
||||
description: card.get('title'),
|
||||
meta: {
|
||||
original: {
|
||||
@@ -59,6 +59,8 @@ export default class Card extends React.PureComponent {
|
||||
|
||||
renderLink () {
|
||||
const { card, maxDescription } = this.props;
|
||||
const { width } = this.state;
|
||||
const horizontal = card.get('width') > card.get('height') && (card.get('width') + 100 >= width);
|
||||
|
||||
let image = '';
|
||||
let provider = card.get('provider_name');
|
||||
@@ -75,17 +77,15 @@ export default class Card extends React.PureComponent {
|
||||
provider = decodeIDNA(getHostname(card.get('url')));
|
||||
}
|
||||
|
||||
const className = classnames('status-card', {
|
||||
'horizontal': card.get('width') > card.get('height'),
|
||||
});
|
||||
const className = classnames('status-card', { horizontal });
|
||||
|
||||
return (
|
||||
<a href={card.get('url')} className={className} target='_blank' rel='noopener'>
|
||||
<a href={card.get('url')} className={className} target='_blank' rel='noopener' ref={this.setRef}>
|
||||
{image}
|
||||
|
||||
<div className='status-card__content'>
|
||||
<strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>
|
||||
<p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>
|
||||
{!horizontal && <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>}
|
||||
<span className='status-card__host'>{provider}</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -53,7 +53,10 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||
if (!this.props.singleColumn) {
|
||||
this.node.addEventListener('wheel', this.handleWheel, detectPassiveEvents.hasSupport ? { passive: true } : false);
|
||||
}
|
||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||
|
||||
this.lastIndex = getIndex(this.context.router.history.location.pathname);
|
||||
this.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
|
||||
|
||||
this.setState({ shouldAnimate: true });
|
||||
}
|
||||
|
||||
@@ -79,7 +82,8 @@ export default class ColumnsArea extends ImmutablePureComponent {
|
||||
|
||||
handleChildrenContentChange() {
|
||||
if (!this.props.singleColumn) {
|
||||
this._interruptScrollAnimation = scrollRight(this.node, this.node.scrollWidth - window.innerWidth);
|
||||
const modifier = this.isRtlLayout ? -1 : 1;
|
||||
this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ export default class VideoModal extends ImmutablePureComponent {
|
||||
src={media.get('url')}
|
||||
startTime={time}
|
||||
onCloseVideo={onClose}
|
||||
detailed
|
||||
description={media.get('description')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,18 @@ const messages = defineMessages({
|
||||
exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
|
||||
});
|
||||
|
||||
const formatTime = secondsNum => {
|
||||
let hours = Math.floor(secondsNum / 3600);
|
||||
let minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
|
||||
let seconds = secondsNum - (hours * 3600) - (minutes * 60);
|
||||
|
||||
if (hours < 10) hours = '0' + hours;
|
||||
if (minutes < 10) minutes = '0' + minutes;
|
||||
if (seconds < 10) seconds = '0' + seconds;
|
||||
|
||||
return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
|
||||
};
|
||||
|
||||
const findElementPosition = el => {
|
||||
let box;
|
||||
|
||||
@@ -83,11 +95,13 @@ export default class Video extends React.PureComponent {
|
||||
startTime: PropTypes.number,
|
||||
onOpenVideo: PropTypes.func,
|
||||
onCloseVideo: PropTypes.func,
|
||||
detailed: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
progress: 0,
|
||||
currentTime: 0,
|
||||
duration: 0,
|
||||
paused: true,
|
||||
dragging: false,
|
||||
fullscreen: false,
|
||||
@@ -117,7 +131,10 @@ export default class Video extends React.PureComponent {
|
||||
}
|
||||
|
||||
handleTimeUpdate = () => {
|
||||
this.setState({ progress: 100 * (this.video.currentTime / this.video.duration) });
|
||||
this.setState({
|
||||
currentTime: Math.floor(this.video.currentTime),
|
||||
duration: Math.floor(this.video.duration),
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseDown = e => {
|
||||
@@ -143,8 +160,10 @@ export default class Video extends React.PureComponent {
|
||||
|
||||
handleMouseMove = throttle(e => {
|
||||
const { x } = getPointerPosition(this.seek, e);
|
||||
this.video.currentTime = this.video.duration * x;
|
||||
this.setState({ progress: x * 100 });
|
||||
const currentTime = Math.floor(this.video.duration * x);
|
||||
|
||||
this.video.currentTime = currentTime;
|
||||
this.setState({ currentTime });
|
||||
}, 60);
|
||||
|
||||
togglePlay = () => {
|
||||
@@ -226,11 +245,12 @@ export default class Video extends React.PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt } = this.props;
|
||||
const { progress, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
|
||||
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 progress = (currentTime / duration) * 100;
|
||||
|
||||
return (
|
||||
<div className={classNames('video-player', { inactive: !revealed, 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: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
<video
|
||||
ref={this.setVideoRef}
|
||||
src={src}
|
||||
@@ -267,16 +287,27 @@ export default class Video extends React.PureComponent {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='video-player__buttons left'>
|
||||
<button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
|
||||
<button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
|
||||
{!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
|
||||
</div>
|
||||
<div className='video-player__buttons-bar'>
|
||||
<div className='video-player__buttons left'>
|
||||
<button aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}><i className={classNames('fa fa-fw', { 'fa-play': paused, 'fa-pause': !paused })} /></button>
|
||||
<button aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}><i className={classNames('fa fa-fw', { 'fa-volume-off': muted, 'fa-volume-up': !muted })} /></button>
|
||||
|
||||
<div className='video-player__buttons right'>
|
||||
{(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
|
||||
{onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-times' /></button>}
|
||||
<button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
|
||||
{!onCloseVideo && <button aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}><i className='fa fa-fw fa-eye' /></button>}
|
||||
|
||||
{(detailed || fullscreen) &&
|
||||
<span>
|
||||
<span className='video-player__time-current'>{formatTime(currentTime)}</span>
|
||||
<span className='video-player__time-sep'>/</span>
|
||||
<span className='video-player__time-total'>{formatTime(duration)}</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div className='video-player__buttons right'>
|
||||
{(!fullscreen && onOpenVideo) && <button aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}><i className='fa fa-fw fa-expand' /></button>}
|
||||
{onCloseVideo && <button aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}><i className='fa fa-fw fa-compress' /></button>}
|
||||
<button aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}><i className={classNames('fa fa-fw', { 'fa-arrows-alt': !fullscreen, 'fa-compress': fullscreen })} /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
"column.favourites": "المفضلة",
|
||||
"column.follow_requests": "طلبات المتابعة",
|
||||
"column.home": "الرئيسية",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "القوائم",
|
||||
"column.mutes": "الحسابات المكتومة",
|
||||
"column.notifications": "الإشعارات",
|
||||
"column.notifications": "الإخطارات",
|
||||
"column.pins": "التبويقات المثبتة",
|
||||
"column.public": "الخيط العام الموحد",
|
||||
"column_back_button.label": "العودة",
|
||||
@@ -64,7 +64,7 @@
|
||||
"confirmations.delete.confirm": "حذف",
|
||||
"confirmations.delete.message": "هل أنت متأكد أنك تريد حذف هذا المنشور ؟",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.message": "هل تود حقا حذف هذه القائمة ؟",
|
||||
"confirmations.domain_block.confirm": "إخفاء إسم النطاق كاملا",
|
||||
"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": "أكتم",
|
||||
@@ -109,32 +109,32 @@
|
||||
"home.settings": "إعدادات العمود",
|
||||
"keyboard_shortcuts.back": "للعودة",
|
||||
"keyboard_shortcuts.boost": "للترقية",
|
||||
"keyboard_shortcuts.column": "to focus a status in one of the columns",
|
||||
"keyboard_shortcuts.compose": "to focus the compose textarea",
|
||||
"keyboard_shortcuts.column": "للتركيز على منشور على أحد الأعمدة",
|
||||
"keyboard_shortcuts.compose": "للتركيز على نافذة تحرير النصوص",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.down": "للإنتقال إلى أسفل القائمة",
|
||||
"keyboard_shortcuts.enter": "to open status",
|
||||
"keyboard_shortcuts.favourite": "to favourite",
|
||||
"keyboard_shortcuts.favourite": "للإضافة إلى المفضلة",
|
||||
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
|
||||
"keyboard_shortcuts.hotkey": "Hotkey",
|
||||
"keyboard_shortcuts.legend": "to display this legend",
|
||||
"keyboard_shortcuts.hotkey": "مفتاح الإختصار",
|
||||
"keyboard_shortcuts.legend": "لعرض هذا المفتاح",
|
||||
"keyboard_shortcuts.mention": "لذِكر الناشر",
|
||||
"keyboard_shortcuts.reply": "للردّ",
|
||||
"keyboard_shortcuts.search": "to focus search",
|
||||
"keyboard_shortcuts.search": "للتركيز على البحث",
|
||||
"keyboard_shortcuts.toot": "لتحرير تبويق جديد",
|
||||
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
|
||||
"keyboard_shortcuts.up": "للإنتقال إلى أعلى القائمة",
|
||||
"lightbox.close": "إغلاق",
|
||||
"lightbox.next": "التالي",
|
||||
"lightbox.previous": "العودة",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.account.add": "أضف إلى القائمة",
|
||||
"lists.account.remove": "إحذف من القائمة",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.edit": "تعديل القائمة",
|
||||
"lists.new.create": "إنشاء قائمة",
|
||||
"lists.new.title_placeholder": "عنوان القائمة الجديدة",
|
||||
"lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
|
||||
"lists.subheading": "قوائمك",
|
||||
"loading_indicator.label": "تحميل ...",
|
||||
"media_gallery.toggle_visible": "عرض / إخفاء",
|
||||
"missing_indicator.label": "تعذر العثور عليه",
|
||||
@@ -146,7 +146,7 @@
|
||||
"navigation_bar.follow_requests": "طلبات المتابعة",
|
||||
"navigation_bar.info": "معلومات إضافية",
|
||||
"navigation_bar.keyboard_shortcuts": "إختصارات لوحة المفاتيح",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.lists": "القوائم",
|
||||
"navigation_bar.logout": "خروج",
|
||||
"navigation_bar.mutes": "الحسابات المكتومة",
|
||||
"navigation_bar.pins": "التبويقات المثبتة",
|
||||
@@ -209,7 +209,7 @@
|
||||
"search_popout.search_format": "نمط البحث المتقدم",
|
||||
"search_popout.tips.hashtag": "وسم",
|
||||
"search_popout.tips.status": "حالة",
|
||||
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
|
||||
"search_popout.tips.text": "جملة قصيرة تُمكّنُك من عرض أسماء و حسابات و كلمات رمزية",
|
||||
"search_popout.tips.user": "مستخدِم",
|
||||
"search_results.total": "{count, number} {count, plural, one {result} و {results}}",
|
||||
"standalone.public_title": "نظرة على ...",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Зареждане...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"column.favourites": "Favorits",
|
||||
"column.follow_requests": "Peticions per seguir-te",
|
||||
"column.home": "Inici",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "Llistes",
|
||||
"column.mutes": "Usuaris silenciats",
|
||||
"column.notifications": "Notificacions",
|
||||
"column.pins": "Toot fixat",
|
||||
@@ -64,7 +64,7 @@
|
||||
"confirmations.delete.confirm": "Esborrar",
|
||||
"confirmations.delete.message": "Estàs segur que vols esborrar aquest estat?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"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",
|
||||
@@ -127,14 +127,14 @@
|
||||
"lightbox.close": "Tancar",
|
||||
"lightbox.next": "Següent",
|
||||
"lightbox.previous": "Anterior",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.account.add": "Afegir a la llista",
|
||||
"lists.account.remove": "Treure de la llista",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.edit": "Editar llista",
|
||||
"lists.new.create": "Afegir llista",
|
||||
"lists.new.title_placeholder": "Nou títol de llista",
|
||||
"lists.search": "Cercar entre les persones que segueixes",
|
||||
"lists.subheading": "Les teves llistes",
|
||||
"loading_indicator.label": "Carregant...",
|
||||
"media_gallery.toggle_visible": "Alternar visibilitat",
|
||||
"missing_indicator.label": "No trobat",
|
||||
@@ -146,7 +146,7 @@
|
||||
"navigation_bar.follow_requests": "Sol·licituds de seguiment",
|
||||
"navigation_bar.info": "Informació addicional",
|
||||
"navigation_bar.keyboard_shortcuts": "Dreceres de teclat",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.lists": "Llistes",
|
||||
"navigation_bar.logout": "Tancar sessió",
|
||||
"navigation_bar.mutes": "Usuaris silenciats",
|
||||
"navigation_bar.pins": "Toots fixats",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Wird geladen …",
|
||||
"media_gallery.toggle_visible": "Sichtbarkeit umschalten",
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
"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.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
|
||||
"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",
|
||||
@@ -135,7 +135,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Ŝarganta…",
|
||||
"media_gallery.toggle_visible": "Baskuli videblecon",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Cargando…",
|
||||
"media_gallery.toggle_visible": "Cambiar visibilidad",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "بارگیری...",
|
||||
"media_gallery.toggle_visible": "تغییر پیدایی",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Ladataan...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
"confirmations.block.message": "Confirmez-vous le blocage de {name} ?",
|
||||
"confirmations.delete.confirm": "Supprimer",
|
||||
"confirmations.delete.message": "Confirmez-vous la suppression de ce pouet ?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.confirm": "Supprimer",
|
||||
"confirmations.delete_list.message": "Êtes-vous sûr de vouloir supprimer définitivement cette liste ?",
|
||||
"confirmations.domain_block.confirm": "Masquer le domaine entier",
|
||||
"confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.",
|
||||
"confirmations.mute.confirm": "Masquer",
|
||||
@@ -91,7 +91,7 @@
|
||||
"empty_column.hashtag": "Il n’y a encore aucun contenu associé à ce hashtag",
|
||||
"empty_column.home": "Vous ne suivez encore personne. Visitez {public} ou bien utilisez la recherche pour vous connecter à d’autres utilisateur⋅ice⋅s.",
|
||||
"empty_column.home.public_timeline": "le fil public",
|
||||
"empty_column.list": "Il n'y a rien dans cette liste pour l'instant.",
|
||||
"empty_column.list": "Il n'y a rien dans cette liste pour l'instant. Dès que des personnes de cette liste publierons de nouveaux statuts, ils apparaîtront ici.",
|
||||
"empty_column.notifications": "Vous n’avez pas encore de notification. Interagissez avec d’autres utilisateur⋅ice⋅s pour débuter la conversation.",
|
||||
"empty_column.public": "Il n’y a rien ici ! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice⋅s d’autres instances pour remplir le fil public.",
|
||||
"follow_request.authorize": "Accepter",
|
||||
@@ -113,28 +113,28 @@
|
||||
"keyboard_shortcuts.compose": "pour centrer la zone de redaction",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.down": "descendre dans la liste",
|
||||
"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.enter": "pour ouvrir le statut",
|
||||
"keyboard_shortcuts.favourite": "vers les favoris",
|
||||
"keyboard_shortcuts.heading": "Raccourcis clavier",
|
||||
"keyboard_shortcuts.hotkey": "Raccourci",
|
||||
"keyboard_shortcuts.legend": "pour afficher cette légende",
|
||||
"keyboard_shortcuts.mention": "pour mentionner l'auteur",
|
||||
"keyboard_shortcuts.reply": "pour répondre",
|
||||
"keyboard_shortcuts.search": "to focus search",
|
||||
"keyboard_shortcuts.toot": "to start a brand new toot",
|
||||
"keyboard_shortcuts.toot": "pour démarrer un tout nouveau pouet",
|
||||
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
|
||||
"keyboard_shortcuts.up": "to move up in the list",
|
||||
"lightbox.close": "Fermer",
|
||||
"lightbox.next": "Suivant",
|
||||
"lightbox.previous": "Précédent",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.account.add": "Ajouter à la liste",
|
||||
"lists.account.remove": "Supprimer de la liste",
|
||||
"lists.delete": "Effacer la liste",
|
||||
"lists.edit": "Éditer la liste",
|
||||
"lists.new.create": "Ajouter une liste",
|
||||
"lists.new.title_placeholder": "Titre de la nouvelle liste",
|
||||
"lists.search": "Rechercher parmi les gens que vous suivez",
|
||||
"lists.subheading": "Vos listes",
|
||||
"loading_indicator.label": "Chargement…",
|
||||
"media_gallery.toggle_visible": "Modifier la visibilité",
|
||||
"missing_indicator.label": "Non trouvé",
|
||||
@@ -145,8 +145,8 @@
|
||||
"navigation_bar.favourites": "Favoris",
|
||||
"navigation_bar.follow_requests": "Demandes de suivi",
|
||||
"navigation_bar.info": "Plus d’informations",
|
||||
"navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.keyboard_shortcuts": "Raccourcis clavier",
|
||||
"navigation_bar.lists": "Listes",
|
||||
"navigation_bar.logout": "Déconnexion",
|
||||
"navigation_bar.mutes": "Comptes masqués",
|
||||
"navigation_bar.pins": "Pouets épinglés",
|
||||
@@ -241,7 +241,7 @@
|
||||
"tabs_bar.home": "Accueil",
|
||||
"tabs_bar.local_timeline": "Fil public local",
|
||||
"tabs_bar.notifications": "Notifications",
|
||||
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
|
||||
"ui.beforeunload": "Votre brouillon sera perdu si vous quittez Mastodon.",
|
||||
"upload_area.title": "Glissez et déposez pour envoyer",
|
||||
"upload_button.label": "Joindre un média",
|
||||
"upload_form.description": "Décrire pour les malvoyants",
|
||||
|
||||
259
app/javascript/mastodon/locales/gl.json
Normal file
259
app/javascript/mastodon/locales/gl.json
Normal file
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"account.block": "Bloquear @{name}",
|
||||
"account.block_domain": "Ocultar calquer contido de {domain}",
|
||||
"account.disclaimer_full": "A información inferior podería mostrar un perfil incompleto da usuaria.",
|
||||
"account.edit_profile": "Editar perfil",
|
||||
"account.follow": "Seguir",
|
||||
"account.followers": "Seguidoras",
|
||||
"account.follows": "Seguindo",
|
||||
"account.follows_you": "Séguena",
|
||||
"account.hide_reblogs": "Ocultar repeticións de @{name}",
|
||||
"account.media": "Medios",
|
||||
"account.mention": "Mencionar @{name}",
|
||||
"account.moved_to": "{name} marchou a:",
|
||||
"account.mute": "Acalar @{name}",
|
||||
"account.mute_notifications": "Acalar as notificacións de @{name}",
|
||||
"account.posts": "Publicacións",
|
||||
"account.report": "Informar sobre @{name}",
|
||||
"account.requested": "Agardando aceptación. Pulse para cancelar a solicitude de seguimento",
|
||||
"account.share": "Compartir o perfil de @{name}",
|
||||
"account.show_reblogs": "Mostrar repeticións de @{name}",
|
||||
"account.unblock": "Desbloquear @{name}",
|
||||
"account.unblock_domain": "Non ocultar {domain}",
|
||||
"account.unfollow": "Non seguir",
|
||||
"account.unmute": "Non acalar @{name}",
|
||||
"account.unmute_notifications": "Desbloquear as notificacións de @{name}",
|
||||
"account.view_full_profile": "Ver o perfil completo",
|
||||
"boost_modal.combo": "Pulse {combo} para saltar esto a próxima vez",
|
||||
"bundle_column_error.body": "Houbo un fallo mentras se cargaba este compoñente.",
|
||||
"bundle_column_error.retry": "Inténteo de novo",
|
||||
"bundle_column_error.title": "Fallo na rede",
|
||||
"bundle_modal_error.close": "Pechar",
|
||||
"bundle_modal_error.message": "Algo fallou mentras se cargaba este compoñente.",
|
||||
"bundle_modal_error.retry": "Inténteo de novo",
|
||||
"column.blocks": "Usuarias bloqueadas",
|
||||
"column.community": "Liña temporal local",
|
||||
"column.favourites": "Favoritas",
|
||||
"column.follow_requests": "Peticións de seguimento",
|
||||
"column.home": "Inicio",
|
||||
"column.lists": "Listas",
|
||||
"column.mutes": "Usuarias acaladas",
|
||||
"column.notifications": "Notificacións",
|
||||
"column.pins": "Mensaxes fixadas",
|
||||
"column.public": "Liña temporal federada",
|
||||
"column_back_button.label": "Atrás",
|
||||
"column_header.hide_settings": "Agochar axustes",
|
||||
"column_header.moveLeft_settings": "Mover a columna hacia a esquerda",
|
||||
"column_header.moveRight_settings": "Mover a columna hacia a dereita",
|
||||
"column_header.pin": "Fixar",
|
||||
"column_header.show_settings": "Mostras axustes",
|
||||
"column_header.unpin": "Soltar",
|
||||
"column_subheading.navigation": "Navegación",
|
||||
"column_subheading.settings": "Axustes",
|
||||
"compose_form.lock_disclaimer": "A súa conta non está {locked}. Calquera pode seguila para ver as súas mensaxes só-para-seguidoras.",
|
||||
"compose_form.lock_disclaimer.lock": "bloqueado",
|
||||
"compose_form.placeholder": "A qué andas?",
|
||||
"compose_form.publish": "Toot",
|
||||
"compose_form.publish_loud": "{publish}!",
|
||||
"compose_form.sensitive": "Marcar medios como sensibles",
|
||||
"compose_form.spoiler": "Agochar texto detrás de un aviso",
|
||||
"compose_form.spoiler_placeholder": "Escriba o aviso aquí",
|
||||
"confirmation_modal.cancel": "Cancelar",
|
||||
"confirmations.block.confirm": "Bloquear",
|
||||
"confirmations.block.message": "Está segura de querer bloquear a {name}?",
|
||||
"confirmations.delete.confirm": "Borrar",
|
||||
"confirmations.delete.message": "Está segura de que quere eliminar este estado?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Estás seguro de que queres eliminar permanentemente esta lista?",
|
||||
"confirmations.domain_block.confirm": "Agochar un dominio completo",
|
||||
"confirmations.domain_block.message": "Realmente está segura de que quere bloquear por completo o dominio {domain}? Normalmente é suficiente, e preferible, bloquear de xeito selectivo varios elementos.",
|
||||
"confirmations.mute.confirm": "Acalar",
|
||||
"confirmations.mute.message": "Está segura de que quere acalar a {name}?",
|
||||
"confirmations.unfollow.confirm": "Deixar de seguir",
|
||||
"confirmations.unfollow.message": "Quere deixar de seguir a {name}?",
|
||||
"embed.instructions": "Copie o código inferior para incrustar no seu sitio web este estado.",
|
||||
"embed.preview": "Así será mostrado:",
|
||||
"emoji_button.activity": "Actividade",
|
||||
"emoji_button.custom": "Personalizado",
|
||||
"emoji_button.flags": "Marcas",
|
||||
"emoji_button.food": "Comida e Bebida",
|
||||
"emoji_button.label": "Insertar emoji",
|
||||
"emoji_button.nature": "Natureza",
|
||||
"emoji_button.not_found": "Sen emojos!! (╯°□°)╯︵ ┻━┻",
|
||||
"emoji_button.objects": "Obxetos",
|
||||
"emoji_button.people": "Xente",
|
||||
"emoji_button.recent": "Utilizadas con frecuencia",
|
||||
"emoji_button.search": "Buscar...",
|
||||
"emoji_button.search_results": "Resultados da busca",
|
||||
"emoji_button.symbols": "Símbolos",
|
||||
"emoji_button.travel": "Viaxes e Lugares",
|
||||
"empty_column.community": "A liña temporal local está baldeira. Escriba algo de xeito público para que rule!",
|
||||
"empty_column.hashtag": "Aínda non hai nada con esta etiqueta.",
|
||||
"empty_column.home": "A súa liña temporal de inicio está baldeira! Visite {public} ou utilice a busca para atopar outras usuarias.",
|
||||
"empty_column.home.public_timeline": "a liña temporal pública",
|
||||
"empty_column.list": "Aínda non hai nada en esta lista.",
|
||||
"empty_column.notifications": "Aínda non ten notificacións. Interactúe con outras para iniciar unha conversa.",
|
||||
"empty_column.public": "Nada por aquí! Escriba algo de xeito público, ou siga manualmente usuarias de outras instancias para ir enchéndoa",
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rexeitar",
|
||||
"getting_started.appsshort": "Aplicacións",
|
||||
"getting_started.faq": "PMF",
|
||||
"getting_started.heading": "Comezando",
|
||||
"getting_started.open_source_notice": "Mastodon é software de código aberto. Pode contribuír ou informar de fallos en GitHub en {github}.",
|
||||
"getting_started.userguide": "Guía de usuaria",
|
||||
"home.column_settings.advanced": "Avanzado",
|
||||
"home.column_settings.basic": "Básico",
|
||||
"home.column_settings.filter_regex": "Filtrar expresións regulares",
|
||||
"home.column_settings.show_reblogs": "Mostrar repeticións",
|
||||
"home.column_settings.show_replies": "Mostrar respostas",
|
||||
"home.settings": "Axustes da columna",
|
||||
"keyboard_shortcuts.back": "voltar atrás",
|
||||
"keyboard_shortcuts.boost": "repetir",
|
||||
"keyboard_shortcuts.column": "destacar un estado en unha das columnas",
|
||||
"keyboard_shortcuts.compose": "Foco no área de escritura",
|
||||
"keyboard_shortcuts.description": "Descrición",
|
||||
"keyboard_shortcuts.down": "ir hacia abaixo na lista",
|
||||
"keyboard_shortcuts.enter": "abrir estado",
|
||||
"keyboard_shortcuts.favourite": "marcar como favorito",
|
||||
"keyboard_shortcuts.heading": "Atallos do teclado",
|
||||
"keyboard_shortcuts.hotkey": "Tecla de acceso directo",
|
||||
"keyboard_shortcuts.legend": "para mostrar esta lenda",
|
||||
"keyboard_shortcuts.mention": "para mencionar o autor",
|
||||
"keyboard_shortcuts.reply": "para responder",
|
||||
"keyboard_shortcuts.search": "para centrar a busca",
|
||||
"keyboard_shortcuts.toot": "escribir un toot novo",
|
||||
"keyboard_shortcuts.unfocus": "quitar o foco do área de escritura/busca",
|
||||
"keyboard_shortcuts.up": "ir hacia arriba na lista",
|
||||
"lightbox.close": "Fechar",
|
||||
"lightbox.next": "Seguinte",
|
||||
"lightbox.previous": "Anterior",
|
||||
"lists.account.add": "Engadir á lista",
|
||||
"lists.account.remove": "Eliminar da lista",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Editar lista",
|
||||
"lists.new.create": "Engadir lista",
|
||||
"lists.new.title_placeholder": "Novo título da lista",
|
||||
"lists.search": "Procurar entre a xente que segues",
|
||||
"lists.subheading": "As túas listas",
|
||||
"loading_indicator.label": "Cargando...",
|
||||
"media_gallery.toggle_visible": "Dar visibilidade",
|
||||
"missing_indicator.label": "Non atopado",
|
||||
"mute_modal.hide_notifications": "Esconder notificacións deste usuario?",
|
||||
"navigation_bar.blocks": "Usuarios bloqueados",
|
||||
"navigation_bar.community_timeline": "Liña temporal local",
|
||||
"navigation_bar.edit_profile": "Editar perfil",
|
||||
"navigation_bar.favourites": "Favoritas",
|
||||
"navigation_bar.follow_requests": "Peticións de seguimento",
|
||||
"navigation_bar.info": "Sobre esta instancia",
|
||||
"navigation_bar.keyboard_shortcuts": "Atallos do teclado",
|
||||
"navigation_bar.lists": "Listas",
|
||||
"navigation_bar.logout": "Sair",
|
||||
"navigation_bar.mutes": "Usuarias acaladas",
|
||||
"navigation_bar.pins": "Mensaxes fixadas",
|
||||
"navigation_bar.preferences": "Preferencias",
|
||||
"navigation_bar.public_timeline": "Liña temporal federada",
|
||||
"notification.favourite": "{name} marcou como favorito o seu estado",
|
||||
"notification.follow": "{name} está a seguila",
|
||||
"notification.mention": "{name} mencionoute",
|
||||
"notification.reblog": "{name} promocionou o seu estado",
|
||||
"notifications.clear": "Limpar notificacións",
|
||||
"notifications.clear_confirmation": "Estás seguro de que queres limpar permanentemente todas as túas notificacións?",
|
||||
"notifications.column_settings.alert": "Notificacións de escritorio",
|
||||
"notifications.column_settings.favourite": "Favoritas:",
|
||||
"notifications.column_settings.follow": "Novos seguidores:",
|
||||
"notifications.column_settings.mention": "Mencións:",
|
||||
"notifications.column_settings.push": "Enviar notificacións",
|
||||
"notifications.column_settings.push_meta": "Este aparello",
|
||||
"notifications.column_settings.reblog": "Promocións:",
|
||||
"notifications.column_settings.show": "Mostrar en columna",
|
||||
"notifications.column_settings.sound": "Reproducir son",
|
||||
"onboarding.done": "Feito",
|
||||
"onboarding.next": "Seguinte",
|
||||
"onboarding.page_five.public_timelines": "A liña de tempo local mostra as publicacións públicas de todos en {domain}. A liña de tempo federada mostra as publicacións públicas de todos os que as persoas en {domain} seguen. Estas son as Liñas de tempo públicas, unha boa forma de descubrir novas persoas.",
|
||||
"onboarding.page_four.home": "A liña de tempo local mostra as publicacións das persoas que segues.",
|
||||
"onboarding.page_four.notifications": "A columna de notificacións mostra cando alguén interactúa contigo.",
|
||||
"onboarding.page_one.federation": "Mastodon é unha rede de servidores independentes que se unen para facer unha rede social máis grande. Chamamos instancias a estes servidores.",
|
||||
"onboarding.page_one.handle": "Estás en {domain}, polo que o teu nome de usuario completo é {handle}",
|
||||
"onboarding.page_one.welcome": "Benvido a Mastodon!",
|
||||
"onboarding.page_six.admin": "O administrador da túa instancia é {admin}.",
|
||||
"onboarding.page_six.almost_done": "Case feito...",
|
||||
"onboarding.page_six.appetoot": "Que tootes ben!",
|
||||
"onboarding.page_six.apps_available": "Hai {apps} dispoñíbeis para iOS, Android e outras plataformas.",
|
||||
"onboarding.page_six.github": "Mastodon é un software gratuito e de código aberto. Pode informar de erros, solicitar novas funcionalidades ou contribuír ao código en {github}.",
|
||||
"onboarding.page_six.guidelines": "directrices da comunidade",
|
||||
"onboarding.page_six.read_guidelines": "Por favor, le as {guidelines} do {domain}!",
|
||||
"onboarding.page_six.various_app": "aplicacións móbiles",
|
||||
"onboarding.page_three.profile": "Edita o teu perfil para cambiar o teu avatar, bio e nome. Alí, tamén atoparás outras preferencias.",
|
||||
"onboarding.page_three.search": "Utilice a barra de busca para atopar xente e descubrir etiquetas, como {illustration} e {introductions}. Para atopar unha usuaria que non está en esta instancia utilice o seu enderezo completo.",
|
||||
"onboarding.page_two.compose": "Escriba mensaxes desde a columna de composición. Pode subir imaxes, mudar as opcións de intimidade e engadir avisos sobre o contido coas iconas inferiores.",
|
||||
"onboarding.skip": "Saltar",
|
||||
"privacy.change": "Axustar a intimidade do estado",
|
||||
"privacy.direct.long": "Enviar exclusivamente as usuarias mencionadas",
|
||||
"privacy.direct.short": "Directa",
|
||||
"privacy.private.long": "Enviar só as seguidoras",
|
||||
"privacy.private.short": "Só-seguidoras",
|
||||
"privacy.public.long": "Publicar na liña temporal pública",
|
||||
"privacy.public.short": "Pública",
|
||||
"privacy.unlisted.long": "Non publicar en liñas temporais públicas",
|
||||
"privacy.unlisted.short": "Non listada",
|
||||
"relative_time.days": "{number}d",
|
||||
"relative_time.hours": "{number}h",
|
||||
"relative_time.just_now": "agora",
|
||||
"relative_time.minutes": "{number}m",
|
||||
"relative_time.seconds": "{number}s",
|
||||
"reply_indicator.cancel": "Cancelar",
|
||||
"report.placeholder": "Comentarios adicionais",
|
||||
"report.submit": "Enviar",
|
||||
"report.target": "Informar {target}",
|
||||
"search.placeholder": "Buscar",
|
||||
"search_popout.search_format": "Formato de busca avanzada",
|
||||
"search_popout.tips.hashtag": "etiqueta",
|
||||
"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.total": "{count, number} {count,plural,one {result} outros {results}}",
|
||||
"standalone.public_title": "Ollada dentro...",
|
||||
"status.cannot_reblog": "Esta mensaxe non pode ser promocionada",
|
||||
"status.delete": "Eliminar",
|
||||
"status.embed": "Incrustar",
|
||||
"status.favourite": "Favorita",
|
||||
"status.load_more": "Cargar máis",
|
||||
"status.media_hidden": "Medios ocultos",
|
||||
"status.mention": "Mencionar @{name}",
|
||||
"status.more": "Máis",
|
||||
"status.mute_conversation": "Acalar conversa",
|
||||
"status.open": "Expandir este estado",
|
||||
"status.pin": "Fixar no perfil",
|
||||
"status.reblog": "Promocionar",
|
||||
"status.reblogged_by": "{name} promocionado",
|
||||
"status.reply": "Resposta",
|
||||
"status.replyAll": "Resposta a conversa",
|
||||
"status.report": "Informar @{name}",
|
||||
"status.sensitive_toggle": "Pulse para ver",
|
||||
"status.sensitive_warning": "Contido sensible",
|
||||
"status.share": "Compartir",
|
||||
"status.show_less": "Mostrar menos",
|
||||
"status.show_more": "Mostrar máis",
|
||||
"status.unmute_conversation": "Non acalar a conversa",
|
||||
"status.unpin": "Despegar do perfil",
|
||||
"tabs_bar.compose": "Compoñer",
|
||||
"tabs_bar.federated_timeline": "Federado",
|
||||
"tabs_bar.home": "Inicio",
|
||||
"tabs_bar.local_timeline": "Local",
|
||||
"tabs_bar.notifications": "Notificacións",
|
||||
"ui.beforeunload": "O borrador perderase se sae de Mastodon.",
|
||||
"upload_area.title": "Arrastre e solte para subir",
|
||||
"upload_button.label": "Engadir medios",
|
||||
"upload_form.description": "Describa para deficientes visuais",
|
||||
"upload_form.undo": "Desfacer",
|
||||
"upload_progress.label": "Subindo...",
|
||||
"video.close": "Pechar video",
|
||||
"video.exit_fullscreen": "Saír da pantalla completa",
|
||||
"video.expand": "Expandir vídeo",
|
||||
"video.fullscreen": "Pantalla completa",
|
||||
"video.hide": "Agochar vídeo",
|
||||
"video.mute": "Acalar son",
|
||||
"video.pause": "Pausar",
|
||||
"video.play": "Reproducir",
|
||||
"video.unmute": "Permitir son"
|
||||
}
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "טוען...",
|
||||
"media_gallery.toggle_visible": "נראה\\בלתי נראה",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Učitavam...",
|
||||
"media_gallery.toggle_visible": "Preklopi vidljivost",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Betöltés...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Tunggu sebentar...",
|
||||
"media_gallery.toggle_visible": "Tampil/Sembunyikan",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Kargante...",
|
||||
"media_gallery.toggle_visible": "Chanjar videbleso",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Carico...",
|
||||
"media_gallery.toggle_visible": "Imposta visibilità",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"account.unmute": "ミュート解除",
|
||||
"account.unmute_notifications": "@{name}さんからの通知を受け取らない",
|
||||
"account.view_full_profile": "全ての情報を見る",
|
||||
"boost_modal.combo": "次からは{combo}を押せば、これをスキップできます。",
|
||||
"boost_modal.combo": "次からは{combo}を押せば、これをスキップできます",
|
||||
"bundle_column_error.body": "コンポーネントの読み込み中に問題が発生しました。",
|
||||
"bundle_column_error.retry": "再試行",
|
||||
"bundle_column_error.title": "ネットワークエラー",
|
||||
@@ -95,7 +95,7 @@
|
||||
"empty_column.home.public_timeline": "連合タイムライン",
|
||||
"empty_column.list": "このリストにはまだなにもありません。",
|
||||
"empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
|
||||
"empty_column.public": "ここにはまだ何もありません!公開で何かを投稿したり、他のインスタンスのユーザーをフォローしたりしていっぱいにしましょう!",
|
||||
"empty_column.public": "ここにはまだ何もありません! 公開で何かを投稿したり、他のインスタンスのユーザーをフォローしたりしていっぱいにしましょう",
|
||||
"follow_request.authorize": "許可",
|
||||
"follow_request.reject": "拒否",
|
||||
"getting_started.appsshort": "アプリ",
|
||||
@@ -162,12 +162,12 @@
|
||||
"notifications.clear": "通知を消去",
|
||||
"notifications.clear_confirmation": "本当に通知を消去しますか?",
|
||||
"notifications.column_settings.alert": "デスクトップ通知",
|
||||
"notifications.column_settings.favourite": "お気に入り",
|
||||
"notifications.column_settings.follow": "新しいフォロワー",
|
||||
"notifications.column_settings.mention": "返信",
|
||||
"notifications.column_settings.favourite": "お気に入り:",
|
||||
"notifications.column_settings.follow": "新しいフォロワー:",
|
||||
"notifications.column_settings.mention": "返信:",
|
||||
"notifications.column_settings.push": "プッシュ通知",
|
||||
"notifications.column_settings.push_meta": "このデバイス",
|
||||
"notifications.column_settings.reblog": "ブースト",
|
||||
"notifications.column_settings.reblog": "ブースト:",
|
||||
"notifications.column_settings.show": "カラムに表示",
|
||||
"notifications.column_settings.sound": "通知音を再生",
|
||||
"onboarding.done": "完了",
|
||||
@@ -176,7 +176,7 @@
|
||||
"onboarding.page_four.home": "「ホーム」タイムラインではあなたがフォローしている人の投稿を表示します。",
|
||||
"onboarding.page_four.notifications": "「通知」ではあなたへの他の人からの関わりを表示します。",
|
||||
"onboarding.page_one.federation": "Mastodonは誰でも参加できるSNSです。",
|
||||
"onboarding.page_one.handle": "あなたは今数あるMastodonインスタンスの1つである{domain}にいます。あなたのフルハンドルは{handle}です。",
|
||||
"onboarding.page_one.handle": "今あなたは数あるMastodonインスタンスの1つである{domain}にいます。あなたのフルハンドルは{handle}です",
|
||||
"onboarding.page_one.welcome": "Mastodonへようこそ!",
|
||||
"onboarding.page_six.admin": "あなたのインスタンスの管理者は{admin}です。",
|
||||
"onboarding.page_six.almost_done": "以上です。",
|
||||
@@ -184,7 +184,7 @@
|
||||
"onboarding.page_six.apps_available": "iOS、Androidあるいは他のプラットフォームで使える{apps}があります。",
|
||||
"onboarding.page_six.github": "MastodonはOSSです。バグ報告や機能要望あるいは貢献を{github}から行なえます。",
|
||||
"onboarding.page_six.guidelines": "コミュニティガイドライン",
|
||||
"onboarding.page_six.read_guidelines": "{guidelines}を読むことを忘れないようにしてください。",
|
||||
"onboarding.page_six.read_guidelines": "{guidelines}を読むことを忘れないようにしてください!",
|
||||
"onboarding.page_six.various_app": "様々なモバイルアプリ",
|
||||
"onboarding.page_three.profile": "「プロフィールを編集」から、あなたの自己紹介や表示名を変更できます。またそこでは他の設定ができます。",
|
||||
"onboarding.page_three.search": "検索バーで、{illustration}や{introductions}のように特定のハッシュタグの投稿を見たり、ユーザーを探したりできます。",
|
||||
@@ -215,7 +215,7 @@
|
||||
"search_popout.tips.text": "表示名やユーザー名、ハッシュタグに一致する単純なテキスト",
|
||||
"search_popout.tips.user": "ユーザー",
|
||||
"search_results.total": "{count, number}件の結果",
|
||||
"standalone.public_title": "今こんな話をしています",
|
||||
"standalone.public_title": "今こんな話をしています...",
|
||||
"status.cannot_reblog": "この投稿はブーストできません",
|
||||
"status.delete": "削除",
|
||||
"status.embed": "埋め込み",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "불러오는 중...",
|
||||
"media_gallery.toggle_visible": "표시 전환",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"column.favourites": "Favorieten",
|
||||
"column.follow_requests": "Volgverzoeken",
|
||||
"column.home": "Start",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "Lijsten",
|
||||
"column.mutes": "Genegeerde gebruikers",
|
||||
"column.notifications": "Meldingen",
|
||||
"column.pins": "Vastgezette toots",
|
||||
@@ -64,7 +64,7 @@
|
||||
"confirmations.delete.confirm": "Verwijderen",
|
||||
"confirmations.delete.message": "Weet je het zeker dat je deze toot wilt verwijderen?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.message": "Weet je zeker dat je deze lijst definitief wilt verwijderen?",
|
||||
"confirmations.domain_block.confirm": "Negeer alles van deze server",
|
||||
"confirmations.domain_block.message": "Weet je het echt, echt zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gewenst.",
|
||||
"confirmations.mute.confirm": "Negeren",
|
||||
@@ -91,7 +91,7 @@
|
||||
"empty_column.hashtag": "Er is nog niks te vinden onder deze hashtag.",
|
||||
"empty_column.home": "Jij volgt nog niemand. Bezoek {public} of gebruik het zoekvenster om andere mensen te ontmoeten.",
|
||||
"empty_column.home.public_timeline": "de globale tijdlijn",
|
||||
"empty_column.list": "Er is nog niks in deze lijst.",
|
||||
"empty_column.list": "Er is nog niks in deze lijst. Wanneer lijstleden nieuwe toots publiceren, zijn deze hier te zien.",
|
||||
"empty_column.notifications": "Je hebt nog geen meldingen. Heb interactie met andere mensen om het gesprek aan te gaan.",
|
||||
"empty_column.public": "Er is hier helemaal niks! Toot iets in het openbaar of volg mensen van andere servers om het te vullen",
|
||||
"follow_request.authorize": "Goedkeuren",
|
||||
@@ -107,34 +107,34 @@
|
||||
"home.column_settings.show_reblogs": "Boosts tonen",
|
||||
"home.column_settings.show_replies": "Reacties tonen",
|
||||
"home.settings": "Kolom-instellingen",
|
||||
"keyboard_shortcuts.back": "om terug te navigeren",
|
||||
"keyboard_shortcuts.back": "om terug te gaan",
|
||||
"keyboard_shortcuts.boost": "om te boosten",
|
||||
"keyboard_shortcuts.column": "om te focussen op een status in één van de kolommen",
|
||||
"keyboard_shortcuts.compose": "om te focussen op het toot tekstvak",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.column": "om op een toot te focussen in één van de kolommen",
|
||||
"keyboard_shortcuts.compose": "om het tekstvak voor toots te focussen",
|
||||
"keyboard_shortcuts.description": "Omschrijving",
|
||||
"keyboard_shortcuts.down": "om naar beneden door de lijst te bewegen",
|
||||
"keyboard_shortcuts.enter": "to open status",
|
||||
"keyboard_shortcuts.favourite": "om het te markeren als favoriet",
|
||||
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
|
||||
"keyboard_shortcuts.favourite": "om als favoriet te markeren",
|
||||
"keyboard_shortcuts.heading": "Sneltoetsen",
|
||||
"keyboard_shortcuts.hotkey": "Sneltoets",
|
||||
"keyboard_shortcuts.legend": "om deze legenda weer te geven",
|
||||
"keyboard_shortcuts.mention": "om de auteur te vermelden",
|
||||
"keyboard_shortcuts.reply": "om te antwoorden",
|
||||
"keyboard_shortcuts.search": "om te focussen op zoeken",
|
||||
"keyboard_shortcuts.reply": "om te reageren",
|
||||
"keyboard_shortcuts.search": "om het zoekvak te focussen",
|
||||
"keyboard_shortcuts.toot": "om een nieuwe toot te starten",
|
||||
"keyboard_shortcuts.unfocus": "om te ontfocussen van het toot tekstvak/zoeken",
|
||||
"keyboard_shortcuts.unfocus": "om het tekst- en zoekvak te ontfocussen",
|
||||
"keyboard_shortcuts.up": "om omhoog te bewegen in de lijst",
|
||||
"lightbox.close": "Sluiten",
|
||||
"lightbox.next": "Volgende",
|
||||
"lightbox.previous": "Vorige",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.account.add": "Aan lijst toevoegen",
|
||||
"lists.account.remove": "Uit lijst verwijderen",
|
||||
"lists.delete": "Lijst verwijderen",
|
||||
"lists.edit": "Lijst bewerken",
|
||||
"lists.new.create": "Lijst toevoegen",
|
||||
"lists.new.title_placeholder": "Naam nieuwe lijst",
|
||||
"lists.search": "Zoek naar mensen die je volgt",
|
||||
"lists.subheading": "Jouw lijsten",
|
||||
"loading_indicator.label": "Laden…",
|
||||
"media_gallery.toggle_visible": "Media wel/niet tonen",
|
||||
"missing_indicator.label": "Niet gevonden",
|
||||
@@ -146,7 +146,7 @@
|
||||
"navigation_bar.follow_requests": "Volgverzoeken",
|
||||
"navigation_bar.info": "Uitgebreide informatie",
|
||||
"navigation_bar.keyboard_shortcuts": "Toetsenbord sneltoetsen",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.lists": "Lijsten",
|
||||
"navigation_bar.logout": "Afmelden",
|
||||
"navigation_bar.mutes": "Genegeerde gebruikers",
|
||||
"navigation_bar.pins": "Vastgezette toots",
|
||||
@@ -204,7 +204,7 @@
|
||||
"reply_indicator.cancel": "Annuleren",
|
||||
"report.placeholder": "Extra opmerkingen",
|
||||
"report.submit": "Verzenden",
|
||||
"report.target": "Rapporteren van",
|
||||
"report.target": "Rapporteer {target}",
|
||||
"search.placeholder": "Zoeken",
|
||||
"search_popout.search_format": "Geavanceerd zoeken",
|
||||
"search_popout.tips.hashtag": "hashtag",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Laster...",
|
||||
"media_gallery.toggle_visible": "Veksle synlighet",
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
"account.hide_reblogs": "Rescondre los partages de @{name}",
|
||||
"account.media": "Mèdias",
|
||||
"account.mention": "Mencionar @{name}",
|
||||
"account.moved_to": "{name} a mudat los catons a : ",
|
||||
"account.moved_to": "{name} a mudat los catons a :",
|
||||
"account.mute": "Rescondre @{name}",
|
||||
"account.mute_notifications": "Mute notifications from @{name}",
|
||||
"account.mute_notifications": "Rescondre las notificacions de @{name}",
|
||||
"account.posts": "Estatuts",
|
||||
"account.report": "Senhalar @{name}",
|
||||
"account.requested": "Invitacion mandada. Clicatz per anullar.",
|
||||
"account.requested": "Invitacion mandada. Clicatz per anullar",
|
||||
"account.share": "Partejar lo perfil a @{name}",
|
||||
"account.show_reblogs": "Mostrar los partages de @{name}",
|
||||
"account.unblock": "Desblocar @{name}",
|
||||
"account.unblock_domain": "Desblocar {domain}",
|
||||
"account.unfollow": "Quitar de sègre",
|
||||
"account.unmute": "Quitar de rescondre @{name}",
|
||||
"account.unmute_notifications": "Unmute notifications from @{name}",
|
||||
"account.unmute_notifications": "Mostrar las notificacions de @{name}",
|
||||
"account.view_full_profile": "Veire lo perfil complet",
|
||||
"boost_modal.combo": "Podètz botar {combo} per passar aquò lo còp que ven",
|
||||
"bundle_column_error.body": "Quicòm a fach meuca pendent lo cargament d’aqueste compausant.",
|
||||
"bundle_column_error.body": "Quicòm a fach mèuca pendent lo cargament d’aqueste compausant.",
|
||||
"bundle_column_error.retry": "Tornar ensajar",
|
||||
"bundle_column_error.title": "Error de ret",
|
||||
"bundle_modal_error.close": "Tampar",
|
||||
@@ -36,7 +36,7 @@
|
||||
"column.favourites": "Favorits",
|
||||
"column.follow_requests": "Demandas d’abonament",
|
||||
"column.home": "Acuèlh",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "Listas",
|
||||
"column.mutes": "Personas rescondudas",
|
||||
"column.notifications": "Notificacions",
|
||||
"column.pins": "Tuts penjats",
|
||||
@@ -63,8 +63,8 @@
|
||||
"confirmations.block.message": "Sètz segur de voler blocar {name} ?",
|
||||
"confirmations.delete.confirm": "Escafar",
|
||||
"confirmations.delete.message": "Sètz segur de voler escafar l’estatut ?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.confirm": "Suprimir",
|
||||
"confirmations.delete_list.message": "Sètz segur de voler suprimir aquesta lista per totjorn ?",
|
||||
"confirmations.domain_block.confirm": "Amagar tot lo domeni",
|
||||
"confirmations.domain_block.message": "Sètz segur segur de voler blocar completament {domain} ? De còps cal pas que blocar o rescondre unas personas solament.",
|
||||
"confirmations.mute.confirm": "Rescondre",
|
||||
@@ -72,7 +72,7 @@
|
||||
"confirmations.unfollow.confirm": "Quitar de sègre",
|
||||
"confirmations.unfollow.message": "Volètz vertadièrament quitar de sègre {name} ?",
|
||||
"embed.instructions": "Embarcar aqueste estatut per lo far veire sus un site Internet en copiar lo còdi çai-jos.",
|
||||
"embed.preview": "Semblarà aquò : ",
|
||||
"embed.preview": "Semblarà aquò :",
|
||||
"emoji_button.activity": "Activitats",
|
||||
"emoji_button.custom": "Personalizats",
|
||||
"emoji_button.flags": "Drapèus",
|
||||
@@ -84,16 +84,16 @@
|
||||
"emoji_button.people": "Gents",
|
||||
"emoji_button.recent": "Sovent utilizats",
|
||||
"emoji_button.search": "Cercar…",
|
||||
"emoji_button.search_results": "Resultat de recèrca",
|
||||
"emoji_button.search_results": "Resultats de recèrca",
|
||||
"emoji_button.symbols": "Simbòls",
|
||||
"emoji_button.travel": "Viatges & lòcs",
|
||||
"empty_column.community": "Lo flux public local es void. Escrivètz quicòm per lo garnir !",
|
||||
"empty_column.hashtag": "I a pas encara de contengut ligat a aqueste hashtag",
|
||||
"empty_column.hashtag": "I a pas encara de contengut ligat a aquesta etiqueta.",
|
||||
"empty_column.home": "Vòstre flux d’acuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a d’autras personas.",
|
||||
"empty_column.home.public_timeline": "lo flux public",
|
||||
"empty_column.list": "I a pas res dins la lista pel moment.",
|
||||
"empty_column.list": "I a pas res dins la lista pel moment. Quand de membres d’aquesta lista publiquen de novèls estatuts los veiretz aquí.",
|
||||
"empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualqu’un per començar una conversacion.",
|
||||
"empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autras instàncias per garnir lo flux public.",
|
||||
"empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autras instàncias per garnir lo flux public",
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Regetar",
|
||||
"getting_started.appsshort": "Apps",
|
||||
@@ -116,7 +116,7 @@
|
||||
"keyboard_shortcuts.enter": "per dobrir los estatuts",
|
||||
"keyboard_shortcuts.favourite": "per apondre als favorits",
|
||||
"keyboard_shortcuts.heading": "Acorchis clavièr",
|
||||
"keyboard_shortcuts.hotkey": "Clau",
|
||||
"keyboard_shortcuts.hotkey": "Acorchis",
|
||||
"keyboard_shortcuts.legend": "per mostrar aquesta legenda",
|
||||
"keyboard_shortcuts.mention": "per mencionar l’autor",
|
||||
"keyboard_shortcuts.reply": "per respondre",
|
||||
@@ -127,35 +127,35 @@
|
||||
"lightbox.close": "Tampar",
|
||||
"lightbox.next": "Seguent",
|
||||
"lightbox.previous": "Precedent",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.account.add": "Ajustar a la lista",
|
||||
"lists.account.remove": "Levar de la lista",
|
||||
"lists.delete": "Suprimir la lista",
|
||||
"lists.edit": "Modificar la lista",
|
||||
"lists.new.create": "Ajustar una lista",
|
||||
"lists.new.title_placeholder": "Títol de la nòva lista",
|
||||
"lists.search": "Cercar demest lo monde que seguètz",
|
||||
"lists.subheading": "Vòstras listas",
|
||||
"loading_indicator.label": "Cargament…",
|
||||
"media_gallery.toggle_visible": "Modificar la visibilitat",
|
||||
"missing_indicator.label": "Pas trobat",
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"mute_modal.hide_notifications": "Rescondre las notificacions d’aquesta persona ?",
|
||||
"navigation_bar.blocks": "Personas blocadas",
|
||||
"navigation_bar.community_timeline": "Flux public local",
|
||||
"navigation_bar.edit_profile": "Modificar lo perfil",
|
||||
"navigation_bar.favourites": "Favorits",
|
||||
"navigation_bar.follow_requests": "Demandas d'abonament",
|
||||
"navigation_bar.follow_requests": "Demandas d’abonament",
|
||||
"navigation_bar.info": "Mai informacions",
|
||||
"navigation_bar.keyboard_shortcuts": "Acorchis clavièr",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.lists": "Listas",
|
||||
"navigation_bar.logout": "Desconnexion",
|
||||
"navigation_bar.mutes": "Personas rescondudas",
|
||||
"navigation_bar.pins": "Tuts penjats",
|
||||
"navigation_bar.preferences": "Preferéncias",
|
||||
"navigation_bar.public_timeline": "Flux public global",
|
||||
"notification.favourite": "{name} a ajustat a sos favorits :",
|
||||
"notification.favourite": "{name} a ajustat a sos favorits",
|
||||
"notification.follow": "{name} vos sèc",
|
||||
"notification.mention": "{name} vos a mencionat :",
|
||||
"notification.reblog": "{name} a partejat vòstre estatut :",
|
||||
"notification.mention": "{name} vos a mencionat",
|
||||
"notification.reblog": "{name} a partejat vòstre estatut",
|
||||
"notifications.clear": "Escafar",
|
||||
"notifications.clear_confirmation": "Volètz vertadièrament escafar totas vòstras las notificacions ?",
|
||||
"notifications.column_settings.alert": "Notificacions localas",
|
||||
@@ -171,7 +171,7 @@
|
||||
"onboarding.next": "Seguent",
|
||||
"onboarding.page_five.public_timelines": "Lo flux local mòstra los estatuts publics del monde de vòstra instància, aquí {domain}. Lo flux federat mòstra los estatuts publics de la gent que los de {domain} sègon. Son los fluxes publics, un bon biais de trobar de mond.",
|
||||
"onboarding.page_four.home": "Lo flux d’acuèlh mòstra los estatuts del mond que seguètz.",
|
||||
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualqu’un interagís amb vos",
|
||||
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualqu’un interagís amb vos.",
|
||||
"onboarding.page_one.federation": "Mastodon es un malhum de servidors independents que comunican per construire un malhum mai larg. Òm los apèla instàncias.",
|
||||
"onboarding.page_one.handle": "Sètz sus {domain}, doncas vòstre identificant complet es {handle}",
|
||||
"onboarding.page_one.welcome": "Benvengut a Mastodon !",
|
||||
@@ -209,7 +209,7 @@
|
||||
"search_popout.search_format": "Format recèrca avançada",
|
||||
"search_popout.tips.hashtag": "etiqueta",
|
||||
"search_popout.tips.status": "estatut",
|
||||
"search_popout.tips.text": "Tèxt brut tòrna escais, noms d’utilizaire e etiquetas correspondents",
|
||||
"search_popout.tips.text": "Lo tèxt brut tòrna escais, noms d’utilizaire e etiquetas correspondents",
|
||||
"search_popout.tips.user": "utilizaire",
|
||||
"search_results.total": "{count, number} {count, plural, one {resultat} other {resultats}}",
|
||||
"standalone.public_title": "Una ulhada dedins…",
|
||||
@@ -225,7 +225,7 @@
|
||||
"status.open": "Desplegar aqueste estatut",
|
||||
"status.pin": "Penjar al perfil",
|
||||
"status.reblog": "Partejar",
|
||||
"status.reblogged_by": "{name} a partejat :",
|
||||
"status.reblogged_by": "{name} a partejat",
|
||||
"status.reply": "Respondre",
|
||||
"status.replyAll": "Respondre a la conversacion",
|
||||
"status.report": "Senhalar @{name}",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"column.favourites": "Favoritos",
|
||||
"column.follow_requests": "Seguidores pendentes",
|
||||
"column.home": "Página inicial",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "Listas",
|
||||
"column.mutes": "Usuários silenciados",
|
||||
"column.notifications": "Notificações",
|
||||
"column.pins": "Postagens fixadas",
|
||||
@@ -64,7 +64,7 @@
|
||||
"confirmations.delete.confirm": "Excluir",
|
||||
"confirmations.delete.message": "Você tem certeza de que quer excluir esta postagem?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.message": "Você tem certeza que quer deletar permanentemente a lista?",
|
||||
"confirmations.domain_block.confirm": "Esconder o domínio inteiro",
|
||||
"confirmations.domain_block.message": "Você quer mesmo bloquear {domain} inteiro? Na maioria dos casos, silenciar ou bloquear alguns usuários é o suficiente e o recomendado.",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
@@ -109,44 +109,44 @@
|
||||
"home.settings": "Configurações de colunas",
|
||||
"keyboard_shortcuts.back": "para navegar de volta",
|
||||
"keyboard_shortcuts.boost": "para compartilhar",
|
||||
"keyboard_shortcuts.column": "to focus a status in one of the columns",
|
||||
"keyboard_shortcuts.compose": "to focus the compose textarea",
|
||||
"keyboard_shortcuts.column": "Focar um status em uma das colunas",
|
||||
"keyboard_shortcuts.compose": "para focar a área de redação",
|
||||
"keyboard_shortcuts.description": "Description",
|
||||
"keyboard_shortcuts.down": "to move down in the list",
|
||||
"keyboard_shortcuts.down": "para mover para baixo na lista",
|
||||
"keyboard_shortcuts.enter": "to open status",
|
||||
"keyboard_shortcuts.favourite": "to favourite",
|
||||
"keyboard_shortcuts.favourite": "para adicionar aos favoritos",
|
||||
"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.hotkey": "Atalho",
|
||||
"keyboard_shortcuts.legend": "para mostrar essa legenda",
|
||||
"keyboard_shortcuts.mention": "para mencionar o autor",
|
||||
"keyboard_shortcuts.reply": "para responder",
|
||||
"keyboard_shortcuts.search": "para focar a pesquisa",
|
||||
"keyboard_shortcuts.toot": "para compor um novo toot",
|
||||
"keyboard_shortcuts.unfocus": "para remover o foco da área de composição/pesquisa",
|
||||
"keyboard_shortcuts.up": "para mover para cima na lista",
|
||||
"lightbox.close": "Fechar",
|
||||
"lightbox.next": "Próximo",
|
||||
"lightbox.previous": "Anterior",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.account.add": "Adicionar a listas",
|
||||
"lists.account.remove": "Remover da lista",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.edit": "Editar lista",
|
||||
"lists.new.create": "Adicionar lista",
|
||||
"lists.new.title_placeholder": "Novo título da lista",
|
||||
"lists.search": "Procurar entre as pessoas que você segue",
|
||||
"lists.subheading": "Suas listas",
|
||||
"loading_indicator.label": "Carregando...",
|
||||
"media_gallery.toggle_visible": "Esconder/Mostrar",
|
||||
"missing_indicator.label": "Não encontrado",
|
||||
"mute_modal.hide_notifications": "Hide notifications from this user?",
|
||||
"mute_modal.hide_notifications": "Esconder notificações deste usuário?",
|
||||
"navigation_bar.blocks": "Usuários bloqueados",
|
||||
"navigation_bar.community_timeline": "Local",
|
||||
"navigation_bar.edit_profile": "Editar perfil",
|
||||
"navigation_bar.favourites": "Favoritos",
|
||||
"navigation_bar.follow_requests": "Seguidores pendentes",
|
||||
"navigation_bar.info": "Mais informações",
|
||||
"navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.keyboard_shortcuts": "Atalhos de teclado",
|
||||
"navigation_bar.lists": "Listas",
|
||||
"navigation_bar.logout": "Sair",
|
||||
"navigation_bar.mutes": "Usuários silenciados",
|
||||
"navigation_bar.pins": "Postagens fixadas",
|
||||
@@ -177,7 +177,7 @@
|
||||
"onboarding.page_one.welcome": "Seja bem-vindo(a) ao Mastodon!",
|
||||
"onboarding.page_six.admin": "O administrador de sua instância é {admin}.",
|
||||
"onboarding.page_six.almost_done": "Quase acabando...",
|
||||
"onboarding.page_six.appetoot": "Bon Appetoot!",
|
||||
"onboarding.page_six.appetoot": "Bom Apetoot!",
|
||||
"onboarding.page_six.apps_available": "Há {apps} disponíveis para iOS, Android e outras plataformas.",
|
||||
"onboarding.page_six.github": "Mastodon é um software gratuito e de código aberto. Você pode reportar bugs, prequisitar novas funções ou contribuir para o código no {github}.",
|
||||
"onboarding.page_six.guidelines": "diretrizes da comunidade",
|
||||
@@ -220,7 +220,7 @@
|
||||
"status.load_more": "Carregar mais",
|
||||
"status.media_hidden": "Mídia escondida",
|
||||
"status.mention": "Mencionar @{name}",
|
||||
"status.more": "More",
|
||||
"status.more": "Mais",
|
||||
"status.mute_conversation": "Silenciar conversa",
|
||||
"status.open": "Expandir",
|
||||
"status.pin": "Fixar no perfil",
|
||||
@@ -241,7 +241,7 @@
|
||||
"tabs_bar.home": "Página inicial",
|
||||
"tabs_bar.local_timeline": "Local",
|
||||
"tabs_bar.notifications": "Notificações",
|
||||
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
|
||||
"ui.beforeunload": "Seu rascunho será perdido se você sair do Mastodon.",
|
||||
"upload_area.title": "Arraste e solte para enviar",
|
||||
"upload_button.label": "Adicionar mídia",
|
||||
"upload_form.description": "Descreva a imagem para deficientes visuais",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"account.block": "Bloquear @{name}",
|
||||
"account.block_domain": "Esconder tudo do domínio {domain}",
|
||||
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
|
||||
"account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de forma incompleta.",
|
||||
"account.edit_profile": "Editar perfil",
|
||||
"account.follow": "Seguir",
|
||||
"account.followers": "Seguidores",
|
||||
@@ -19,7 +19,7 @@
|
||||
"account.share": "Partilhar o perfil @{name}",
|
||||
"account.show_reblogs": "Mostrar partilhas de @{name}",
|
||||
"account.unblock": "Não bloquear @{name}",
|
||||
"account.unblock_domain": "Unhide {domain}",
|
||||
"account.unblock_domain": "Mostrar {domain}",
|
||||
"account.unfollow": "Deixar de seguir",
|
||||
"account.unmute": "Não silenciar @{name}",
|
||||
"account.unmute_notifications": "Deixar de silenciar @{name}",
|
||||
@@ -36,7 +36,7 @@
|
||||
"column.favourites": "Favoritos",
|
||||
"column.follow_requests": "Seguidores Pendentes",
|
||||
"column.home": "Home",
|
||||
"column.lists": "Lists",
|
||||
"column.lists": "Listas",
|
||||
"column.mutes": "Utilizadores silenciados",
|
||||
"column.notifications": "Notificações",
|
||||
"column.pins": "Pinned toot",
|
||||
@@ -64,7 +64,7 @@
|
||||
"confirmations.delete.confirm": "Eliminar",
|
||||
"confirmations.delete.message": "De certeza que queres eliminar esta publicação?",
|
||||
"confirmations.delete_list.confirm": "Delete",
|
||||
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
|
||||
"confirmations.delete_list.message": "Tens a certeza de que desejas apagar permanentemente esta lista?",
|
||||
"confirmations.domain_block.confirm": "Esconder tudo deste domínio",
|
||||
"confirmations.domain_block.message": "De certeza que queres bloquear por completo o domínio {domain}? Na maioria dos casos, silenciar ou bloquear alguns utilizadores é o suficiente e o recomendado.",
|
||||
"confirmations.mute.confirm": "Silenciar",
|
||||
@@ -88,12 +88,12 @@
|
||||
"emoji_button.symbols": "Símbolos",
|
||||
"emoji_button.travel": "Viagens & Lugares",
|
||||
"empty_column.community": "Ainda não existe conteúdo local para mostrar!",
|
||||
"empty_column.hashtag": "Não foram encontradas publicações com essa hashtag",
|
||||
"empty_column.hashtag": "Não foram encontradas publicações com essa hashtag.",
|
||||
"empty_column.home": "Ainda não segues qualquer utilizador. Visita {public} ou utiliza a pesquisa para procurar outros utilizadores.",
|
||||
"empty_column.home.public_timeline": "global",
|
||||
"empty_column.list": "Ainda não existem publicações nesta lista.",
|
||||
"empty_column.notifications": "Não tens notificações. Interage com outros utilizadores para iniciar uma conversa.",
|
||||
"empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para ver aqui os conteúdos públicos.",
|
||||
"empty_column.public": "Não há nada aqui! Escreve algo publicamente ou segue outros utilizadores para ver aqui os conteúdos públicos",
|
||||
"follow_request.authorize": "Autorizar",
|
||||
"follow_request.reject": "Rejeitar",
|
||||
"getting_started.appsshort": "Aplicações",
|
||||
@@ -116,7 +116,7 @@
|
||||
"keyboard_shortcuts.enter": "para expandir uma publicação",
|
||||
"keyboard_shortcuts.favourite": "para adicionar aos favoritos",
|
||||
"keyboard_shortcuts.heading": "Atalhos do teclado",
|
||||
"keyboard_shortcuts.hotkey": "Hotkey",
|
||||
"keyboard_shortcuts.hotkey": "Atalho",
|
||||
"keyboard_shortcuts.legend": "para mostrar esta legenda",
|
||||
"keyboard_shortcuts.mention": "para mencionar o autor",
|
||||
"keyboard_shortcuts.reply": "para responder",
|
||||
@@ -127,14 +127,14 @@
|
||||
"lightbox.close": "Fechar",
|
||||
"lightbox.next": "Próximo",
|
||||
"lightbox.previous": "Anterior",
|
||||
"lists.account.add": "Add to list",
|
||||
"lists.account.remove": "Remove from list",
|
||||
"lists.account.add": "Adicionar à lista",
|
||||
"lists.account.remove": "Remover da lista",
|
||||
"lists.delete": "Delete list",
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.subheading": "Your lists",
|
||||
"lists.edit": "Editar lista",
|
||||
"lists.new.create": "Adicionar lista",
|
||||
"lists.new.title_placeholder": "Novo título da lista",
|
||||
"lists.search": "Pesquisa entre as pessoas que segues",
|
||||
"lists.subheading": "As tuas listas",
|
||||
"loading_indicator.label": "A carregar...",
|
||||
"media_gallery.toggle_visible": "Esconder/Mostrar",
|
||||
"missing_indicator.label": "Não encontrado",
|
||||
@@ -146,7 +146,7 @@
|
||||
"navigation_bar.follow_requests": "Seguidores pendentes",
|
||||
"navigation_bar.info": "Mais informações",
|
||||
"navigation_bar.keyboard_shortcuts": "Atalhos de teclado",
|
||||
"navigation_bar.lists": "Lists",
|
||||
"navigation_bar.lists": "Listas",
|
||||
"navigation_bar.logout": "Sair",
|
||||
"navigation_bar.mutes": "Utilizadores silenciados",
|
||||
"navigation_bar.pins": "Posts fixos",
|
||||
@@ -209,13 +209,13 @@
|
||||
"search_popout.search_format": "Formato avançado de pesquisa",
|
||||
"search_popout.tips.hashtag": "hashtag",
|
||||
"search_popout.tips.status": "status",
|
||||
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
|
||||
"search_popout.tips.text": "O texto simples retorna a correspondência de nomes, utilizadores e hashtags",
|
||||
"search_popout.tips.user": "utilizador",
|
||||
"search_results.total": "{count, number} {count, plural, one {resultado} other {resultados}}",
|
||||
"standalone.public_title": "Espreitar lá dentro...",
|
||||
"status.cannot_reblog": "Este post não pode ser partilhado",
|
||||
"status.delete": "Eliminar",
|
||||
"status.embed": "Embed",
|
||||
"status.embed": "Incorporar",
|
||||
"status.favourite": "Adicionar aos favoritos",
|
||||
"status.load_more": "Carregar mais",
|
||||
"status.media_hidden": "Media escondida",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Загрузка...",
|
||||
"media_gallery.toggle_visible": "Показать/скрыть",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Laddar...",
|
||||
"media_gallery.toggle_visible": "Växla synlighet",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Loading...",
|
||||
"media_gallery.toggle_visible": "Toggle visibility",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Yükleniyor...",
|
||||
"media_gallery.toggle_visible": "Görünürlüğü değiştir",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "Завантаження...",
|
||||
"media_gallery.toggle_visible": "Показати/приховати",
|
||||
|
||||
2
app/javascript/mastodon/locales/whitelist_gl.json
Normal file
2
app/javascript/mastodon/locales/whitelist_gl.json
Normal file
@@ -0,0 +1,2 @@
|
||||
[
|
||||
]
|
||||
@@ -25,11 +25,11 @@
|
||||
"account.unmute_notifications": "不再隐藏来自 @{name} 的通知",
|
||||
"account.view_full_profile": "查看完整资料",
|
||||
"boost_modal.combo": "下次按住 {combo} 即可跳过此提示",
|
||||
"bundle_column_error.body": "载入组件出错。",
|
||||
"bundle_column_error.body": "载入这个组件时发生了错误。",
|
||||
"bundle_column_error.retry": "重试",
|
||||
"bundle_column_error.title": "网络错误",
|
||||
"bundle_modal_error.close": "关闭",
|
||||
"bundle_modal_error.message": "载入组件出错。",
|
||||
"bundle_modal_error.message": "载入这个组件时发生了错误。",
|
||||
"bundle_modal_error.retry": "重试",
|
||||
"column.blocks": "屏蔽用户",
|
||||
"column.community": "本站时间轴",
|
||||
@@ -50,8 +50,8 @@
|
||||
"column_header.unpin": "取消固定",
|
||||
"column_subheading.navigation": "导航",
|
||||
"column_subheading.settings": "设置",
|
||||
"compose_form.lock_disclaimer": "你的帐户没有{locked}。任何人都可以通过关注你来查看仅关注者可见的嘟文。",
|
||||
"compose_form.lock_disclaimer.lock": "被保护",
|
||||
"compose_form.lock_disclaimer": "你的帐户没有{locked}。任何人都可以在关注你后立即查看仅关注者可见的嘟文。",
|
||||
"compose_form.lock_disclaimer.lock": "开启保护",
|
||||
"compose_form.placeholder": "在想啥?",
|
||||
"compose_form.publish": "嘟嘟",
|
||||
"compose_form.publish_loud": "{publish}!",
|
||||
@@ -60,17 +60,17 @@
|
||||
"compose_form.spoiler_placeholder": "折叠部分的警告消息",
|
||||
"confirmation_modal.cancel": "取消",
|
||||
"confirmations.block.confirm": "屏蔽",
|
||||
"confirmations.block.message": "想好了,真的要屏蔽 {name}?",
|
||||
"confirmations.block.message": "你确定要屏蔽 {name} 吗?",
|
||||
"confirmations.delete.confirm": "删除",
|
||||
"confirmations.delete.message": "想好了,真的要删除这条嘟文?",
|
||||
"confirmations.delete.message": "你确定要删除这条嘟文吗?",
|
||||
"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.mute.message": "你确定要隐藏 {name} 吗?",
|
||||
"confirmations.unfollow.confirm": "取消关注",
|
||||
"confirmations.unfollow.message": "确定要取消关注 {name} 吗?",
|
||||
"confirmations.unfollow.message": "你确定要取消关注 {name} 吗?",
|
||||
"embed.instructions": "要在你的网站上嵌入这条嘟文,请复制以下代码。",
|
||||
"embed.preview": "它会像这样显示出来:",
|
||||
"emoji_button.activity": "活动",
|
||||
@@ -91,9 +91,9 @@
|
||||
"empty_column.hashtag": "这个话题标签下暂时没有内容。",
|
||||
"empty_column.home": "你还没有关注任何用户。快看看{public},向其他用户搭讪吧。",
|
||||
"empty_column.home.public_timeline": "公共时间轴",
|
||||
"empty_column.list": "这个列表中暂时没有内容。",
|
||||
"empty_column.notifications": "你还没有收到过通知信息,快向其他用户搭讪吧。",
|
||||
"empty_column.public": "这里神马都没有!写一些公开的嘟文,或者关注其他实例的用户,这里就会有嘟文出现了哦!",
|
||||
"empty_column.list": "这个列表中暂时没有内容。列表中用户所发送的的新嘟文将会在这里显示。",
|
||||
"empty_column.notifications": "你还没有收到过任何通知,快向其他用户搭讪吧。",
|
||||
"empty_column.public": "这里神马都没有!写一些公开的嘟文,或者关注其他实例的用户后,这里就会有嘟文出现了哦!",
|
||||
"follow_request.authorize": "同意",
|
||||
"follow_request.reject": "拒绝",
|
||||
"getting_started.appsshort": "应用",
|
||||
@@ -138,7 +138,7 @@
|
||||
"loading_indicator.label": "加载中……",
|
||||
"media_gallery.toggle_visible": "切换显示/隐藏",
|
||||
"missing_indicator.label": "找不到内容",
|
||||
"mute_modal.hide_notifications": "隐藏来自这个用户的通知",
|
||||
"mute_modal.hide_notifications": "同时隐藏来自这个用户的通知",
|
||||
"navigation_bar.blocks": "被屏蔽的用户",
|
||||
"navigation_bar.community_timeline": "本站时间轴",
|
||||
"navigation_bar.edit_profile": "修改个人资料",
|
||||
@@ -157,25 +157,25 @@
|
||||
"notification.mention": "{name} 提及你",
|
||||
"notification.reblog": "{name} 转嘟了你的嘟文",
|
||||
"notifications.clear": "清空通知列表",
|
||||
"notifications.clear_confirmation": "你确定要清空通知列表吗?",
|
||||
"notifications.clear_confirmation": "你确定要永久清空通知列表吗?",
|
||||
"notifications.column_settings.alert": "桌面通知",
|
||||
"notifications.column_settings.favourite": "你的嘟文被收藏:",
|
||||
"notifications.column_settings.follow": "关注你:",
|
||||
"notifications.column_settings.mention": "提及你:",
|
||||
"notifications.column_settings.favourite": "当你的嘟文被收藏时:",
|
||||
"notifications.column_settings.follow": "当有人关注你时:",
|
||||
"notifications.column_settings.mention": "当有人在嘟文中提及你时:",
|
||||
"notifications.column_settings.push": "推送通知",
|
||||
"notifications.column_settings.push_meta": "此设备",
|
||||
"notifications.column_settings.reblog": "你的嘟文被转嘟:",
|
||||
"notifications.column_settings.reblog": "当有人转嘟了你的嘟文时:",
|
||||
"notifications.column_settings.show": "在通知栏显示",
|
||||
"notifications.column_settings.sound": "播放音效",
|
||||
"onboarding.done": "出发!",
|
||||
"onboarding.next": "下一步",
|
||||
"onboarding.page_five.public_timelines": "本站时间轴显示的是由本站({domain})用户发布的所有公开嘟文。跨站公共时间轴显示的的是由本站用户关注对象所发布的所有公开嘟文。这些就是寻人好去处的公共时间轴啦。",
|
||||
"onboarding.page_four.home": "你的主页上的时间轴上显示的是你关注对象的嘟文。",
|
||||
"onboarding.page_four.notifications": "如果有人与你互动,便会出现在通知栏中哦~",
|
||||
"onboarding.page_one.federation": "Mastodon 是由一系列独立的服务器共同打造的强大的社交网络,我们将这些各自独立但又相互连接的服务器叫做实例。",
|
||||
"onboarding.page_one.handle": "你在 {domain},{handle} 就是你的完整帐户名称。",
|
||||
"onboarding.page_four.home": "你的主页时间轴上显示的是你的关注对象所发布的嘟文。",
|
||||
"onboarding.page_four.notifications": "如果有人与你互动了,他们就会出现在通知栏中哦~",
|
||||
"onboarding.page_one.federation": "Mastodon 是由一系列独立的服务器共同打造的强大的社交网络,我们将这些各自独立而又相互连接的服务器叫做实例。",
|
||||
"onboarding.page_one.handle": "你是在 {domain} 上注册的,所以你的完整用户地址是 {handle}。",
|
||||
"onboarding.page_one.welcome": "欢迎来到 Mastodon!",
|
||||
"onboarding.page_six.admin": "{admin} 是你所在服务器实例的管理员.",
|
||||
"onboarding.page_six.admin": "{admin} 是你所在服务器实例的管理员。",
|
||||
"onboarding.page_six.almost_done": "差不多了……",
|
||||
"onboarding.page_six.appetoot": "嗷呜~",
|
||||
"onboarding.page_six.apps_available": "我们还有适用于 iOS、Android 和其它平台的{apps}哦~",
|
||||
@@ -184,8 +184,8 @@
|
||||
"onboarding.page_six.read_guidelines": "别忘了看看 {domain} 的{guidelines}!",
|
||||
"onboarding.page_six.various_app": "移动设备应用",
|
||||
"onboarding.page_three.profile": "你可以修改你的个人资料,比如头像、简介和昵称等偏好设置。",
|
||||
"onboarding.page_three.search": "你可以通过搜索功能寻找用户和话题标签,比如{illustration}或者{introductions}。如果你想搜索其他实例上的用户,就需要输入完整帐户名称(用户名@域名)哦。",
|
||||
"onboarding.page_two.compose": "在撰写栏中开始嘟嘟吧!下方的按钮分别用来上传图片,修改嘟文可见范围,以及添加警告信息。",
|
||||
"onboarding.page_three.search": "你可以通过搜索功能寻找用户和话题标签,比如{illustration}或者{introductions}。如果你想搜索其他实例上的用户,就需要输入完整用户地址(@用户名@域名)哦。",
|
||||
"onboarding.page_two.compose": "在撰写栏中开始嘟嘟吧!下方的按钮分别可以用来上传图片、修改嘟文可见范围,以及添加警告信息。",
|
||||
"onboarding.skip": "跳过",
|
||||
"privacy.change": "设置嘟文可见范围",
|
||||
"privacy.direct.long": "只有被提及的用户能看到",
|
||||
@@ -196,11 +196,11 @@
|
||||
"privacy.public.short": "公开",
|
||||
"privacy.unlisted.long": "所有人可见,但不会出现在公共时间轴上",
|
||||
"privacy.unlisted.short": "不公开",
|
||||
"relative_time.days": "{number} 天",
|
||||
"relative_time.hours": "{number} 时",
|
||||
"relative_time.days": "{number}天",
|
||||
"relative_time.hours": "{number}时",
|
||||
"relative_time.just_now": "刚刚",
|
||||
"relative_time.minutes": "{number} 分",
|
||||
"relative_time.seconds": "{number} 秒",
|
||||
"relative_time.minutes": "{number}分",
|
||||
"relative_time.seconds": "{number}秒",
|
||||
"reply_indicator.cancel": "取消",
|
||||
"report.placeholder": "附言",
|
||||
"report.submit": "提交",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "載入中...",
|
||||
"media_gallery.toggle_visible": "打開或關上",
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
"lists.edit": "Edit list",
|
||||
"lists.new.create": "Add list",
|
||||
"lists.new.title_placeholder": "New list title",
|
||||
"lists.search": "Search among follows",
|
||||
"lists.search": "Search among people you follow",
|
||||
"lists.subheading": "Your lists",
|
||||
"loading_indicator.label": "讀取中...",
|
||||
"media_gallery.toggle_visible": "切換可見性",
|
||||
|
||||
@@ -15,7 +15,7 @@ const play = audio => {
|
||||
if (typeof audio.fastSeek === 'function') {
|
||||
audio.fastSeek(0);
|
||||
} else {
|
||||
audio.seek(0);
|
||||
audio.currentTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import {
|
||||
FAVOURITED_STATUSES_FETCH_REQUEST,
|
||||
FAVOURITED_STATUSES_FETCH_SUCCESS,
|
||||
FAVOURITED_STATUSES_FETCH_FAIL,
|
||||
FAVOURITED_STATUSES_EXPAND_REQUEST,
|
||||
FAVOURITED_STATUSES_EXPAND_SUCCESS,
|
||||
FAVOURITED_STATUSES_EXPAND_FAIL,
|
||||
} from '../actions/favourites';
|
||||
import {
|
||||
PINNED_STATUSES_FETCH_SUCCESS,
|
||||
@@ -30,6 +34,7 @@ const normalizeList = (state, listType, statuses, next) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('next', next);
|
||||
map.set('loaded', true);
|
||||
map.set('isLoading', false);
|
||||
map.set('items', ImmutableList(statuses.map(item => item.id)));
|
||||
}));
|
||||
};
|
||||
@@ -37,6 +42,7 @@ const normalizeList = (state, listType, statuses, next) => {
|
||||
const appendToList = (state, listType, statuses, next) => {
|
||||
return state.update(listType, listMap => listMap.withMutations(map => {
|
||||
map.set('next', next);
|
||||
map.set('isLoading', false);
|
||||
map.set('items', map.get('items').concat(statuses.map(item => item.id)));
|
||||
}));
|
||||
};
|
||||
@@ -55,6 +61,12 @@ const removeOneFromList = (state, listType, status) => {
|
||||
|
||||
export default function statusLists(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case FAVOURITED_STATUSES_FETCH_REQUEST:
|
||||
case FAVOURITED_STATUSES_EXPAND_REQUEST:
|
||||
return state.setIn(['favourites', 'isLoading'], true);
|
||||
case FAVOURITED_STATUSES_FETCH_FAIL:
|
||||
case FAVOURITED_STATUSES_EXPAND_FAIL:
|
||||
return state.setIn(['favourites', 'isLoading'], false);
|
||||
case FAVOURITED_STATUSES_FETCH_SUCCESS:
|
||||
return normalizeList(state, 'favourites', action.statuses, action.next);
|
||||
case FAVOURITED_STATUSES_EXPAND_SUCCESS:
|
||||
|
||||
46
app/javascript/mastodon/settings.js
Normal file
46
app/javascript/mastodon/settings.js
Normal file
@@ -0,0 +1,46 @@
|
||||
export default class Settings {
|
||||
|
||||
constructor(keyBase = null) {
|
||||
this.keyBase = keyBase;
|
||||
}
|
||||
|
||||
generateKey(id) {
|
||||
return this.keyBase ? [this.keyBase, `id${id}`].join('.') : id;
|
||||
}
|
||||
|
||||
set(id, data) {
|
||||
const key = this.generateKey(id);
|
||||
try {
|
||||
const encodedData = JSON.stringify(data);
|
||||
localStorage.setItem(key, encodedData);
|
||||
return data;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
get(id) {
|
||||
const key = this.generateKey(id);
|
||||
try {
|
||||
const rawData = localStorage.getItem(key);
|
||||
return JSON.parse(rawData);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
remove(id) {
|
||||
const data = this.get(id);
|
||||
if (data) {
|
||||
const key = this.generateKey(id);
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const pushNotificationsSetting = new Settings('mastodon_push_notification_data');
|
||||
@@ -62,7 +62,13 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
|
||||
|
||||
|
||||
export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) {
|
||||
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?access_token=${accessToken}&stream=${stream}`);
|
||||
const params = [ `stream=${stream}` ];
|
||||
|
||||
if (accessToken !== null) {
|
||||
params.push(`access_token=${accessToken}`);
|
||||
}
|
||||
|
||||
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`);
|
||||
|
||||
ws.onopen = connected;
|
||||
ws.onmessage = e => received(JSON.parse(e.data));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios from 'axios';
|
||||
import { store } from './containers/mastodon';
|
||||
import { setBrowserSupport, setSubscription, clearSubscription } from './actions/push_notifications';
|
||||
import { pushNotificationsSetting } from './settings';
|
||||
|
||||
// Taken from https://www.npmjs.com/package/web-push
|
||||
const urlBase64ToUint8Array = (base64String) => {
|
||||
@@ -35,16 +36,33 @@ const subscribe = (registration) =>
|
||||
const unsubscribe = ({ registration, subscription }) =>
|
||||
subscription ? subscription.unsubscribe().then(() => registration) : registration;
|
||||
|
||||
const sendSubscriptionToBackend = (subscription) =>
|
||||
axios.post('/api/web/push_subscriptions', {
|
||||
subscription,
|
||||
}).then(response => response.data);
|
||||
const sendSubscriptionToBackend = (subscription) => {
|
||||
const params = { subscription };
|
||||
|
||||
const me = store.getState().getIn(['meta', 'me']);
|
||||
if (me) {
|
||||
const data = pushNotificationsSetting.get(me);
|
||||
if (data) {
|
||||
params.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
return axios.post('/api/web/push_subscriptions', params).then(response => response.data);
|
||||
};
|
||||
|
||||
// Last one checks for payload support: https://web-push-book.gauntface.com/chapter-06/01-non-standards-browsers/#no-payload
|
||||
const supportsPushNotifications = ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in PushSubscription.prototype);
|
||||
|
||||
export function register () {
|
||||
store.dispatch(setBrowserSupport(supportsPushNotifications));
|
||||
const me = store.getState().getIn(['meta', 'me']);
|
||||
|
||||
if (me && !pushNotificationsSetting.get(me)) {
|
||||
const alerts = store.getState().getIn(['push_notifications', 'alerts']);
|
||||
if (alerts) {
|
||||
pushNotificationsSetting.set(me, { alerts: alerts });
|
||||
}
|
||||
}
|
||||
|
||||
if (supportsPushNotifications) {
|
||||
if (!getApplicationServerKey()) {
|
||||
@@ -79,6 +97,9 @@ export function register () {
|
||||
// it means that the backend subscription is valid (and was set during hydration)
|
||||
if (!(subscription instanceof PushSubscription)) {
|
||||
store.dispatch(setSubscription(subscription));
|
||||
if (me) {
|
||||
pushNotificationsSetting.set(me, { alerts: subscription.alerts });
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -90,6 +111,9 @@ export function register () {
|
||||
|
||||
// Clear alerts and hide UI settings
|
||||
store.dispatch(clearSubscription());
|
||||
if (me) {
|
||||
pushNotificationsSetting.remove(me);
|
||||
}
|
||||
|
||||
try {
|
||||
getRegistration()
|
||||
|
||||
@@ -265,198 +265,286 @@
|
||||
|
||||
.compose-form {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.compose-form__warning {
|
||||
color: darken($ui-secondary-color, 65%);
|
||||
margin-bottom: 15px;
|
||||
background: $ui-primary-color;
|
||||
box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
|
||||
padding: 8px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
|
||||
strong {
|
||||
.compose-form__warning {
|
||||
color: darken($ui-secondary-color, 65%);
|
||||
font-weight: 500;
|
||||
margin-bottom: 15px;
|
||||
background: $ui-primary-color;
|
||||
box-shadow: 0 2px 6px rgba($base-shadow-color, 0.3);
|
||||
padding: 8px 10px;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: darken($ui-primary-color, 33%);
|
||||
font-weight: 500;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__modifiers {
|
||||
color: $ui-base-color;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
background: $simple-background-color;
|
||||
border-radius: 0 0 4px;
|
||||
}
|
||||
|
||||
.compose-form__buttons-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.compose-form__buttons {
|
||||
padding: 10px;
|
||||
background: darken($simple-background-color, 8%);
|
||||
box-shadow: inset 0 5px 5px rgba($base-shadow-color, 0.05);
|
||||
border-radius: 0 0 4px 4px;
|
||||
display: flex;
|
||||
|
||||
.icon-button {
|
||||
box-sizing: content-box;
|
||||
padding: 0 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__upload-button-icon {
|
||||
line-height: 27px;
|
||||
}
|
||||
|
||||
.compose-form__sensitive-button {
|
||||
display: none;
|
||||
|
||||
&.compose-form__sensitive-button--visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.compose-form__sensitive-button__icon {
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__upload-wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.compose-form__uploads-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.compose-form__upload {
|
||||
flex: 1 1 0;
|
||||
min-width: 40%;
|
||||
margin: 5px;
|
||||
|
||||
&-description {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent);
|
||||
padding: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity .1s ease;
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
color: $ui-secondary-color;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
strong {
|
||||
color: darken($ui-secondary-color, 65%);
|
||||
font-weight: 500;
|
||||
|
||||
@each $lang in $cjk-langs {
|
||||
&:lang(#{$lang}) {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: darken($ui-primary-color, 33%);
|
||||
font-weight: 500;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
opacity: 0.54;
|
||||
color: $ui-secondary-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
.compose-form__autosuggest-wrapper {
|
||||
position: relative;
|
||||
|
||||
.emoji-picker-dropdown {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
mix-blend-mode: difference;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__upload-thumbnail {
|
||||
border-radius: 4px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.compose-form__label {
|
||||
display: block;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
|
||||
&.with-border {
|
||||
border-top: 1px solid $ui-base-color;
|
||||
padding-top: 10px;
|
||||
.autosuggest-textarea,
|
||||
.spoiler-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.compose-form__label__text {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 14px;
|
||||
margin-left: 8px;
|
||||
color: $ui-primary-color;
|
||||
.autosuggest-textarea__textarea,
|
||||
.spoiler-input__input {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: $ui-base-color;
|
||||
background: $simple-background-color;
|
||||
padding: 10px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__textarea,
|
||||
.follow-form__input {
|
||||
background: $simple-background-color;
|
||||
|
||||
&:disabled {
|
||||
background: $ui-secondary-color;
|
||||
.spoiler-input__input {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__autosuggest-wrapper {
|
||||
position: relative;
|
||||
.autosuggest-textarea__textarea {
|
||||
min-height: 100px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
padding-bottom: 0;
|
||||
padding-right: 10px + 22px;
|
||||
resize: none;
|
||||
|
||||
.emoji-picker-dropdown {
|
||||
@media screen and (max-width: 600px) {
|
||||
height: 100px !important; // prevent auto-resize textarea
|
||||
resize: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-textarea__suggestions {
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
top: 100%;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4);
|
||||
background: $ui-secondary-color;
|
||||
border-radius: 0 0 4px 4px;
|
||||
color: $ui-base-color;
|
||||
font-size: 14px;
|
||||
padding: 6px;
|
||||
|
||||
&.autosuggest-textarea__suggestions--visible {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__publish {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
}
|
||||
.autosuggest-textarea__suggestions__item {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
|
||||
.compose-form__publish-button-wrapper {
|
||||
overflow: hidden;
|
||||
padding-top: 10px;
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active,
|
||||
&.selected {
|
||||
background: darken($ui-secondary-color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-account,
|
||||
.autosuggest-emoji {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
line-height: 18px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.autosuggest-account-icon,
|
||||
.autosuggest-emoji img {
|
||||
display: block;
|
||||
margin-right: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.autosuggest-account .display-name__account {
|
||||
color: lighten($ui-base-color, 36%);
|
||||
}
|
||||
|
||||
.compose-form__modifiers {
|
||||
color: $ui-base-color;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
background: $simple-background-color;
|
||||
|
||||
.compose-form__upload-wrapper {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.compose-form__uploads-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 5px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.compose-form__upload {
|
||||
flex: 1 1 0;
|
||||
min-width: 40%;
|
||||
margin: 5px;
|
||||
|
||||
&-description {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 80%, transparent);
|
||||
padding: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity .1s ease;
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
color: $ui-secondary-color;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
|
||||
&:focus {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
opacity: 0.54;
|
||||
color: $ui-secondary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
mix-blend-mode: difference;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__upload-thumbnail {
|
||||
border-radius: 4px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__buttons-wrapper {
|
||||
padding: 10px;
|
||||
background: darken($simple-background-color, 8%);
|
||||
border-radius: 0 0 4px 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.compose-form__buttons {
|
||||
display: flex;
|
||||
|
||||
.compose-form__upload-button-icon {
|
||||
line-height: 27px;
|
||||
}
|
||||
|
||||
.compose-form__sensitive-button {
|
||||
display: none;
|
||||
|
||||
&.compose-form__sensitive-button--visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.compose-form__sensitive-button__icon {
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
box-sizing: content-box;
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.character-counter__wrapper {
|
||||
align-self: center;
|
||||
margin-right: 4px;
|
||||
|
||||
.character-counter {
|
||||
cursor: default;
|
||||
font-family: 'mastodon-font-sans-serif', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: lighten($ui-base-color, 12%);
|
||||
|
||||
&.character-counter--over {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.compose-form__publish {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
|
||||
.compose-form__publish-button-wrapper {
|
||||
overflow: hidden;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emojione {
|
||||
@@ -518,6 +606,7 @@
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
white-space: pre-wrap;
|
||||
padding-top: 2px;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
@@ -616,6 +705,10 @@
|
||||
|
||||
.status.status-direct {
|
||||
background: lighten($ui-base-color, 12%);
|
||||
|
||||
&.muted {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.detailed-status,
|
||||
@@ -770,7 +863,7 @@
|
||||
.status__action-bar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.status__action-bar-button {
|
||||
@@ -803,7 +896,7 @@
|
||||
.emojione {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: -3px 0 0;
|
||||
margin: -1px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1973,121 +2066,6 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.autosuggest-textarea,
|
||||
.spoiler-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.autosuggest-textarea__textarea,
|
||||
.spoiler-input__input {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: $ui-base-color;
|
||||
background: $simple-background-color;
|
||||
padding: 10px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.spoiler-input__input {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.autosuggest-textarea__textarea {
|
||||
min-height: 100px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
padding-bottom: 0;
|
||||
padding-right: 10px + 22px;
|
||||
resize: none;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
height: 100px !important; // prevent auto-resize textarea
|
||||
resize: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-textarea__suggestions {
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4);
|
||||
background: $ui-secondary-color;
|
||||
border-radius: 0 0 4px 4px;
|
||||
color: $ui-base-color;
|
||||
font-size: 14px;
|
||||
padding: 6px;
|
||||
|
||||
&.autosuggest-textarea__suggestions--visible {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-textarea__suggestions__item {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active,
|
||||
&.selected {
|
||||
background: darken($ui-secondary-color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.autosuggest-account,
|
||||
.autosuggest-emoji {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
line-height: 18px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.autosuggest-account-icon,
|
||||
.autosuggest-emoji img {
|
||||
display: block;
|
||||
margin-right: 8px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.autosuggest-account .display-name__account {
|
||||
color: lighten($ui-base-color, 36%);
|
||||
}
|
||||
|
||||
.character-counter__wrapper {
|
||||
line-height: 36px;
|
||||
margin: 0 16px 0 8px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.character-counter {
|
||||
cursor: default;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.character-counter--over {
|
||||
color: $warning-red;
|
||||
}
|
||||
|
||||
.getting-started__wrapper {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
@@ -2273,14 +2251,19 @@ button.icon-button.active i.fa-retweet {
|
||||
.status-card__image-image {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.status-card__title {
|
||||
white-space: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.status-card__image-image {
|
||||
border-radius: 4px 0 0 4px;
|
||||
display: block;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
@@ -3998,6 +3981,7 @@ button.icon-button.active i.fa-retweet {
|
||||
position: relative;
|
||||
background: $base-shadow-color;
|
||||
max-width: 100%;
|
||||
border-radius: 4px;
|
||||
|
||||
video {
|
||||
height: 100%;
|
||||
@@ -4032,8 +4016,8 @@ button.icon-button.active i.fa-retweet {
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 60%, transparent);
|
||||
padding: 0 10px;
|
||||
background: linear-gradient(0deg, rgba($base-shadow-color, 0.85) 0, rgba($base-shadow-color, 0.45) 60%, transparent);
|
||||
padding: 0 15px;
|
||||
opacity: 0;
|
||||
transition: opacity .1s ease;
|
||||
|
||||
@@ -4086,40 +4070,67 @@ button.icon-button.active i.fa-retweet {
|
||||
}
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
&__buttons-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
font-size: 16px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&.left {
|
||||
float: left;
|
||||
|
||||
button {
|
||||
padding-right: 10px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
float: right;
|
||||
|
||||
button {
|
||||
padding-left: 10px;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
padding: 2px 10px;
|
||||
font-size: 16px;
|
||||
border: 0;
|
||||
color: $white;
|
||||
color: rgba($white, 0.75);
|
||||
|
||||
&:active,
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $ui-highlight-color;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__time-sep,
|
||||
&__time-total,
|
||||
&__time-current {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&__time-current {
|
||||
color: $white;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
&__time-sep {
|
||||
display: inline-block;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
&__time-sep,
|
||||
&__time-total {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
&__seek {
|
||||
cursor: pointer;
|
||||
height: 24px;
|
||||
@@ -4129,6 +4140,7 @@ button.icon-button.active i.fa-retweet {
|
||||
content: "";
|
||||
width: 100%;
|
||||
background: rgba($white, 0.35);
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
@@ -4140,8 +4152,9 @@ button.icon-button.active i.fa-retweet {
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 4px;
|
||||
border-radius: 4px;
|
||||
top: 10px;
|
||||
background: $ui-highlight-color;
|
||||
background: lighten($ui-highlight-color, 8%);
|
||||
}
|
||||
|
||||
&__buffer {
|
||||
@@ -4158,7 +4171,8 @@ button.icon-button.active i.fa-retweet {
|
||||
top: 6px;
|
||||
margin-left: -6px;
|
||||
transition: opacity .1s ease;
|
||||
background: $ui-highlight-color;
|
||||
background: lighten($ui-highlight-color, 8%);
|
||||
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
|
||||
pointer-events: none;
|
||||
|
||||
&.active {
|
||||
@@ -4172,6 +4186,16 @@ button.icon-button.active i.fa-retweet {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.detailed,
|
||||
&.fullscreen {
|
||||
.video-player__buttons {
|
||||
button {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.media-spoiler-video {
|
||||
|
||||
@@ -7,9 +7,9 @@ body.rtl {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.character-counter__wrapper {
|
||||
margin-right: 8px;
|
||||
margin-left: 16px;
|
||||
.compose-form .compose-form__buttons-wrapper .character-counter__wrapper {
|
||||
margin-right: 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.navigation-bar__profile {
|
||||
@@ -30,6 +30,22 @@ body.rtl {
|
||||
.column-header__buttons {
|
||||
left: 0;
|
||||
right: auto;
|
||||
margin-left: -15px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.column-inline-form .icon-button {
|
||||
margin-left: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.column-header__links .text-btn {
|
||||
margin-left: 10px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.account__avatar-wrapper {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.column-header__back-button {
|
||||
@@ -41,10 +57,6 @@ body.rtl {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.compose-form__modifiers {
|
||||
border-radius: 0 0 0 4px;
|
||||
}
|
||||
|
||||
.setting-toggle {
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
|
||||
@@ -20,11 +20,13 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||
private
|
||||
|
||||
def process_status
|
||||
media_attachments = process_attachments
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
@status = Status.create!(status_params)
|
||||
|
||||
process_tags(@status)
|
||||
process_attachments(@status)
|
||||
attach_media(@status, media_attachments)
|
||||
end
|
||||
|
||||
resolve_thread(@status)
|
||||
@@ -105,22 +107,36 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||
emoji.save
|
||||
end
|
||||
|
||||
def process_attachments(status)
|
||||
def process_attachments
|
||||
return if @object['attachment'].nil?
|
||||
|
||||
media_attachments = []
|
||||
|
||||
as_array(@object['attachment']).each do |attachment|
|
||||
next if unsupported_media_type?(attachment['mediaType']) || attachment['url'].blank?
|
||||
|
||||
href = Addressable::URI.parse(attachment['url']).normalize.to_s
|
||||
media_attachment = MediaAttachment.create(status: status, account: status.account, remote_url: href, description: attachment['name'].presence)
|
||||
media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence)
|
||||
media_attachments << media_attachment
|
||||
|
||||
next if skip_download?
|
||||
|
||||
media_attachment.file_remote_url = href
|
||||
media_attachment.save
|
||||
end
|
||||
|
||||
media_attachments
|
||||
rescue Addressable::URI::InvalidURIError => e
|
||||
Rails.logger.debug e
|
||||
|
||||
media_attachments
|
||||
end
|
||||
|
||||
def attach_media(status, media_attachments)
|
||||
return if media_attachments.blank?
|
||||
|
||||
media = MediaAttachment.where(status_id: nil, id: media_attachments.take(4).map(&:id))
|
||||
media.update(status_id: status.id)
|
||||
end
|
||||
|
||||
def resolve_thread(status)
|
||||
|
||||
@@ -26,6 +26,8 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
|
||||
cached_reblog = reblog
|
||||
status = nil
|
||||
|
||||
media_attachments = save_media
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
status = Status.create!(
|
||||
uri: id,
|
||||
@@ -44,7 +46,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
|
||||
|
||||
save_mentions(status)
|
||||
save_hashtags(status)
|
||||
save_media(status)
|
||||
attach_media(status, media_attachments)
|
||||
save_emojis(status)
|
||||
end
|
||||
|
||||
@@ -126,18 +128,20 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
|
||||
ProcessHashtagsService.new.call(parent, tags)
|
||||
end
|
||||
|
||||
def save_media(parent)
|
||||
do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
|
||||
def save_media
|
||||
do_not_download = DomainBlock.find_by(domain: @account.domain)&.reject_media?
|
||||
media_attachments = []
|
||||
|
||||
@xml.xpath('./xmlns:link[@rel="enclosure"]', xmlns: OStatus::TagManager::XMLNS).each do |link|
|
||||
next unless link['href']
|
||||
|
||||
media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, remote_url: link['href'])
|
||||
media = MediaAttachment.where(status: nil, remote_url: link['href']).first_or_initialize(account: @account, status: nil, remote_url: link['href'])
|
||||
parsed_url = Addressable::URI.parse(link['href']).normalize
|
||||
|
||||
next if !%w(http https).include?(parsed_url.scheme) || parsed_url.host.empty?
|
||||
|
||||
media.save
|
||||
media_attachments << media
|
||||
|
||||
next if do_not_download
|
||||
|
||||
@@ -148,6 +152,15 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
|
||||
next
|
||||
end
|
||||
end
|
||||
|
||||
media_attachments
|
||||
end
|
||||
|
||||
def attach_media(parent, media_attachments)
|
||||
return if media_attachments.blank?
|
||||
|
||||
media = MediaAttachment.where(status_id: nil, id: media_attachments.take(4).map(&:id))
|
||||
media.update(status_id: parent.id)
|
||||
end
|
||||
|
||||
def save_emojis(parent)
|
||||
|
||||
@@ -2,13 +2,26 @@
|
||||
|
||||
class ProviderDiscovery < OEmbed::ProviderDiscovery
|
||||
class << self
|
||||
def get(url, **options)
|
||||
provider = discover_provider(url, options)
|
||||
|
||||
options.delete(:html)
|
||||
|
||||
provider.get(url, options)
|
||||
end
|
||||
|
||||
def discover_provider(url, **options)
|
||||
res = Request.new(:get, url).perform
|
||||
format = options[:format]
|
||||
|
||||
raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html'
|
||||
if options[:html]
|
||||
html = Nokogiri::HTML(options[:html])
|
||||
else
|
||||
res = Request.new(:get, url).perform
|
||||
|
||||
html = Nokogiri::HTML(res.to_s)
|
||||
raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html'
|
||||
|
||||
html = Nokogiri::HTML(res.to_s)
|
||||
end
|
||||
|
||||
if format.nil? || format == :json
|
||||
provider_endpoint ||= html.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value
|
||||
|
||||
@@ -35,7 +35,7 @@ class StatusFilter
|
||||
end
|
||||
|
||||
def silenced_account?
|
||||
status_account_silenced? && !account_following_status_account?
|
||||
!account&.silenced? && status_account_silenced? && !account_following_status_account?
|
||||
end
|
||||
|
||||
def status_account_silenced?
|
||||
|
||||
@@ -14,17 +14,27 @@ class Themes
|
||||
result = Hash.new
|
||||
Dir.glob(Rails.root.join('app', 'javascript', 'flavours', '*', 'theme.yml')) do |path|
|
||||
data = YAML.load_file(path)
|
||||
name = File.basename(File.dirname(path))
|
||||
dir = File.dirname(path)
|
||||
name = File.basename(dir)
|
||||
locales = []
|
||||
screenshots = []
|
||||
if data['locales']
|
||||
locales = []
|
||||
Dir.glob(File.join(File.dirname(path), data['locales'], '*.{js,json}')) do |locale|
|
||||
Dir.glob(File.join(dir, data['locales'], '*.{js,json}')) do |locale|
|
||||
localeName = File.basename(locale, File.extname(locale))
|
||||
locales.push(localeName) unless localeName.match(/defaultMessages|whitelist|index/)
|
||||
end
|
||||
data['locales'] = locales
|
||||
end
|
||||
if data['screenshot']
|
||||
if data['screenshot'].is_a? Array
|
||||
screenshots = data['screenshot']
|
||||
else
|
||||
screenshots.push(data['screenshot'])
|
||||
end
|
||||
end
|
||||
if data['pack']
|
||||
data['name'] = name
|
||||
data['locales'] = locales
|
||||
data['screenshot'] = screenshots
|
||||
data['skin'] = { 'default' => [] }
|
||||
result[name] = data
|
||||
end
|
||||
|
||||
@@ -287,6 +287,7 @@ class Account < ApplicationRecord
|
||||
FROM accounts
|
||||
WHERE #{query} @@ #{textsearch}
|
||||
AND accounts.suspended = false
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
ORDER BY rank DESC
|
||||
LIMIT ?
|
||||
SQL
|
||||
@@ -312,6 +313,7 @@ class Account < ApplicationRecord
|
||||
WHERE accounts.id IN (SELECT * FROM first_degree)
|
||||
AND #{query} @@ #{textsearch}
|
||||
AND accounts.suspended = false
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
GROUP BY accounts.id
|
||||
ORDER BY rank DESC
|
||||
LIMIT ?
|
||||
@@ -327,6 +329,7 @@ class Account < ApplicationRecord
|
||||
LEFT OUTER JOIN follows AS f ON (accounts.id = f.account_id AND f.target_account_id = ?) OR (accounts.id = f.target_account_id AND f.account_id = ?)
|
||||
WHERE #{query} @@ #{textsearch}
|
||||
AND accounts.suspended = false
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
GROUP BY accounts.id
|
||||
ORDER BY rank DESC
|
||||
LIMIT ?
|
||||
|
||||
@@ -45,6 +45,8 @@ class AccountFilter
|
||||
else
|
||||
Account.default_scoped
|
||||
end
|
||||
when 'staff'
|
||||
accounts_with_users.merge User.staff
|
||||
else
|
||||
raise "Unknown filter: #{key}"
|
||||
end
|
||||
|
||||
@@ -27,6 +27,8 @@ class CustomEmojiFilter
|
||||
CustomEmoji.remote
|
||||
when 'by_domain'
|
||||
CustomEmoji.where(domain: value)
|
||||
when 'shortcode'
|
||||
CustomEmoji.where(shortcode: value)
|
||||
else
|
||||
raise "Unknown filter: #{key}"
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Table name: lists
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# account_id :integer
|
||||
# account_id :integer not null
|
||||
# title :string default(""), not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
@@ -13,6 +13,8 @@
|
||||
class List < ApplicationRecord
|
||||
include Paginable
|
||||
|
||||
PER_ACCOUNT_LIMIT = 50
|
||||
|
||||
belongs_to :account
|
||||
|
||||
has_many :list_accounts, inverse_of: :list, dependent: :destroy
|
||||
@@ -20,6 +22,10 @@ class List < ApplicationRecord
|
||||
|
||||
validates :title, presence: true
|
||||
|
||||
validates_each :account_id, on: :create do |record, _attr, value|
|
||||
record.errors.add(:base, I18n.t('lists.errors.limit')) if List.where(account_id: value).count >= PER_ACCOUNT_LIMIT
|
||||
end
|
||||
|
||||
before_destroy :clean_feed_manager
|
||||
|
||||
private
|
||||
|
||||
@@ -33,7 +33,7 @@ class PreviewCard < ApplicationRecord
|
||||
|
||||
has_and_belongs_to_many :statuses
|
||||
|
||||
has_attached_file :image, styles: { original: '280x280>' }, convert_options: { all: '-quality 80 -strip' }
|
||||
has_attached_file :image, styles: { original: '400x400>' }, convert_options: { all: '-quality 80 -strip' }
|
||||
|
||||
include Attachmentable
|
||||
include Remotable
|
||||
|
||||
@@ -23,7 +23,7 @@ class Tag < ApplicationRecord
|
||||
|
||||
class << self
|
||||
def search_for(term, limit = 5)
|
||||
pattern = sanitize_sql_like(term) + '%'
|
||||
pattern = sanitize_sql_like(term.strip) + '%'
|
||||
Tag.where('lower(name) like lower(?)', pattern).order(:name).limit(limit)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,9 +7,7 @@ class REST::AccountSerializer < ActiveModel::Serializer
|
||||
:note, :url, :avatar, :avatar_static, :header, :header_static,
|
||||
:followers_count, :following_count, :statuses_count
|
||||
|
||||
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved?
|
||||
|
||||
delegate :moved?, to: :object
|
||||
has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?
|
||||
|
||||
def id
|
||||
object.id.to_s
|
||||
@@ -38,4 +36,8 @@ class REST::AccountSerializer < ActiveModel::Serializer
|
||||
def header_static
|
||||
full_asset_url(object.header_static_url)
|
||||
end
|
||||
|
||||
def moved_and_not_nested?
|
||||
object.moved? && object.moved_to_account.moved_to_account_id.nil?
|
||||
end
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user