Compare commits

..

2 Commits

Author SHA1 Message Date
kibigo!
f32ef29808 Removed unnecessary constraint 2017-12-11 00:14:00 -08:00
kibigo!
a634d3876f Route flavours ~ URLs 2017-12-10 23:59:04 -08:00
180 changed files with 1102 additions and 2633 deletions

View File

@@ -14,13 +14,12 @@ gem 'pg', '~> 0.20'
gem 'pghero', '~> 1.7'
gem 'dotenv-rails', '~> 2.2'
gem 'aws-sdk', '~> 2.10', require: false
gem 'fog-aws', '~> 1.4', 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'

View File

@@ -57,14 +57,6 @@ 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)
@@ -160,6 +152,11 @@ 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)
@@ -173,6 +170,9 @@ 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,7 +228,6 @@ 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)
@@ -325,7 +324,6 @@ 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)
@@ -546,7 +544,6 @@ 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
@@ -569,6 +566,7 @@ 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)
@@ -603,7 +601,6 @@ DEPENDENCIES
pg (~> 0.20)
pghero (~> 1.7)
pkg-config (~> 1.2)
posix-spawn
pry-rails (~> 0.3)
puma (~> 3.10)
pundit (~> 1.1)

View File

@@ -49,7 +49,7 @@ class AccountsController < ApplicationController
end
def default_statuses
@account.statuses.not_local_only.where(visibility: [:public, :unlisted])
@account.statuses.where(visibility: [:public, :unlisted])
end
def only_media_scope

View File

@@ -89,8 +89,7 @@ module Admin
:username,
:display_name,
:email,
:ip,
:staff
:ip
)
end
end

View File

@@ -92,9 +92,7 @@ module Admin
def filter_params
params.permit(
:local,
:remote,
:by_domain,
:shortcode
:remote
)
end
end

View File

@@ -72,4 +72,19 @@ 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

View File

@@ -1,20 +0,0 @@
# 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

View File

@@ -1,14 +1,18 @@
# 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).all
@lists = List.where(account: current_account).paginate_by_max_id(limit_param(LISTS_LIMIT), params[:max_id], params[:since_id])
render json: @lists, each_serializer: REST::ListSerializer
end
@@ -40,4 +44,36 @@ 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

View File

@@ -42,7 +42,6 @@ class Api::V1::StatusesController < Api::BaseController
@status = PostStatusService.new.call(current_user.account,
status_params[:status],
status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]),
local_only: status_params[:local_only],
media_ids: status_params[:media_ids],
sensitive: status_params[:sensitive],
spoiler_text: status_params[:spoiler_text],
@@ -73,7 +72,7 @@ class Api::V1::StatusesController < Api::BaseController
end
def status_params
params.permit(:status, :in_reply_to_id, :local_only, :sensitive, :spoiler_text, :visibility, media_ids: [])
params.permit(:status, :in_reply_to_id, :sensitive, :spoiler_text, :visibility, media_ids: [])
end
def pagination_params(core_params)

View File

@@ -28,8 +28,6 @@ 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],

View File

@@ -81,6 +81,7 @@ class ApplicationController < ActionController::Base
end
def pack?(data, pack_name)
return false unless data
if data['pack'].is_a?(Hash) && data['pack'].key?(pack_name)
return true if data['pack'][pack_name].is_a?(String) || data['pack'][pack_name].is_a?(Hash)
end
@@ -89,16 +90,17 @@ class ApplicationController < ActionController::Base
def nil_pack(data, pack_name, skin = 'default')
{
common: pack_name == 'common' ? nil : resolve_pack(data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
flavour: data['name'],
common: pack_name == 'common' ? nil : resolve_pack(!data || data['name'] ? Themes.instance.flavour(current_flavour) : Themes.instance.core, 'common', skin),
flavour: data ? data['name'] : nil,
pack: nil,
preload: nil,
skin: nil,
supported_locales: data['locales'],
supported_locales: data ? data['locales'] : nil,
}
end
def resolve_pack(data, pack_name, skin = 'default')
return nil_pack(data, pack_name, skin) unless data
result = pack(data, pack_name, skin)
unless result
if data['name'] && data.key?('fallback')
@@ -154,13 +156,14 @@ class ApplicationController < ActionController::Base
end
def current_flavour
return Setting.default_settings['flavour'] unless Themes.instance.flavours.include? current_user&.setting_flavour
current_user.setting_flavour
return params[:use_flavour].to_s if Themes.instance.flavours.include? params[:use_flavour].to_s
return current_user.setting_flavour if Themes.instance.flavours.include? current_user&.setting_flavour
Setting.default_settings['flavour']
end
def current_skin
return 'default' unless Themes.instance.skins_for(current_flavour).include? current_user&.setting_skin
current_user.setting_skin
return current_user.setting_skin if Themes.instance.skins_for(current_flavour).include? current_user&.setting_skin
'default'
end
def cache_collection(raw, klass)

View File

@@ -44,8 +44,7 @@ module RateLimitHeaders
end
def api_throttle_data
most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
request.env['rack.attack.throttle_data'][most_limited_type]
request.env['rack.attack.throttle_data']['api']
end
def request_time

View File

@@ -7,6 +7,7 @@ class HomeController < ApplicationController
def index
@body_classes = 'app-body'
redirect_to "/$#{current_flavour}/#{params[:glob] || ''}" unless Themes.instance.flavours.include?(params[:use_flavour].to_s) or request.path.start_with?("/$#{current_flavour}")
end
private
@@ -58,7 +59,7 @@ class HomeController < ApplicationController
end
def default_redirect_path
if request.path.start_with?('/web')
if request.path.start_with?('/web') || request.path.match?(/\A\$[\w-]+/)
new_user_session_path
elsif single_user_mode?
short_account_path(Account.first)

View File

@@ -5,7 +5,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_action :store_current_location
before_action :authenticate_resource_owner!
before_action :set_pack
include Localized
@@ -14,8 +13,4 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
def store_current_location
store_location_for(:user, request.url)
end
def set_pack
use_pack 'auth'
end
end

View File

@@ -5,7 +5,6 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
before_action :store_current_location
before_action :authenticate_resource_owner!
before_action :set_pack
include Localized
@@ -14,8 +13,4 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
def store_current_location
store_location_for(:user, request.url)
end
def set_pack
use_pack 'settings'
end
end

View File

@@ -1,35 +0,0 @@
# 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

View File

@@ -28,7 +28,6 @@ class Settings::MigrationsController < ApplicationController
end
def migration_account_changed?
current_account.moved_to_account_id != @migration.account&.id &&
current_account.id != @migration.account&.id
current_account.moved_to_account_id != @migration.account&.id
end
end

View File

@@ -39,6 +39,8 @@ 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)
)

View File

@@ -1,12 +1,11 @@
# frozen_string_literal: true
module Admin::FilterHelper
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
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
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS
FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER
def filter_link_to(text, link_to_params, link_class_params = link_to_params)
new_url = filtered_url_for(link_to_params)

View File

@@ -10,7 +10,6 @@ module SettingsHelper
eo: 'Esperanto',
es: 'Español',
fa: 'فارسی',
gl: 'Galego',
fi: 'Suomi',
fr: 'Français',
he: 'עברית',

View File

@@ -37,3 +37,7 @@ delegate(document, '#account_header', 'change', ({ target }) => {
header.style.backgroundImage = `url(${url})`;
});
delegate(document, '#user_setting_flavour, #user_setting_skin', 'change', ({ target }) => {
target.form.submit();
});

View File

@@ -57,7 +57,7 @@ export default class Mastodon extends React.PureComponent {
return (
<IntlProvider locale={locale} messages={messages}>
<Provider store={store}>
<BrowserRouter basename='/web'>
<BrowserRouter basename='/$glitch'>
<ScrollContext>
<Route path='/' component={UI} />
</ScrollContext>

View File

@@ -112,7 +112,7 @@ export default class Compose extends React.PureComponent {
<Motion defaultStyle={{ x: -100 }} style={{ x: spring(showSearch ? 0 : -100, { stiffness: 210, damping: 20 }) }}>
{({ x }) =>
<div className='drawer__inner darker scrollable optionally-scrollable' style={{ transform: `translateX(${x}%)`, visibility: x === -100 ? 'hidden' : 'visible' }}>
<div className='drawer__inner darker' style={{ transform: `translateX(${x}%)`, visibility: x === -100 ? 'hidden' : 'visible' }}>
<SearchResultsContainer />
</div>
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

View File

@@ -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,10 +37,6 @@ const messages = {
'status.collapse': '折りたたむ',
'status.uncollapse': '折りたたみを解除',
'favourite_modal.combo': '次からは {combo} を押せば、これをスキップできます。',
'home.column_settings.show_direct': 'DMを表示',
'notification.markForDeletion': '選択',
'notifications.clear': '通知を全てクリアする',
'notifications.marked_clear_confirmation': '削除した全ての通知を完全に削除してもよろしいですか?',

View File

@@ -1,8 +1,6 @@
en:
flavours:
glitch:
description: The default flavour for GlitchSoc instances.
name: Glitch Edition
glitch: Glitch Edition
skins:
glitch:
default: Default

View File

@@ -1,4 +1 @@
import 'flavours/glitch/styles/index.scss';
// This ensures that webpack compiles our images.
require.context('../images', true);

View File

@@ -17,7 +17,7 @@ const notify = options =>
icon: '/android-chrome-192x192.png',
tag: GROUP_TAG,
data: {
url: (new URL('/web/notifications', self.location)).href,
url: (new URL('/$glitch/notifications', self.location)).href,
count: notifications.length + 1,
message: options.data.message,
},

View File

@@ -246,22 +246,6 @@
}
}
.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;
@@ -363,120 +347,3 @@
}
}
}
.spacer {
flex: 1 1 auto;
}
.log-entry {
margin-bottom: 8px;
line-height: 20px;
&__header {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 10px;
background: $ui-base-color;
color: $ui-primary-color;
border-radius: 4px 4px 0 0;
font-size: 14px;
position: relative;
}
&__avatar {
margin-right: 10px;
.avatar {
display: block;
margin: 0;
border-radius: 50%;
width: 40px;
height: 40px;
}
}
&__title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__timestamp {
color: lighten($ui-base-color, 34%);
}
&__extras {
background: lighten($ui-base-color, 6%);
border-radius: 0 0 4px 4px;
padding: 10px;
color: $ui-primary-color;
font-family: 'mastodon-font-monospace', monospace;
font-size: 12px;
white-space: nowrap;
min-height: 20px;
}
&__icon {
font-size: 28px;
margin-right: 10px;
color: lighten($ui-base-color, 34%);
}
&__icon__overlay {
position: absolute;
top: 10px;
right: 10px;
width: 10px;
height: 10px;
border-radius: 50%;
&.positive {
background: $success-green;
}
&.negative {
background: $error-red;
}
&.neutral {
background: $ui-highlight-color;
}
}
a,
.username,
.target {
color: $ui-secondary-color;
text-decoration: none;
font-weight: 500;
}
.diff-old {
color: $error-red;
}
.diff-neutral {
color: $ui-secondary-color;
}
.diff-new {
color: $success-green;
}
}
.name-tag {
display: flex;
align-items: center;
.avatar {
display: block;
margin: 0;
margin-right: 5px;
border-radius: 50%;
}
.username {
font-weight: 500;
}
}

View File

@@ -2286,6 +2286,7 @@
.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 {

View File

@@ -26,12 +26,6 @@ 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.

View File

@@ -12,8 +12,8 @@ function main() {
if (window.history && history.replaceState) {
const { pathname, search, hash } = window.location;
const path = pathname + search + hash;
if (!(/^\/web[$/]/).test(path)) {
history.replaceState(null, document.title, `/web${path}`);
if (!(/^\/\$glitch[$/]/).test(path)) {
history.replaceState(null, document.title, `/$glitch${path}`);
}
}

View File

@@ -1,8 +1,6 @@
en:
flavours:
vanilla:
description: The theme used by vanilla Mastodon instances. This theme might not support all of the features of GlitchSoc.
name: Vanilla Mastodon
vanilla: Vanilla Mastodon
skins:
vanilla:
default: Default

View File

@@ -24,12 +24,6 @@ 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 KiB

View File

@@ -10,10 +10,6 @@ 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 => {
@@ -50,7 +46,7 @@ export function expandFavouritedStatuses() {
return (dispatch, getState) => {
const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
if (url === null || getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
if (url === null) {
return;
}

View File

@@ -1,5 +1,4 @@
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';
@@ -43,15 +42,11 @@ 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,
}).then(() => {
const me = getState().getIn(['meta', 'me']);
if (me) {
pushNotificationsSetting.set(me, data);
}
data: {
alerts,
},
});
};
}

View File

@@ -1,7 +1,6 @@
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 {
@@ -9,12 +8,12 @@ export default class Avatar extends React.PureComponent {
account: ImmutablePropTypes.map.isRequired,
size: PropTypes.number.isRequired,
style: PropTypes.object,
inline: PropTypes.bool,
animate: PropTypes.bool,
inline: PropTypes.bool,
};
static defaultProps = {
animate: autoPlayGif,
animate: false,
size: 20,
inline: false,
};

View File

@@ -1,29 +1,22 @@
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, animate } = this.props;
const { account, friend } = this.props;
const baseStyle = {
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
backgroundImage: `url(${account.get('avatar_static')})`,
};
const overlayStyle = {
backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
backgroundImage: `url(${friend.get('avatar_static')})`,
};
return (

View File

@@ -57,7 +57,7 @@ export default class Mastodon extends React.PureComponent {
return (
<IntlProvider locale={locale} messages={messages}>
<Provider store={store}>
<BrowserRouter basename='/web'>
<BrowserRouter basename='/$vanilla'>
<ScrollContext>
<Route path='/' component={UI} />
</ScrollContext>

View File

@@ -156,8 +156,6 @@ export default class ComposeForm extends ImmutablePureComponent {
return (
<div className='compose-form'>
<WarningContainer />
<Collapsable isVisible={this.props.spoiler} fullHeight={50}>
<div className='spoiler-input'>
<label>
@@ -167,6 +165,8 @@ 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='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 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>
</div>
);

View File

@@ -6,7 +6,6 @@ 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' },
@@ -43,10 +42,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
return null;
}
const content = { __html: status.get('contentHtml') };
const style = {
direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr',
};
const content = { __html: status.get('contentHtml') };
return (
<div className='reply-indicator'>
@@ -59,7 +55,7 @@ export default class ReplyIndicator extends ImmutablePureComponent {
</a>
</div>
<div className='reply-indicator__content' style={style} dangerouslySetInnerHTML={content} />
<div className='reply-indicator__content' dangerouslySetInnerHTML={content} />
</div>
);
}

View File

@@ -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 || (this.state.dirtyDescription !== '' && media.get('description')) || '';
const description = this.state.dirtyDescription || media.get('description') || '';
return (
<div className='compose-form__upload' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>

View File

@@ -9,7 +9,6 @@ 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' },
@@ -17,7 +16,6 @@ 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']),
});
@@ -32,7 +30,6 @@ export default class Favourites extends ImmutablePureComponent {
columnId: PropTypes.string,
multiColumn: PropTypes.bool,
hasMore: PropTypes.bool,
isLoading: PropTypes.bool,
};
componentWillMount () {
@@ -62,12 +59,12 @@ export default class Favourites extends ImmutablePureComponent {
this.column = c;
}
handleScrollToBottom = debounce(() => {
handleScrollToBottom = () => {
this.props.dispatch(expandFavouritedStatuses());
}, 300, { leading: true })
}
render () {
const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props;
const { intl, statusIds, columnId, multiColumn, hasMore } = this.props;
const pinned = !!columnId;
return (
@@ -88,7 +85,6 @@ export default class Favourites extends ImmutablePureComponent {
statusIds={statusIds}
scrollKey={`favourited_statuses-${columnId}`}
hasMore={hasMore}
isLoading={isLoading}
onScrollToBottom={this.handleScrollToBottom}
/>
</Column>

View File

@@ -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. When members of this list post new statuses, they will appear here.' />}
emptyMessage={<FormattedMessage id='empty_column.list' defaultMessage='There is nothing in this list yet.' />}
/>
</Column>
);

View File

@@ -8,7 +8,6 @@ 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 {
@@ -30,13 +29,16 @@ export default class HashtagTimeline extends React.PureComponent {
const { dispatch, hashtag } = this.props;
dispatch(refreshHashtagTimeline(hashtag));
this.disconnect = dispatch(connectHashtagStream(hashtag));
this.polling = setInterval(() => {
dispatch(refreshHashtagTimeline(hashtag));
}, 10000);
}
componentWillUnmount () {
if (this.disconnect) {
this.disconnect();
this.disconnect = null;
if (typeof this.polling !== 'undefined') {
clearInterval(this.polling);
this.polling = null;
}
}

View File

@@ -9,7 +9,6 @@ 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...' },
@@ -36,13 +35,16 @@ export default class PublicTimeline extends React.PureComponent {
const { dispatch } = this.props;
dispatch(refreshPublicTimeline());
this.disconnect = dispatch(connectPublicStream());
this.polling = setInterval(() => {
dispatch(refreshPublicTimeline());
}, 3000);
}
componentWillUnmount () {
if (this.disconnect) {
this.disconnect();
this.disconnect = null;
if (typeof this.polling !== 'undefined') {
clearInterval(this.polling);
this.polling = null;
}
}

View File

@@ -43,7 +43,7 @@ export default class Card extends React.PureComponent {
Immutable.fromJS([
{
type: 'image',
url: card.get('embed_url'),
url: card.get('url'),
description: card.get('title'),
meta: {
original: {
@@ -59,8 +59,6 @@ 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');
@@ -77,15 +75,17 @@ export default class Card extends React.PureComponent {
provider = decodeIDNA(getHostname(card.get('url')));
}
const className = classnames('status-card', { horizontal });
const className = classnames('status-card', {
'horizontal': card.get('width') > card.get('height'),
});
return (
<a href={card.get('url')} className={className} target='_blank' rel='noopener' ref={this.setRef}>
<a href={card.get('url')} className={className} target='_blank' rel='noopener'>
{image}
<div className='status-card__content'>
<strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>
{!horizontal && <p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>}
<p className='status-card__description'>{(card.get('description') || '').substring(0, maxDescription)}</p>
<span className='status-card__host'>{provider}</span>
</div>
</a>

View File

@@ -53,10 +53,7 @@ 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.isRtlLayout = document.getElementsByTagName('body')[0].classList.contains('rtl');
this.lastIndex = getIndex(this.context.router.history.location.pathname);
this.setState({ shouldAnimate: true });
}
@@ -82,8 +79,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
handleChildrenContentChange() {
if (!this.props.singleColumn) {
const modifier = this.isRtlLayout ? -1 : 1;
this._interruptScrollAnimation = scrollRight(this.node, (this.node.scrollWidth - window.innerWidth) * modifier);
this._interruptScrollAnimation = scrollRight(this.node, this.node.scrollWidth - window.innerWidth);
}
}

View File

@@ -23,7 +23,6 @@ export default class VideoModal extends ImmutablePureComponent {
src={media.get('url')}
startTime={time}
onCloseVideo={onClose}
detailed
description={media.get('description')}
/>
</div>

View File

@@ -17,18 +17,6 @@ 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;
@@ -95,13 +83,11 @@ export default class Video extends React.PureComponent {
startTime: PropTypes.number,
onOpenVideo: PropTypes.func,
onCloseVideo: PropTypes.func,
detailed: PropTypes.bool,
intl: PropTypes.object.isRequired,
};
state = {
currentTime: 0,
duration: 0,
progress: 0,
paused: true,
dragging: false,
fullscreen: false,
@@ -131,10 +117,7 @@ export default class Video extends React.PureComponent {
}
handleTimeUpdate = () => {
this.setState({
currentTime: Math.floor(this.video.currentTime),
duration: Math.floor(this.video.duration),
});
this.setState({ progress: 100 * (this.video.currentTime / this.video.duration) });
}
handleMouseDown = e => {
@@ -160,10 +143,8 @@ export default class Video extends React.PureComponent {
handleMouseMove = throttle(e => {
const { x } = getPointerPosition(this.seek, e);
const currentTime = Math.floor(this.video.duration * x);
this.video.currentTime = currentTime;
this.setState({ currentTime });
this.video.currentTime = this.video.duration * x;
this.setState({ progress: x * 100 });
}, 60);
togglePlay = () => {
@@ -245,12 +226,11 @@ export default class Video extends React.PureComponent {
}
render () {
const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
const { currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
const progress = (currentTime / duration) * 100;
const { preview, src, width, height, startTime, onOpenVideo, onCloseVideo, intl, alt } = this.props;
const { progress, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
return (
<div className={classNames('video-player', { inactive: !revealed, detailed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<div className={classNames('video-player', { inactive: !revealed, inline: width && height && !fullscreen, fullscreen })} style={{ width, height }} ref={this.setPlayerRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<video
ref={this.setVideoRef}
src={src}
@@ -287,27 +267,16 @@ export default class Video extends React.PureComponent {
/>
</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 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>
{!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 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>
</div>
</div>
</div>

View File

@@ -36,9 +36,9 @@
"column.favourites": "المفضلة",
"column.follow_requests": "طلبات المتابعة",
"column.home": "الرئيسية",
"column.lists": "القوائم",
"column.lists": "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": "هل تود حقا حذف هذه القائمة ؟",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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": "للتركيز على منشور على أحد الأعمدة",
"keyboard_shortcuts.compose": "للتركيز على نافذة تحرير النصوص",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.down": "للإنتقال إلى أسفل القائمة",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "للإضافة إلى المفضلة",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.hotkey": "مفتاح الإختصار",
"keyboard_shortcuts.legend": "لعرض هذا المفتاح",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.mention": "لذِكر الناشر",
"keyboard_shortcuts.reply": "للردّ",
"keyboard_shortcuts.search": "للتركيز على البحث",
"keyboard_shortcuts.search": "to focus 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": "أضف إلى القائمة",
"lists.account.remove": "إحذف من القائمة",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"lists.edit": "تعديل القائمة",
"lists.new.create": "إنشاء قائمة",
"lists.new.title_placeholder": "عنوان القائمة الجديدة",
"lists.search": "إبحث في قائمة الحسابات التي تُتابِعها",
"lists.subheading": "قوائمك",
"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",
"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": "القوائم",
"navigation_bar.lists": "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": "جملة قصيرة تُمكّنُك من عرض أسماء و حسابات و كلمات رمزية",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "مستخدِم",
"search_results.total": "{count, number} {count, plural, one {result} و {results}}",
"standalone.public_title": "نظرة على ...",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Зареждане...",
"media_gallery.toggle_visible": "Toggle visibility",

View File

@@ -36,7 +36,7 @@
"column.favourites": "Favorits",
"column.follow_requests": "Peticions per seguir-te",
"column.home": "Inici",
"column.lists": "Llistes",
"column.lists": "Lists",
"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": "Estàs segur que vols esborrar permanenment aquesta llista?",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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": "Afegir a la llista",
"lists.account.remove": "Treure de la llista",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"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",
"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",
"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": "Llistes",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Tancar sessió",
"navigation_bar.mutes": "Usuaris silenciats",
"navigation_bar.pins": "Toots fixats",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Wird geladen …",
"media_gallery.toggle_visible": "Sichtbarkeit umschalten",

View File

@@ -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. When members of this list post new statuses, they will appear here.",
"empty_column.list": "There is nothing in this list yet.",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
"follow_request.authorize": "Authorize",
@@ -135,7 +135,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Toggle visibility",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Ŝarganta…",
"media_gallery.toggle_visible": "Baskuli videblecon",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Cargando…",
"media_gallery.toggle_visible": "Cambiar visibilidad",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "بارگیری...",
"media_gallery.toggle_visible": "تغییر پیدایی",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Ladataan...",
"media_gallery.toggle_visible": "Toggle visibility",

View File

@@ -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": "Supprimer",
"confirmations.delete_list.message": "Êtes-vous sûr de vouloir supprimer définitivement cette liste ?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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 ny 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 à dautres 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. Dès que des personnes de cette liste publierons de nouveaux statuts, ils apparaîtront ici.",
"empty_column.list": "Il n'y a rien dans cette liste pour l'instant.",
"empty_column.notifications": "Vous navez pas encore de notification. Interagissez avec dautres utilisateur⋅ice⋅s pour débuter la conversation.",
"empty_column.public": "Il ny a rien ici! Écrivez quelque chose publiquement, ou bien suivez manuellement des utilisateur⋅ice⋅s dautres 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": "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.enter": "to open status",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.toot": "pour démarrer un tout nouveau pouet",
"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",
"lightbox.close": "Fermer",
"lightbox.next": "Suivant",
"lightbox.previous": "Précédent",
"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",
"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",
"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 dinformations",
"navigation_bar.keyboard_shortcuts": "Raccourcis clavier",
"navigation_bar.lists": "Listes",
"navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
"navigation_bar.lists": "Lists",
"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": "Votre brouillon sera perdu si vous quittez Mastodon.",
"ui.beforeunload": "Your draft will be lost if you leave 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",

View File

@@ -1,259 +0,0 @@
{
"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"
}

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "טוען...",
"media_gallery.toggle_visible": "נראה\\בלתי נראה",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Učitavam...",
"media_gallery.toggle_visible": "Preklopi vidljivost",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Betöltés...",
"media_gallery.toggle_visible": "Toggle visibility",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Tunggu sebentar...",
"media_gallery.toggle_visible": "Tampil/Sembunyikan",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Kargante...",
"media_gallery.toggle_visible": "Chanjar videbleso",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Carico...",
"media_gallery.toggle_visible": "Imposta visibilità",

View File

@@ -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": "埋め込み",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "불러오는 중...",
"media_gallery.toggle_visible": "표시 전환",

View File

@@ -36,7 +36,7 @@
"column.favourites": "Favorieten",
"column.follow_requests": "Volgverzoeken",
"column.home": "Start",
"column.lists": "Lijsten",
"column.lists": "Lists",
"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": "Weet je zeker dat je deze lijst definitief wilt verwijderen?",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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. Wanneer lijstleden nieuwe toots publiceren, zijn deze hier te zien.",
"empty_column.list": "Er is nog niks in deze lijst.",
"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 gaan",
"keyboard_shortcuts.back": "om terug te navigeren",
"keyboard_shortcuts.boost": "om te boosten",
"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.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.down": "om naar beneden door de lijst te bewegen",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "om als favoriet te markeren",
"keyboard_shortcuts.heading": "Sneltoetsen",
"keyboard_shortcuts.favourite": "om het te markeren als favoriet",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"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 reageren",
"keyboard_shortcuts.search": "om het zoekvak te focussen",
"keyboard_shortcuts.reply": "om te antwoorden",
"keyboard_shortcuts.search": "om te focussen op zoeken",
"keyboard_shortcuts.toot": "om een nieuwe toot te starten",
"keyboard_shortcuts.unfocus": "om het tekst- en zoekvak te ontfocussen",
"keyboard_shortcuts.unfocus": "om te ontfocussen van het toot tekstvak/zoeken",
"keyboard_shortcuts.up": "om omhoog te bewegen in de lijst",
"lightbox.close": "Sluiten",
"lightbox.next": "Volgende",
"lightbox.previous": "Vorige",
"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",
"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",
"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": "Lijsten",
"navigation_bar.lists": "Lists",
"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": "Rapporteer {target}",
"report.target": "Rapporteren van",
"search.placeholder": "Zoeken",
"search_popout.search_format": "Geavanceerd zoeken",
"search_popout.tips.hashtag": "hashtag",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Laster...",
"media_gallery.toggle_visible": "Veksle synlighet",

View File

@@ -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": "Rescondre las notificacions de @{name}",
"account.mute_notifications": "Mute notifications from @{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": "Mostrar las notificacions de @{name}",
"account.unmute_notifications": "Unmute notifications from @{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 mèuca pendent lo cargament daqueste compausant.",
"bundle_column_error.body": "Quicòm a fach meuca pendent lo cargament daqueste 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 dabonament",
"column.home": "Acuèlh",
"column.lists": "Listas",
"column.lists": "Lists",
"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 lestatut?",
"confirmations.delete_list.confirm": "Suprimir",
"confirmations.delete_list.message": "Sètz segur de voler suprimir aquesta lista per totjorn?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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": "Resultats de recèrca",
"emoji_button.search_results": "Resultat 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 aquesta etiqueta.",
"empty_column.hashtag": "I a pas encara de contengut ligat a aqueste hashtag",
"empty_column.home": "Vòstre flux dacuèlh es void. Visitatz {public} o utilizatz la recèrca per vos connectar a dautras personas.",
"empty_column.home.public_timeline": "lo flux public",
"empty_column.list": "I a pas res dins la lista pel moment. Quand de membres daquesta lista publiquen de novèls estatuts los veiretz aquí.",
"empty_column.list": "I a pas res dins la lista pel moment.",
"empty_column.notifications": "Avètz pas encara de notificacions. Respondètz a qualquun per començar una conversacion.",
"empty_column.public": "I a pas res aquí! Escrivètz quicòm de public, o seguètz de personas dautras 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 dautras 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": "Acorchis",
"keyboard_shortcuts.hotkey": "Clau",
"keyboard_shortcuts.legend": "per mostrar aquesta legenda",
"keyboard_shortcuts.mention": "per mencionar lautor",
"keyboard_shortcuts.reply": "per respondre",
@@ -127,35 +127,35 @@
"lightbox.close": "Tampar",
"lightbox.next": "Seguent",
"lightbox.previous": "Precedent",
"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",
"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",
"loading_indicator.label": "Cargament…",
"media_gallery.toggle_visible": "Modificar la visibilitat",
"missing_indicator.label": "Pas trobat",
"mute_modal.hide_notifications": "Rescondre las notificacions daquesta persona?",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"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 dabonament",
"navigation_bar.follow_requests": "Demandas d'abonament",
"navigation_bar.info": "Mai informacions",
"navigation_bar.keyboard_shortcuts": "Acorchis clavièr",
"navigation_bar.lists": "Listas",
"navigation_bar.lists": "Lists",
"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 dacuèlh mòstra los estatuts del mond que seguètz.",
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualquun interagís amb vos.",
"onboarding.page_four.notifications": "La colomna de notificacions vos fa veire quand qualquun 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": "Lo tèxt brut tòrna escais, noms dutilizaire e etiquetas correspondents",
"search_popout.tips.text": "Tèxt brut tòrna escais, noms dutilizaire 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}",

View File

@@ -36,7 +36,7 @@
"column.favourites": "Favoritos",
"column.follow_requests": "Seguidores pendentes",
"column.home": "Página inicial",
"column.lists": "Listas",
"column.lists": "Lists",
"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": "Você tem certeza que quer deletar permanentemente a lista?",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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": "Focar um status em uma das colunas",
"keyboard_shortcuts.compose": "para focar a área de redação",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.down": "para mover para baixo na lista",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "para adicionar aos favoritos",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"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",
"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",
"lightbox.close": "Fechar",
"lightbox.next": "Próximo",
"lightbox.previous": "Anterior",
"lists.account.add": "Adicionar a listas",
"lists.account.remove": "Remover da lista",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"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",
"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",
"loading_indicator.label": "Carregando...",
"media_gallery.toggle_visible": "Esconder/Mostrar",
"missing_indicator.label": "Não encontrado",
"mute_modal.hide_notifications": "Esconder notificações deste usuário?",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"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": "Atalhos de teclado",
"navigation_bar.lists": "Listas",
"navigation_bar.keyboard_shortcuts": "Keyboard shortcuts",
"navigation_bar.lists": "Lists",
"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": "Bom Apetoot!",
"onboarding.page_six.appetoot": "Bon Appetoot!",
"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": "Mais",
"status.more": "More",
"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": "Seu rascunho será perdido se você sair do Mastodon.",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Arraste e solte para enviar",
"upload_button.label": "Adicionar mídia",
"upload_form.description": "Descreva a imagem para deficientes visuais",

View File

@@ -1,7 +1,7 @@
{
"account.block": "Bloquear @{name}",
"account.block_domain": "Esconder tudo do domínio {domain}",
"account.disclaimer_full": "As informações abaixo podem refletir o perfil do usuário de forma incompleta.",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"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": "Mostrar {domain}",
"account.unblock_domain": "Unhide {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": "Listas",
"column.lists": "Lists",
"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": "Tens a certeza de que desejas apagar permanentemente esta lista?",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"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": "Atalho",
"keyboard_shortcuts.hotkey": "Hotkey",
"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": "Adicionar à lista",
"lists.account.remove": "Remover da lista",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"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",
"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",
"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": "Listas",
"navigation_bar.lists": "Lists",
"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": "O texto simples retorna a correspondência de nomes, utilizadores e hashtags",
"search_popout.tips.text": "Simple text returns matching display names, usernames and 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": "Incorporar",
"status.embed": "Embed",
"status.favourite": "Adicionar aos favoritos",
"status.load_more": "Carregar mais",
"status.media_hidden": "Media escondida",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Загрузка...",
"media_gallery.toggle_visible": "Показать/скрыть",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Laddar...",
"media_gallery.toggle_visible": "Växla synlighet",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Toggle visibility",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Yükleniyor...",
"media_gallery.toggle_visible": "Görünürlüğü değiştir",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "Завантаження...",
"media_gallery.toggle_visible": "Показати/приховати",

View File

@@ -1,2 +0,0 @@
[
]

View File

@@ -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": "提交",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "載入中...",
"media_gallery.toggle_visible": "打開或關上",

View File

@@ -133,7 +133,7 @@
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.search": "Search among follows",
"lists.subheading": "Your lists",
"loading_indicator.label": "讀取中...",
"media_gallery.toggle_visible": "切換可見性",

View File

@@ -12,8 +12,8 @@ function main() {
if (window.history && history.replaceState) {
const { pathname, search, hash } = window.location;
const path = pathname + search + hash;
if (!(/^\/web[$/]/).test(path)) {
history.replaceState(null, document.title, `/web${path}`);
if (!(/^\/\$vanilla[$/]/).test(path)) {
history.replaceState(null, document.title, `/$vanilla${path}`);
}
}

View File

@@ -15,7 +15,7 @@ const play = audio => {
if (typeof audio.fastSeek === 'function') {
audio.fastSeek(0);
} else {
audio.currentTime = 0;
audio.seek(0);
}
}

View File

@@ -1,10 +1,6 @@
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,
@@ -34,7 +30,6 @@ 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)));
}));
};
@@ -42,7 +37,6 @@ 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)));
}));
};
@@ -61,12 +55,6 @@ 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:

View File

@@ -102,16 +102,16 @@ const findBestClient = clients => {
const openUrl = url =>
self.clients.matchAll({ type: 'window' }).then(clientList => {
if (clientList.length !== 0) {
const webClients = clientList.filter(client => /\/web\//.test(client.url));
const webClients = clientList.filter(client => /\/\$vanilla\//.test(client.url));
if (webClients.length !== 0) {
const client = findBestClient(webClients);
const { pathname } = new URL(url);
if (pathname.startsWith('/web/')) {
if (pathname.startsWith('/$vanilla/')) {
return client.focus().then(client => client.postMessage({
type: 'navigate',
path: pathname.slice('/web/'.length - 1),
path: pathname.slice('/$vanilla/'.length - 1),
}));
}
} else if ('navigate' in clientList[0]) { // Chrome 42-48 does not support navigate

View File

@@ -1,46 +0,0 @@
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');

View File

@@ -62,13 +62,7 @@ export function connectStream(path, pollingRefresh = null, callbacks = () => ({
export default function getStream(streamingAPIBaseURL, accessToken, stream, { connected, received, disconnected, reconnected }) {
const params = [ `stream=${stream}` ];
if (accessToken !== null) {
params.push(`access_token=${accessToken}`);
}
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`);
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?access_token=${accessToken}&stream=${stream}`);
ws.onopen = connected;
ws.onmessage = e => received(JSON.parse(e.data));

View File

@@ -1,7 +1,6 @@
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) => {
@@ -36,33 +35,16 @@ const subscribe = (registration) =>
const unsubscribe = ({ registration, subscription }) =>
subscription ? subscription.unsubscribe().then(() => registration) : registration;
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);
};
const sendSubscriptionToBackend = (subscription) =>
axios.post('/api/web/push_subscriptions', {
subscription,
}).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()) {
@@ -97,9 +79,6 @@ 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 => {
@@ -111,9 +90,6 @@ export function register () {
// Clear alerts and hide UI settings
store.dispatch(clearSubscription());
if (me) {
pushNotificationsSetting.remove(me);
}
try {
getRegistration()

View File

@@ -265,288 +265,200 @@
.compose-form {
padding: 10px;
}
.compose-form__warning {
.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 {
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;
font-weight: 500;
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 {
text-decoration: none;
@each $lang in $cjk-langs {
&:lang(#{$lang}) {
font-weight: 700;
}
}
}
.compose-form__autosuggest-wrapper {
position: relative;
.emoji-picker-dropdown {
position: absolute;
right: 5px;
top: 5px;
}
}
.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;
a {
color: darken($ui-primary-color, 33%);
font-weight: 500;
text-decoration: underline;
&:hover,
&:focus,
&:active,
&.selected {
background: darken($ui-secondary-color, 10%);
&:focus {
text-decoration: none;
}
}
}
.autosuggest-account,
.autosuggest-emoji {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
line-height: 18px;
font-size: 14px;
.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;
}
}
.autosuggest-account-icon,
.autosuggest-emoji img {
.compose-form__upload-button-icon {
line-height: 27px;
}
.compose-form__sensitive-button {
display: none;
&.compose-form__sensitive-button--visible {
display: block;
margin-right: 8px;
width: 16px;
height: 16px;
}
.autosuggest-account .display-name__account {
color: lighten($ui-base-color, 36%);
.compose-form__sensitive-button__icon {
line-height: 27px;
}
}
.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__upload-wrapper {
overflow: hidden;
}
.compose-form__uploads-wrapper {
display: flex;
flex-direction: row;
padding: 5px;
flex-wrap: wrap;
}
.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;
.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 {
&-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;
background: darken($simple-background-color, 8%);
border-radius: 0 0 4px 4px;
display: flex;
justify-content: space-between;
opacity: 0;
transition: opacity .1s ease;
.compose-form__buttons {
display: flex;
input {
background: transparent;
color: $ui-secondary-color;
border: 0;
padding: 0;
margin: 0;
width: 100%;
font-family: inherit;
font-size: 14px;
font-weight: 500;
.compose-form__upload-button-icon {
line-height: 27px;
&:focus {
color: $white;
}
.compose-form__sensitive-button {
display: none;
&.compose-form__sensitive-button--visible {
display: block;
}
.compose-form__sensitive-button__icon {
line-height: 27px;
}
&::placeholder {
opacity: 0.54;
color: $ui-secondary-color;
}
}
.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;
}
}
&.active {
opacity: 1;
}
}
.compose-form__publish {
display: flex;
justify-content: flex-end;
min-width: 0;
.compose-form__publish-button-wrapper {
overflow: hidden;
padding-top: 10px;
}
.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;
}
.compose-form__label__text {
display: inline-block;
vertical-align: middle;
margin-bottom: 14px;
margin-left: 8px;
color: $ui-primary-color;
}
}
.compose-form__textarea,
.follow-form__input {
background: $simple-background-color;
&:disabled {
background: $ui-secondary-color;
}
}
.compose-form__autosuggest-wrapper {
position: relative;
.emoji-picker-dropdown {
position: absolute;
right: 5px;
top: 5px;
}
}
.compose-form__publish {
display: flex;
min-width: 0;
}
.compose-form__publish-button-wrapper {
overflow: hidden;
padding-top: 10px;
}
.emojione {
display: inline-block;
font-size: inherit;
@@ -606,7 +518,6 @@
font-weight: 400;
overflow: hidden;
white-space: pre-wrap;
padding-top: 2px;
&:focus {
outline: 0;
@@ -705,10 +616,6 @@
.status.status-direct {
background: lighten($ui-base-color, 12%);
&.muted {
background: transparent;
}
}
.detailed-status,
@@ -863,7 +770,7 @@
.status__action-bar {
align-items: center;
display: flex;
margin-top: 8px;
margin-top: 10px;
}
.status__action-bar-button {
@@ -896,7 +803,7 @@
.emojione {
width: 24px;
height: 24px;
margin: -1px 0 0;
margin: -3px 0 0;
}
}
@@ -2066,6 +1973,121 @@
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;
@@ -2251,19 +2273,14 @@ 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 {
@@ -3981,7 +3998,6 @@ button.icon-button.active i.fa-retweet {
position: relative;
background: $base-shadow-color;
max-width: 100%;
border-radius: 4px;
video {
height: 100%;
@@ -4016,8 +4032,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.85) 0, rgba($base-shadow-color, 0.45) 60%, transparent);
padding: 0 15px;
background: linear-gradient(0deg, rgba($base-shadow-color, 0.8) 0, rgba($base-shadow-color, 0.35) 60%, transparent);
padding: 0 10px;
opacity: 0;
transition: opacity .1s ease;
@@ -4070,67 +4086,40 @@ button.icon-button.active i.fa-retweet {
}
}
&__buttons-bar {
display: flex;
justify-content: space-between;
padding-bottom: 10px;
}
&__buttons {
padding-bottom: 10px;
font-size: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.left {
float: left;
button {
padding-left: 0;
padding-right: 10px;
}
}
&.right {
float: right;
button {
padding-right: 0;
padding-left: 10px;
}
}
button {
background: transparent;
padding: 2px 10px;
font-size: 16px;
padding: 0;
border: 0;
color: rgba($white, 0.75);
color: $white;
&:active,
&:hover,
&:focus {
color: $white;
color: $ui-highlight-color;
}
}
}
&__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;
@@ -4140,7 +4129,6 @@ button.icon-button.active i.fa-retweet {
content: "";
width: 100%;
background: rgba($white, 0.35);
border-radius: 4px;
display: block;
position: absolute;
height: 4px;
@@ -4152,9 +4140,8 @@ button.icon-button.active i.fa-retweet {
display: block;
position: absolute;
height: 4px;
border-radius: 4px;
top: 10px;
background: lighten($ui-highlight-color, 8%);
background: $ui-highlight-color;
}
&__buffer {
@@ -4171,8 +4158,7 @@ button.icon-button.active i.fa-retweet {
top: 6px;
margin-left: -6px;
transition: opacity .1s ease;
background: lighten($ui-highlight-color, 8%);
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
background: $ui-highlight-color;
pointer-events: none;
&.active {
@@ -4186,16 +4172,6 @@ button.icon-button.active i.fa-retweet {
}
}
}
&.detailed,
&.fullscreen {
.video-player__buttons {
button {
padding-top: 10px;
padding-bottom: 10px;
}
}
}
}
.media-spoiler-video {

View File

@@ -7,9 +7,9 @@ body.rtl {
margin-left: 5px;
}
.compose-form .compose-form__buttons-wrapper .character-counter__wrapper {
margin-right: 0;
margin-left: 4px;
.character-counter__wrapper {
margin-right: 8px;
margin-left: 16px;
}
.navigation-bar__profile {
@@ -30,22 +30,6 @@ 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 {
@@ -57,6 +41,10 @@ body.rtl {
float: left;
}
.compose-form__modifiers {
border-radius: 0 0 0 4px;
}
.setting-toggle {
margin-left: 0;
margin-right: 8px;

View File

@@ -1054,23 +1054,23 @@ body.admin {
}
}
.column-link[href="/web/timelines/public"] {
.column-link[href="/$vanilla/timelines/public"] {
background-image: url("~images/icon_public.png");
&:hover { background-image: url("~images/icon_public.png"); }
}
.column-link[href="/web/timelines/public/local"] {
.column-link[href="/$vanilla/timelines/public/local"] {
background-image: url("~images/icon_local.png");
&:hover { background-image: url("~images/icon_local.png"); }
}
.column-link[href="/web/pinned"] {
.column-link[href="/$vanilla/pinned"] {
background-image: url("~images/icon_pin.png");
&:hover { background-image: url("~images/icon_pin.png"); }
}
.column-link[href="/web/favourites"] {
.column-link[href="/$vanilla/favourites"] {
background-image: url("~images/icon_likes.png");
&:hover { background-image: url("~images/icon_likes.png"); }
}
.column-link[href="/web/blocks"] {
.column-link[href="/$vanilla/blocks"] {
background-image: url("~images/icon_blocks.png");
&:hover { background-image: url("~images/icon_blocks.png"); }
}

View File

@@ -20,13 +20,11 @@ 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)
attach_media(@status, media_attachments)
process_attachments(@status)
end
resolve_thread(@status)
@@ -107,36 +105,22 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
emoji.save
end
def process_attachments
def process_attachments(status)
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(account: @account, remote_url: href, description: attachment['name'].presence)
media_attachments << media_attachment
media_attachment = MediaAttachment.create(status: status, account: status.account, remote_url: href, description: attachment['name'].presence)
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)

View File

@@ -26,8 +26,6 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
cached_reblog = reblog
status = nil
media_attachments = save_media
ApplicationRecord.transaction do
status = Status.create!(
uri: id,
@@ -46,7 +44,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
save_mentions(status)
save_hashtags(status)
attach_media(status, media_attachments)
save_media(status)
save_emojis(status)
end
@@ -128,20 +126,18 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
ProcessHashtagsService.new.call(parent, tags)
end
def save_media
do_not_download = DomainBlock.find_by(domain: @account.domain)&.reject_media?
media_attachments = []
def save_media(parent)
do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
@xml.xpath('./xmlns:link[@rel="enclosure"]', xmlns: OStatus::TagManager::XMLNS).each do |link|
next unless link['href']
media = MediaAttachment.where(status: nil, remote_url: link['href']).first_or_initialize(account: @account, status: nil, remote_url: link['href'])
media = MediaAttachment.where(status: parent, remote_url: link['href']).first_or_initialize(account: parent.account, status: parent, 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
@@ -152,15 +148,6 @@ 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)

View File

@@ -2,26 +2,13 @@
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]
if options[:html]
html = Nokogiri::HTML(options[:html])
else
res = Request.new(:get, url).perform
raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html'
raise OEmbed::NotFound, url if res.code != 200 || res.mime_type != 'text/html'
html = Nokogiri::HTML(res.to_s)
end
html = Nokogiri::HTML(res.to_s)
if format.nil? || format == :json
provider_endpoint ||= html.at_xpath('//link[@type="application/json+oembed"]')&.attribute('href')&.value

View File

@@ -35,7 +35,7 @@ class StatusFilter
end
def silenced_account?
!account&.silenced? && status_account_silenced? && !account_following_status_account?
status_account_silenced? && !account_following_status_account?
end
def status_account_silenced?

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