Merge pull request #739 from ThibG/glitch-soc/merge-upstream

Merge upstream changes
lolsob-rspec
ThibG 2018-09-21 08:39:07 +02:00 committed by GitHub
commit a595ce525e
281 changed files with 6158 additions and 4333 deletions

View File

@ -1,66 +0,0 @@
{
"presets": [
"react",
[
"env",
{
"exclude": ["transform-async-to-generator", "transform-regenerator"],
"loose": true,
"modules": false,
"targets": {
"browsers": ["last 2 versions", "IE >= 11", "iOS >= 9"]
}
}
]
],
"plugins": [
"syntax-dynamic-import",
["transform-object-rest-spread", { "useBuiltIns": true }],
"transform-decorators-legacy",
"transform-class-properties",
[
"react-intl",
{
"messagesDir": "./build/messages"
}
],
"preval"
],
"env": {
"development": {
"plugins": [
"transform-react-jsx-source",
"transform-react-jsx-self"
]
},
"production": {
"plugins": [
"lodash",
[
"transform-react-remove-prop-types",
{
"mode": "remove",
"removeImport": true,
"additionalLibraries": [
"react-immutable-proptypes"
]
}
],
"transform-react-inline-elements",
[
"transform-runtime",
{
"helpers": true,
"polyfill": false,
"regenerator": false
}
]
]
},
"test": {
"plugins": [
"transform-es2015-modules-commonjs"
]
}
}
}

View File

@ -1,2 +1,2 @@
VAGRANT=true
LOCAL_DOMAIN=mastodon.dev
LOCAL_DOMAIN=mastodon.local

View File

@ -77,6 +77,11 @@ Rails/SkipsModelValidations:
Rails/HttpStatus:
Enabled: false
Rails/Exit:
Exclude:
- 'lib/mastodon/*'
- 'lib/cli'
Style/ClassAndModuleChildren:
Enabled: false

View File

@ -34,7 +34,7 @@ gem 'devise', '~> 4.4'
gem 'devise-two-factor', '~> 3.0'
group :pam_authentication, optional: true do
gem 'devise_pam_authenticatable2', '~> 9.1'
gem 'devise_pam_authenticatable2', '~> 9.2'
end
gem 'net-ldap', '~> 0.10'
@ -88,7 +88,7 @@ gem 'tty-command', '~> 0.8', require: false
gem 'tty-prompt', '~> 0.16', require: false
gem 'twitter-text', '~> 1.14'
gem 'tzinfo-data', '~> 1.2018'
gem 'webpacker', '~> 3.4'
gem 'webpacker', '~> 3.5'
gem 'webpush'
gem 'json-ld', '~> 2.2'

View File

@ -174,7 +174,7 @@ GEM
devise (~> 4.0)
railties (< 5.3)
rotp (~> 2.0)
devise_pam_authenticatable2 (9.1.1)
devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0)
rpam2 (~> 4.0)
diff-lcs (1.3)
@ -629,7 +629,7 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
webpacker (3.4.3)
webpacker (3.5.5)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
@ -671,7 +671,7 @@ DEPENDENCIES
derailed_benchmarks
devise (~> 4.4)
devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.1)
devise_pam_authenticatable2 (~> 9.2)
doorkeeper (~> 5.0)
dotenv-rails (~> 2.2, < 2.3)
fabrication (~> 2.20)
@ -761,7 +761,7 @@ DEPENDENCIES
twitter-text (~> 1.14)
tzinfo-data (~> 1.2018)
webmock (~> 3.3)
webpacker (~> 3.4)
webpacker (~> 3.5)
webpush
RUBY VERSION

14
Vagrantfile vendored
View File

@ -85,6 +85,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.provider :virtualbox do |vb|
vb.name = "mastodon"
vb.customize ["modifyvm", :id, "--memory", "4096"]
# Increase the number of CPUs. Uncomment and adjust to
# increase performance
# vb.customize ["modifyvm", :id, "--cpus", "3"]
# Disable VirtualBox DNS proxy to skip long-delay IPv6 resolutions.
# https://github.com/mitchellh/vagrant/issues/1172
@ -97,19 +100,22 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
end
config.vm.hostname = "mastodon.dev"
# This uses the vagrant-hostsupdater plugin, and lets you
# access the development site at http://mastodon.dev.
# access the development site at http://mastodon.local.
# If you change it, also change it in .env.vagrant before provisioning
# the vagrant server to update the development build.
#
# To install:
# $ vagrant plugin install vagrant-hostsupdater
config.vm.hostname = "mastodon.local"
if defined?(VagrantPlugins::HostsUpdater)
config.vm.network :private_network, ip: "192.168.42.42", nictype: "virtio"
config.hostsupdater.remove_on_suspend = false
end
if config.vm.networks.any? { |type, options| type == :private_network }
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp']
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'actimeo=1']
else
config.vm.synced_folder ".", "/vagrant"
end

View File

@ -133,7 +133,7 @@ class Auth::SessionsController < Devise::SessionsController
def clear_site_data
return if continue_after?
# Should be '"*"' but that doen't work in Chrome (neither does '"executionContexts"')
# Should be '"*"' but that doesn't work in Chrome (neither does '"executionContexts"')
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data
response.headers['Clear-Site-Data'] = '"cache", "cookies"'
end

View File

@ -4,7 +4,7 @@ module Admin::AccountModerationNotesHelper
def admin_account_link_to(account)
return if account.nil?
link_to admin_account_path(account.id), class: name_tag_classes(account) do
link_to admin_account_path(account.id), class: name_tag_classes(account), title: account.acct do
safe_join([
image_tag(account.avatar.url, width: 15, height: 15, alt: display_name(account), class: 'avatar'),
content_tag(:span, account.acct, class: 'username'),
@ -15,7 +15,7 @@ module Admin::AccountModerationNotesHelper
def admin_account_inline_link_to(account)
return if account.nil?
link_to admin_account_path(account.id), class: name_tag_classes(account, true) do
link_to admin_account_path(account.id), class: name_tag_classes(account, true), title: account.acct do
content_tag(:span, account.acct, class: 'username')
end
end

View File

@ -7,13 +7,13 @@ module HomeHelper
}
end
def account_link_to(account, button = '')
def account_link_to(account, button = '', size: 36, path: nil)
content_tag(:div, class: 'account') do
content_tag(:div, class: 'account__wrapper') do
section = if account.nil?
content_tag(:div, class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{full_asset_url('avatars/original/missing.png', skip_pipeline: true)})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:strong, t('about.contact_missing')) +
@ -21,9 +21,9 @@ module HomeHelper
end
end
else
link_to(TagManager.instance.url_for(account), class: 'account__display-name') do
link_to(path || TagManager.instance.url_for(account), class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
content_tag(:div, '', class: 'account__avatar', style: "background-image: url(#{account.avatar.url})")
content_tag(:div, '', class: 'account__avatar', style: "width: #{size}px; height: #{size}px; background-size: #{size}px #{size}px; background-image: url(#{account.avatar.url})")
end +
content_tag(:span, class: 'display-name') do
content_tag(:bdi) do
@ -48,4 +48,12 @@ module HomeHelper
'1+'
end
end
def custom_field_classes(field)
if field.verified?
'verified'
else
'emojify'
end
end
end

View File

@ -50,3 +50,27 @@ delegate(document, '#account_locked', 'change', ({ target }) => {
lock.style.display = 'none';
}
});
delegate(document, '.input-copy input', 'click', ({ target }) => {
target.select();
});
delegate(document, '.input-copy button', 'click', ({ target }) => {
const input = target.parentNode.querySelector('input');
input.focus();
input.select();
try {
if (document.execCommand('copy')) {
input.blur();
target.parentNode.classList.add('copied');
setTimeout(() => {
target.parentNode.classList.remove('copied');
}, 700);
}
} catch (err) {
console.error(err);
}
});

View File

@ -267,6 +267,20 @@
}
}
.verified {
border: 1px solid rgba($valid-value-color, 0.5);
background: rgba($valid-value-color, 0.25);
a {
color: $valid-value-color;
font-weight: 500;
}
&__mark {
color: $valid-value-color;
}
}
dl:last-child {
border-bottom: 0;
}

View File

@ -1,3 +1,5 @@
$no-columns-breakpoint: 600px;
.admin-wrapper {
display: flex;
justify-content: center;
@ -24,12 +26,22 @@
height: 100px;
}
@media screen and (max-width: $no-columns-breakpoint) {
& > a:first-child {
display: none;
}
}
ul {
list-style: none;
border-radius: 4px 0 0 4px;
overflow: hidden;
margin-bottom: 20px;
@media screen and (max-width: $no-columns-breakpoint) {
margin-bottom: 0;
}
a {
display: block;
padding: 15px;
@ -62,19 +74,23 @@
a {
border: 0;
padding: 15px 35px;
&.selected {
color: $primary-text-color;
background-color: $ui-highlight-color;
border-bottom: 0;
border-radius: 0;
&:hover {
background-color: lighten($ui-highlight-color, 5%);
}
}
}
}
.simple-navigation-active-leaf a {
color: $primary-text-color;
background-color: $ui-highlight-color;
border-bottom: 0;
border-radius: 0;
&:hover {
background-color: lighten($ui-highlight-color, 5%);
}
}
}
& > ul > .simple-navigation-active-leaf a {
border-radius: 4px 0 0 4px;
}
}
@ -89,11 +105,19 @@
padding-top: 60px;
padding-left: 25px;
@media screen and (max-width: $no-columns-breakpoint) {
max-width: none;
padding: 15px;
padding-top: 30px;
}
h2 {
color: $secondary-text-color;
font-size: 24px;
line-height: 28px;
font-weight: 400;
padding-bottom: 40px;
border-bottom: 1px solid lighten($ui-base-color, 8%);
margin-bottom: 40px;
}
@ -108,7 +132,7 @@
h4 {
text-transform: uppercase;
font-size: 13px;
font-weight: 500;
font-weight: 700;
color: $darker-text-color;
padding-bottom: 8px;
margin-bottom: 8px;
@ -122,6 +146,11 @@
font-weight: 400;
}
.fields-group h6 {
color: $primary-text-color;
font-weight: 500;
}
& > p {
font-size: 14px;
line-height: 18px;
@ -167,30 +196,7 @@
}
}
.simple_form {
max-width: 400px;
&.edit_user,
&.new_form_admin_settings,
&.new_form_two_factor_confirmation,
&.new_form_delete_confirmation,
&.new_import,
&.new_domain_block,
&.edit_domain_block {
max-width: none;
}
.form_two_factor_confirmation_code,
.form_delete_confirmation_password {
max-width: 400px;
}
.actions {
max-width: 400px;
}
}
@media screen and (max-width: 600px) {
@media screen and (max-width: $no-columns-breakpoint) {
display: block;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
@ -204,16 +210,8 @@
.sidebar {
width: 100%;
padding: 10px 0;
padding: 0;
height: auto;
.logo {
margin: 20px auto;
}
}
.content {
padding-top: 20px;
}
}
}
@ -578,3 +576,102 @@ a.name-tag,
color: $dark-text-color;
}
}
.report-card {
background: $ui-base-color;
border-radius: 4px;
margin-bottom: 20px;
&__profile {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
.account {
padding: 0;
border: 0;
&__avatar-wrapper {
margin-left: 0;
}
}
&__stats {
flex: 0 0 auto;
font-weight: 500;
color: $darker-text-color;
text-transform: uppercase;
text-align: right;
a {
color: inherit;
text-decoration: none;
&:focus,
&:hover,
&:active {
color: lighten($darker-text-color, 8%);
}
}
.red {
color: $error-value-color;
}
}
}
&__summary {
&__item {
display: flex;
justify-content: flex-start;
border-top: 1px solid darken($ui-base-color, 4%);
&:hover {
background: lighten($ui-base-color, 2%);
}
&__reported-by,
&__assigned {
padding: 15px;
flex: 0 0 auto;
box-sizing: border-box;
width: 150px;
color: $darker-text-color;
&,
.username {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
&__content {
flex: 1 1 auto;
max-width: calc(100% - 300px);
&__icon {
color: $dark-text-color;
margin-right: 4px;
font-weight: 500;
}
}
&__content a {
display: block;
box-sizing: border-box;
width: 100%;
padding: 15px;
text-decoration: none;
color: $darker-text-color;
}
}
}
}
.one-line {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -1,3 +1,10 @@
@function hex-color($color) {
@if type-of($color) == 'color' {
$color: str-slice(ie-hex-str($color), 4);
}
@return '%23' + unquote($color)
}
body {
font-family: 'mastodon-font-sans-serif', sans-serif;
background: darken($ui-base-color, 8%);

File diff suppressed because one or more lines are too long

View File

@ -724,6 +724,14 @@
a {
color: lighten($ui-highlight-color, 8%);
}
dl:first-child .verified {
border-radius: 0 4px 0 0;
}
.verified a {
color: $valid-value-color;
}
}
.account__header__content {

View File

@ -1,3 +1,5 @@
$no-columns-breakpoint: 600px;
code {
font-family: 'mastodon-font-monospace', monospace;
font-weight: 400;
@ -13,6 +15,60 @@ code {
.input {
margin-bottom: 15px;
overflow: hidden;
&.hidden {
margin: 0;
}
&.radio_buttons {
.radio {
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
}
.radio > label {
position: relative;
padding-left: 28px;
input {
position: absolute;
top: -2px;
left: 0;
}
}
}
&.boolean {
position: relative;
margin-bottom: 0;
.label_input > label {
font-family: inherit;
font-size: 14px;
padding-top: 5px;
color: $primary-text-color;
display: block;
width: auto;
}
.label_input,
.hint {
padding-left: 28px;
}
.label_input__wrapper {
position: static;
}
label.checkbox {
position: absolute;
top: 2px;
left: 0;
}
}
}
.row {
@ -27,9 +83,22 @@ code {
}
}
.hint {
color: $darker-text-color;
a {
color: $highlight-text-color;
}
code {
border-radius: 3px;
padding: 0.2em 0.4em;
background: darken($ui-base-color, 12%);
}
}
span.hint {
display: block;
color: $darker-text-color;
font-size: 12px;
margin-top: 4px;
}
@ -44,11 +113,6 @@ code {
line-height: 18px;
margin-top: 15px;
margin-bottom: 0;
color: $darker-text-color;
a {
color: $highlight-text-color;
}
}
}
@ -66,81 +130,60 @@ code {
}
}
.label_input {
display: flex;
.input.with_floating_label {
.label_input {
display: flex;
label {
flex: 0 0 auto;
& > label {
font-family: inherit;
font-size: 14px;
color: $primary-text-color;
font-weight: 500;
min-width: 150px;
flex: 0 0 auto;
}
input,
select {
flex: 1 1 auto;
}
}
input {
flex: 1 1 auto;
&.select .hint {
margin-top: 6px;
margin-left: 150px;
}
}
.input.with_label {
padding: 15px 0;
margin-bottom: 0;
.label_input {
flex-wrap: wrap;
align-items: flex-start;
}
&.select .label_input {
align-items: initial;
}
.label_input > label {
font-family: inherit;
font-size: 16px;
font-size: 14px;
color: $primary-text-color;
display: block;
padding-top: 5px;
margin-bottom: 5px;
flex: 1;
min-width: 150px;
margin-bottom: 8px;
word-wrap: break-word;
font-weight: 500;
}
&.select {
flex: 0;
}
& ~ * {
margin-left: 10px;
}
.hint {
margin-top: 6px;
}
ul {
flex: 390px;
}
&.boolean {
padding: initial;
margin-bottom: initial;
.label_input > label {
font-family: inherit;
font-size: 14px;
color: $primary-text-color;
display: block;
width: auto;
}
label.checkbox {
position: relative;
padding-left: 25px;
flex: 1 1 auto;
}
}
}
.input.with_block_label {
max-width: none;
& > label {
font-family: inherit;
font-size: 16px;
color: $primary-text-color;
display: block;
font-weight: 500;
padding-top: 5px;
}
@ -148,14 +191,64 @@ code {
margin-bottom: 15px;
}
li {
float: left;
width: 50%;
ul {
columns: 2;
}
}
.required abbr {
text-decoration: none;
color: lighten($error-value-color, 12%);
}
.fields-group {
margin-bottom: 25px;
.input:last-child {
margin-bottom: 0;
}
}
.fields-row {
display: flex;
margin: 0 -10px;
padding-top: 5px;
margin-bottom: 25px;
.input {
max-width: none;
}
&__column {
box-sizing: border-box;
padding: 0 10px;
flex: 1 1 auto;
min-height: 1px;
&-6 {
max-width: 50%;
}
}
.fields-group:last-child,
.fields-row__column.fields-group {
margin-bottom: 0;
}
@media screen and (max-width: $no-columns-breakpoint) {
display: block;
margin-bottom: 0;
&__column {
max-width: none;
}
.fields-group:last-child,
.fields-row__column.fields-group,
.fields-row__column {
margin-bottom: 25px;
}
}
}
.input.radio_buttons .radio label {
@ -167,36 +260,6 @@ code {
width: auto;
}
.input.boolean {
margin-bottom: 5px;
label {
font-family: inherit;
font-size: 14px;
color: $primary-text-color;
display: block;
width: auto;
}
label.checkbox {
position: relative;
padding-left: 25px;
flex: 1 1 auto;
}
input[type=checkbox] {
position: absolute;
left: 0;
top: 5px;
margin: 0;
}
.hint {
padding-left: 25px;
margin-left: 0;
}
}
.check_boxes {
.checkbox {
label {
@ -225,12 +288,7 @@ code {
input[type=email],
input[type=password],
textarea {
background: transparent;
box-sizing: border-box;
border: 0;
border-bottom: 2px solid $ui-primary-color;
border-radius: 2px 2px 0 0;
padding: 7px 4px;
font-size: 16px;
color: $primary-text-color;
display: block;
@ -238,23 +296,31 @@ code {
outline: 0;
font-family: inherit;
resize: vertical;
background: darken($ui-base-color, 10%);
border: 1px solid darken($ui-base-color, 14%);
border-radius: 4px;
padding: 10px;
&:invalid {
box-shadow: none;
}
&:focus:invalid {
border-bottom-color: lighten($error-red, 12%);
border-color: lighten($error-red, 12%);
}
&:required:valid {
border-bottom-color: $valid-value-color;
border-color: $valid-value-color;
}
&:hover {
border-color: darken($ui-base-color, 20%);
}
&:active,
&:focus {
border-bottom-color: $highlight-text-color;
background: rgba($base-overlay-background, 0.1);
border-color: $highlight-text-color;
background: darken($ui-base-color, 8%);
}
}
@ -338,28 +404,52 @@ code {
}
select {
appearance: none;
box-sizing: border-box;
font-size: 16px;
max-height: 29px;
color: $primary-text-color;
display: block;
width: 100%;
outline: 0;
font-family: inherit;
resize: vertical;
background: darken($ui-base-color, 10%) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14.933 18.467' height='19.698' width='15.929'><path d='M3.467 14.967l-3.393-3.5H14.86l-3.392 3.5c-1.866 1.925-3.666 3.5-4 3.5-.335 0-2.135-1.575-4-3.5zm.266-11.234L7.467 0 11.2 3.733l3.733 3.734H0l3.733-3.734z' fill='#{hex-color(lighten($ui-base-color, 12%))}'/></svg>") no-repeat right 8px center / auto 16px;
border: 1px solid darken($ui-base-color, 14%);
border-radius: 4px;
padding: 10px;
height: 41px;
}
.input-with-append {
position: relative;
.input input {
padding-right: 127px;
.label_input {
&__wrapper {
position: relative;
}
.append {
&__append {
position: absolute;
right: 0;
top: 0;
padding: 7px 4px;
right: 1px;
top: 1px;
padding: 10px;
padding-bottom: 9px;
font-size: 16px;
color: $dark-text-color;
font-family: inherit;
pointer-events: none;
cursor: default;
max-width: 140px;
white-space: nowrap;
overflow: hidden;
&::after {
content: '';
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 1px;
width: 5px;
background-image: linear-gradient(to right, rgba(darken($ui-base-color, 10%), 0), darken($ui-base-color, 10%));
}
}
}
}
@ -434,6 +524,30 @@ code {
}
}
.quick-nav {
list-style: none;
margin-bottom: 25px;
font-size: 14px;
li {
display: inline-block;
margin-right: 10px;
}
a {
color: $highlight-text-color;
text-transform: uppercase;
text-decoration: none;
font-weight: 700;
&:hover,
&:focus,
&:active {
color: lighten($highlight-text-color, 8%);
}
}
}
.oauth-prompt,
.follow-prompt {
margin-bottom: 30px;
@ -592,3 +706,64 @@ code {
display: block;
}
}
.scope-danger {
color: $warning-red;
}
.form_admin_settings_site_short_description,
.form_admin_settings_site_description,
.form_admin_settings_site_extended_description,
.form_admin_settings_site_terms,
.form_admin_settings_custom_css,
.form_admin_settings_closed_registrations_message {
textarea {
font-family: 'mastodon-font-monospace', monospace;
}
}
.input-copy {
background: darken($ui-base-color, 10%);
border: 1px solid darken($ui-base-color, 14%);
border-radius: 4px;
display: flex;
align-items: center;
padding-right: 4px;
position: relative;
top: 1px;
transition: border-color 300ms linear;
&__wrapper {
flex: 1 1 auto;
}
input[type=text] {
background: transparent;
border: 0;
padding: 10px;
font-size: 14px;
font-family: 'mastodon-font-monospace', monospace;
}
button {
flex: 0 0 auto;
margin: 4px;
text-transform: none;
font-weight: 400;
font-size: 14px;
padding: 7px 18px;
padding-bottom: 6px;
width: auto;
transition: background 300ms linear;
}
&.copied {
border-color: $valid-value-color;
transition: none;
button {
background: $valid-value-color;
transition: none;
}
}
}

View File

@ -206,13 +206,19 @@ body.rtl {
}
.simple_form .input-with-append .input input {
padding-left: 127px;
padding-left: 142px;
padding-right: 0;
}
.simple_form .input-with-append .append {
right: auto;
left: 0;
&::after {
right: auto;
left: 0;
background-image: linear-gradient(to left, rgba($ui-base-color, 0), $ui-base-color);
}
}
.table th,

View File

@ -1,8 +1,8 @@
export const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN';
export const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE';
export function openDropdownMenu(id, placement) {
return { type: DROPDOWN_MENU_OPEN, id, placement };
export function openDropdownMenu(id, placement, keyboard) {
return { type: DROPDOWN_MENU_OPEN, id, placement, keyboard };
}
export function closeDropdownMenu(id) {

View File

@ -3,7 +3,6 @@
exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] = `
<button
className="button button-secondary"
disabled={undefined}
onClick={[Function]}
style={
Object {
@ -18,7 +17,6 @@ exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] =
exports[`<Button /> renders a button element 1`] = `
<button
className="button"
disabled={undefined}
onClick={[Function]}
style={
Object {
@ -48,7 +46,6 @@ exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = `
exports[`<Button /> renders class="button--block" if props.block given 1`] = `
<button
className="button button--block"
disabled={undefined}
onClick={[Function]}
style={
Object {
@ -63,7 +60,6 @@ exports[`<Button /> renders class="button--block" if props.block given 1`] = `
exports[`<Button /> renders the children 1`] = `
<button
className="button"
disabled={undefined}
onClick={[Function]}
style={
Object {
@ -82,7 +78,6 @@ exports[`<Button /> renders the children 1`] = `
exports[`<Button /> renders the given text 1`] = `
<button
className="button"
disabled={undefined}
onClick={[Function]}
style={
Object {
@ -99,7 +94,6 @@ exports[`<Button /> renders the given text 1`] = `
exports[`<Button /> renders the props.text instead of children 1`] = `
<button
className="button"
disabled={undefined}
onClick={[Function]}
style={
Object {

View File

@ -19,8 +19,8 @@ const messages = defineMessages({
unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
});
@injectIntl
export default class Account extends ImmutablePureComponent {
export default @injectIntl
class Account extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,

View File

@ -10,8 +10,8 @@ const messages = defineMessages({
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
});
@injectIntl
export default class ColumnHeader extends React.PureComponent {
export default @injectIntl
class ColumnHeader extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -8,8 +8,8 @@ const messages = defineMessages({
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
});
@injectIntl
export default class Account extends ImmutablePureComponent {
export default @injectIntl
class Account extends ImmutablePureComponent {
static propTypes = {
domain: PropTypes.string,

View File

@ -23,6 +23,7 @@ class DropdownMenu extends React.PureComponent {
placement: PropTypes.string,
arrowOffsetLeft: PropTypes.string,
arrowOffsetTop: PropTypes.string,
openedViaKeyboard: PropTypes.bool,
};
static defaultProps = {
@ -42,13 +43,15 @@ class DropdownMenu extends React.PureComponent {
componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false);
document.addEventListener('keydown', this.handleKeyDown, false);
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
if (this.focusedItem) this.focusedItem.focus();
if (this.focusedItem && this.props.openedViaKeyboard) this.focusedItem.focus();
this.setState({ mounted: true });
}
componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false);
document.removeEventListener('keydown', this.handleKeyDown, false);
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
}
@ -62,13 +65,10 @@ class DropdownMenu extends React.PureComponent {
handleKeyDown = e => {
const items = Array.from(this.node.getElementsByTagName('a'));
const index = items.indexOf(e.currentTarget);
const index = items.indexOf(document.activeElement);
let element;
switch(e.key) {
case 'Enter':
this.handleClick(e);
break;
case 'ArrowDown':
element = items[index+1];
if (element) {
@ -96,6 +96,12 @@ class DropdownMenu extends React.PureComponent {
}
}
handleItemKeyDown = e => {
if (e.key === 'Enter') {
this.handleClick(e);
}
}
handleClick = e => {
const i = Number(e.currentTarget.getAttribute('data-index'));
const { action, to } = this.props.items[i];
@ -120,7 +126,7 @@ class DropdownMenu extends React.PureComponent {
return (
<li className='dropdown-menu__item' key={`${text}-${i}`}>
<a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleKeyDown} data-index={i}>
<a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleItemKeyDown} data-index={i}>
{text}
</a>
</li>
@ -170,6 +176,7 @@ export default class Dropdown extends React.PureComponent {
onClose: PropTypes.func.isRequired,
dropdownPlacement: PropTypes.string,
openDropdownId: PropTypes.number,
openedViaKeyboard: PropTypes.bool,
};
static defaultProps = {
@ -180,14 +187,14 @@ export default class Dropdown extends React.PureComponent {
id: id++,
};
handleClick = ({ target }) => {
handleClick = ({ target, type }) => {
if (this.state.id === this.props.openDropdownId) {
this.handleClose();
} else {
const { top } = target.getBoundingClientRect();
const placement = top * 2 < innerHeight ? 'bottom' : 'top';
this.props.onOpen(this.state.id, this.handleItemClick, placement);
this.props.onOpen(this.state.id, this.handleItemClick, placement, type !== 'click');
}
}
@ -197,6 +204,11 @@ export default class Dropdown extends React.PureComponent {
handleKeyDown = e => {
switch(e.key) {
case ' ':
case 'Enter':
this.handleClick(e);
e.preventDefault();
break;
case 'Escape':
this.handleClose();
break;
@ -233,7 +245,7 @@ export default class Dropdown extends React.PureComponent {
}
render () {
const { icon, items, size, title, disabled, dropdownPlacement, openDropdownId } = this.props;
const { icon, items, size, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard } = this.props;
const open = this.state.id === openDropdownId;
return (
@ -249,7 +261,7 @@ export default class Dropdown extends React.PureComponent {
/>
<Overlay show={open} placement={dropdownPlacement} target={this.findTarget}>
<DropdownMenu items={items} onClose={this.handleClose} />
<DropdownMenu items={items} onClose={this.handleClose} openedViaKeyboard={openedViaKeyboard} />
</Overlay>
</div>
);

View File

@ -6,8 +6,8 @@ const messages = defineMessages({
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
});
@injectIntl
export default class LoadGap extends React.PureComponent {
export default @injectIntl
class LoadGap extends React.PureComponent {
static propTypes = {
disabled: PropTypes.bool,

View File

@ -179,8 +179,8 @@ class Item extends React.PureComponent {
}
@injectIntl
export default class MediaGallery extends React.PureComponent {
export default @injectIntl
class MediaGallery extends React.PureComponent {
static propTypes = {
sensitive: PropTypes.bool,

View File

@ -86,8 +86,8 @@ export const timeAgoString = (intl, date, now, year) => {
return relativeTime;
};
@injectIntl
export default class RelativeTimestamp extends React.Component {
export default @injectIntl
class RelativeTimestamp extends React.Component {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

@ -35,8 +35,8 @@ export const textForScreenReader = (intl, status, rebloggedByText = false) => {
return values.join(', ');
};
@injectIntl
export default class Status extends ImmutablePureComponent {
export default @injectIntl
class Status extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -42,8 +42,8 @@ const obfuscatedCount = count => {
}
};
@injectIntl
export default class StatusActionBar extends ImmutablePureComponent {
export default @injectIntl
class StatusActionBar extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -8,15 +8,16 @@ const mapStateToProps = state => ({
isModalOpen: state.get('modal').modalType === 'ACTIONS',
dropdownPlacement: state.getIn(['dropdown_menu', 'placement']),
openDropdownId: state.getIn(['dropdown_menu', 'openId']),
openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']),
});
const mapDispatchToProps = (dispatch, { status, items }) => ({
onOpen(id, onItemClick, dropdownPlacement) {
onOpen(id, onItemClick, dropdownPlacement, keyboard) {
dispatch(isUserTouching() ? openModal('ACTIONS', {
status,
actions: items,
onClick: onItemClick,
}) : openDropdownMenu(id, dropdownPlacement));
}) : openDropdownMenu(id, dropdownPlacement, keyboard));
},
onClose(id) {
dispatch(closeModal());

View File

@ -2,7 +2,7 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { Link } from 'react-router-dom';
import { NavLink } from 'react-router-dom';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { me } from '../../../initial_state';
import { shortNumberFormat } from '../../../utils/numbers';
@ -36,8 +36,8 @@ const messages = defineMessages({
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
});
@injectIntl
export default class ActionBar extends React.PureComponent {
export default @injectIntl
class ActionBar extends React.PureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,
@ -60,6 +60,13 @@ export default class ActionBar extends React.PureComponent {
});
}
isStatusesPageActive = (match, location) => {
if (!match) {
return false;
}
return !location.pathname.match(/\/(followers|following)\/?$/);
}
render () {
const { account, intl } = this.props;
@ -147,20 +154,20 @@ export default class ActionBar extends React.PureComponent {
<div className='account__action-bar'>
<div className='account__action-bar-links'>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}>
<NavLink isActive={this.isStatusesPageActive} activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}`} title={intl.formatNumber(account.get('statuses_count'))}>
<FormattedMessage id='account.posts' defaultMessage='Toots' />
<strong>{shortNumberFormat(account.get('statuses_count'))}</strong>
</Link>
</NavLink>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}>
<NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/following`} title={intl.formatNumber(account.get('following_count'))}>
<FormattedMessage id='account.follows' defaultMessage='Follows' />
<strong>{shortNumberFormat(account.get('following_count'))}</strong>
</Link>
</NavLink>
<Link className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
<NavLink exact activeClassName='active' className='account__action-bar__tab' to={`/accounts/${account.get('id')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
<FormattedMessage id='account.followers' defaultMessage='Followers' />
<strong>{shortNumberFormat(account.get('followers_count'))}</strong>
</Link>
</NavLink>
</div>
<div className='account__action-bar-dropdown'>

View File

@ -15,8 +15,18 @@ const messages = defineMessages({
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
});
const dateFormatOptions = {
month: 'short',
day: 'numeric',
year: 'numeric',
hour12: false,
hour: '2-digit',
minute: '2-digit',
};
class Avatar extends ImmutablePureComponent {
static propTypes = {
@ -65,8 +75,8 @@ class Avatar extends ImmutablePureComponent {
}
@injectIntl
export default class Header extends ImmutablePureComponent {
export default @injectIntl
class Header extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map,
@ -163,7 +173,10 @@ export default class Header extends ImmutablePureComponent {
{fields.map((pair, i) => (
<dl key={i}>
<dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} />
<dd dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} title={pair.get('value_plain')} />
<dd className={pair.get('verified_at') && 'verified'} title={pair.get('value_plain')}>
{pair.get('verified_at') && <span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(pair.get('verified_at'), dateFormatOptions) })}><i className='fa fa-check verified__mark' /></span>} <span dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} />
</dd>
</dl>
))}
</div>

View File

@ -43,8 +43,8 @@ class LoadMoreMedia extends ImmutablePureComponent {
}
@connect(mapStateToProps)
export default class AccountGallery extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class AccountGallery extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -23,8 +23,8 @@ const mapStateToProps = (state, { params: { accountId }, withReplies = false })
};
};
@connect(mapStateToProps)
export default class AccountTimeline extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class AccountTimeline extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -20,9 +20,9 @@ const mapStateToProps = state => ({
accountIds: state.getIn(['user_lists', 'blocks', 'items']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Blocks extends ImmutablePureComponent {
class Blocks extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -4,8 +4,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, FormattedMessage } from 'react-intl';
import SettingToggle from '../../notifications/components/setting_toggle';
@injectIntl
export default class ColumnSettings extends React.PureComponent {
export default @injectIntl
class ColumnSettings extends React.PureComponent {
static propTypes = {
settings: ImmutablePropTypes.map.isRequired,

View File

@ -25,9 +25,9 @@ const mapStateToProps = (state, { onlyMedia, columnId }) => {
};
};
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class CommunityTimeline extends React.PureComponent {
class CommunityTimeline extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -17,8 +17,8 @@ const messages = defineMessages({
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
});
@injectIntl
export default class ActionBar extends React.PureComponent {
export default @injectIntl
class ActionBar extends React.PureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,

View File

@ -28,8 +28,8 @@ const messages = defineMessages({
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
});
@injectIntl
export default class ComposeForm extends ImmutablePureComponent {
export default @injectIntl
class ComposeForm extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

@ -261,6 +261,7 @@ class EmojiPickerMenu extends React.PureComponent {
skin={skinTone}
showPreview={false}
backgroundImageFn={backgroundImageFn}
autoFocus
emojiTooltip
/>
@ -277,8 +278,8 @@ class EmojiPickerMenu extends React.PureComponent {
}
@injectIntl
export default class EmojiPickerDropdown extends React.PureComponent {
export default @injectIntl
class EmojiPickerDropdown extends React.PureComponent {
static propTypes = {
custom_emojis: ImmutablePropTypes.list,

View File

@ -149,8 +149,8 @@ class PrivacyDropdownMenu extends React.PureComponent {
}
@injectIntl
export default class PrivacyDropdown extends React.PureComponent {
export default @injectIntl
class PrivacyDropdown extends React.PureComponent {
static propTypes = {
isUserTouching: PropTypes.func,

View File

@ -12,8 +12,8 @@ const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
});
@injectIntl
export default class ReplyIndicator extends ImmutablePureComponent {
export default @injectIntl
class ReplyIndicator extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -43,8 +43,8 @@ class SearchPopout extends React.PureComponent {
}
@injectIntl
export default class Search extends React.PureComponent {
export default @injectIntl
class Search extends React.PureComponent {
static propTypes = {
value: PropTypes.string.isRequired,

View File

@ -11,8 +11,8 @@ const messages = defineMessages({
description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' },
});
@injectIntl
export default class Upload extends ImmutablePureComponent {
export default @injectIntl
class Upload extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,

View File

@ -23,9 +23,9 @@ const iconStyle = {
lineHeight: '27px',
};
@connect(makeMapStateToProps)
export default @connect(makeMapStateToProps)
@injectIntl
export default class UploadButton extends ImmutablePureComponent {
class UploadButton extends ImmutablePureComponent {
static propTypes = {
disabled: PropTypes.bool,

View File

@ -30,9 +30,9 @@ const mapStateToProps = (state, ownProps) => ({
showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage,
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Compose extends React.PureComponent {
class Compose extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -170,7 +170,7 @@ export const urlRegex = (function() {
')' +
'\\)',
'i');
// Valid end-of-path chracters (so /foo. does not gobble the period).
// Valid end-of-path characters (so /foo. does not gobble the period).
// 1. Allow =&# for empty URL parameters and other URL-join artifacts
regexen.validUrlPathEndingChars = regexSupplant(/[^#{spaces_group}\(\)\?!\*';:=\,\.\$%\[\]#{pd}~&\|@]|(?:#{validUrlBalancedParens})/i);
// Allow @ in a url, but only in the middle. Catch things like http://example.com/@user/

View File

@ -9,8 +9,8 @@ const messages = defineMessages({
settings: { id: 'home.settings', defaultMessage: 'Column settings' },
});
@injectIntl
export default class ColumnSettings extends React.PureComponent {
export default @injectIntl
class ColumnSettings extends React.PureComponent {
static propTypes = {
settings: ImmutablePropTypes.map.isRequired,

View File

@ -17,9 +17,9 @@ const mapStateToProps = state => ({
hasUnread: state.getIn(['timelines', 'direct', 'unread']) > 0,
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class DirectTimeline extends React.PureComponent {
class DirectTimeline extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -21,9 +21,9 @@ const mapStateToProps = state => ({
domains: state.getIn(['domain_lists', 'blocks', 'items']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Blocks extends ImmutablePureComponent {
class Blocks extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -21,9 +21,9 @@ const mapStateToProps = state => ({
hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Favourites extends ImmutablePureComponent {
class Favourites extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -15,8 +15,8 @@ const mapStateToProps = (state, props) => ({
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
});
@connect(mapStateToProps)
export default class Favourites extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class Favourites extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -13,8 +13,8 @@ const messages = defineMessages({
reject: { id: 'follow_request.reject', defaultMessage: 'Reject' },
});
@injectIntl
export default class AccountAuthorize extends ImmutablePureComponent {
export default @injectIntl
class AccountAuthorize extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,

View File

@ -20,9 +20,9 @@ const mapStateToProps = state => ({
accountIds: state.getIn(['user_lists', 'follow_requests', 'items']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class FollowRequests extends ImmutablePureComponent {
class FollowRequests extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -22,8 +22,8 @@ const mapStateToProps = (state, props) => ({
hasMore: !!state.getIn(['user_lists', 'followers', props.params.accountId, 'next']),
});
@connect(mapStateToProps)
export default class Followers extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class Followers extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -22,8 +22,8 @@ const mapStateToProps = (state, props) => ({
hasMore: !!state.getIn(['user_lists', 'following', props.params.accountId, 'next']),
});
@connect(mapStateToProps)
export default class Following extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class Following extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -53,9 +53,9 @@ const badgeDisplay = (number, limit) => {
}
};
@connect(mapStateToProps, mapDispatchToProps)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default class GettingStarted extends ImmutablePureComponent {
class GettingStarted extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

@ -13,8 +13,8 @@ const mapStateToProps = (state, props) => ({
hasUnread: state.getIn(['timelines', `hashtag:${props.params.id}`, 'unread']) > 0,
});
@connect(mapStateToProps)
export default class HashtagTimeline extends React.PureComponent {
export default @connect(mapStateToProps)
class HashtagTimeline extends React.PureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -4,8 +4,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, FormattedMessage } from 'react-intl';
import SettingToggle from '../../notifications/components/setting_toggle';
@injectIntl
export default class ColumnSettings extends React.PureComponent {
export default @injectIntl
class ColumnSettings extends React.PureComponent {
static propTypes = {
settings: ImmutablePropTypes.map.isRequired,

View File

@ -19,9 +19,9 @@ const mapStateToProps = state => ({
isPartial: state.getIn(['timelines', 'home', 'items', 0], null) === null,
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class HomeTimeline extends React.PureComponent {
class HomeTimeline extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -9,8 +9,8 @@ const messages = defineMessages({
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
});
@injectIntl
export default class KeyboardShortcuts extends ImmutablePureComponent {
export default @injectIntl
class KeyboardShortcuts extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

@ -31,9 +31,9 @@ const mapDispatchToProps = (dispatch, { accountId }) => ({
onAdd: () => dispatch(addToListEditor(accountId)),
});
@connect(makeMapStateToProps, mapDispatchToProps)
export default @connect(makeMapStateToProps, mapDispatchToProps)
@injectIntl
export default class Account extends ImmutablePureComponent {
class Account extends ImmutablePureComponent {
static propTypes = {
account: ImmutablePropTypes.map.isRequired,

View File

@ -19,9 +19,9 @@ const mapDispatchToProps = dispatch => ({
onChange: value => dispatch(changeListSuggestions(value)),
});
@connect(mapStateToProps, mapDispatchToProps)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default class Search extends React.PureComponent {
class Search extends React.PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

@ -22,9 +22,9 @@ const mapDispatchToProps = dispatch => ({
onReset: () => dispatch(resetListEditor()),
});
@connect(mapStateToProps, mapDispatchToProps)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default class ListEditor extends ImmutablePureComponent {
class ListEditor extends ImmutablePureComponent {
static propTypes = {
listId: PropTypes.string.isRequired,

View File

@ -25,9 +25,9 @@ const mapStateToProps = (state, props) => ({
hasUnread: state.getIn(['timelines', `list:${props.params.id}`, 'unread']) > 0,
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class ListTimeline extends React.PureComponent {
class ListTimeline extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -20,9 +20,9 @@ const mapDispatchToProps = dispatch => ({
onSubmit: () => dispatch(submitListEditor(true)),
});
@connect(mapStateToProps, mapDispatchToProps)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default class NewListForm extends React.PureComponent {
class NewListForm extends React.PureComponent {
static propTypes = {
value: PropTypes.string.isRequired,

View File

@ -31,9 +31,9 @@ const mapStateToProps = state => ({
lists: getOrderedLists(state),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Lists extends ImmutablePureComponent {
class Lists extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -20,9 +20,9 @@ const mapStateToProps = state => ({
accountIds: state.getIn(['user_lists', 'mutes', 'items']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Mutes extends ImmutablePureComponent {
class Mutes extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -16,8 +16,8 @@ const notificationForScreenReader = (intl, message, timestamp) => {
return output.join(', ');
};
@injectIntl
export default class Notification extends ImmutablePureComponent {
export default @injectIntl
class Notification extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -31,9 +31,9 @@ const mapStateToProps = state => ({
hasMore: state.getIn(['notifications', 'hasMore']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class Notifications extends React.PureComponent {
class Notifications extends React.PureComponent {
static propTypes = {
columnId: PropTypes.string,

View File

@ -18,9 +18,9 @@ const mapStateToProps = state => ({
hasMore: !!state.getIn(['status_lists', 'pins', 'next']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class PinnedStatuses extends ImmutablePureComponent {
class PinnedStatuses extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -25,9 +25,9 @@ const mapStateToProps = (state, { onlyMedia, columnId }) => {
};
};
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class PublicTimeline extends React.PureComponent {
class PublicTimeline extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -15,8 +15,8 @@ const mapStateToProps = (state, props) => ({
accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId]),
});
@connect(mapStateToProps)
export default class Reblogs extends ImmutablePureComponent {
export default @connect(mapStateToProps)
class Reblogs extends ImmutablePureComponent {
static propTypes = {
params: PropTypes.object.isRequired,

View File

@ -12,9 +12,9 @@ const messages = defineMessages({
title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
});
@connect()
export default @connect()
@injectIntl
export default class CommunityTimeline extends React.PureComponent {
class CommunityTimeline extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -7,8 +7,8 @@ import Column from '../../../components/column';
import ColumnHeader from '../../../components/column_header';
import { connectHashtagStream } from '../../../actions/streaming';
@connect()
export default class HashtagTimeline extends React.PureComponent {
export default @connect()
class HashtagTimeline extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -12,9 +12,9 @@ const messages = defineMessages({
title: { id: 'standalone.public_title', defaultMessage: 'A look inside...' },
});
@connect()
export default @connect()
@injectIntl
export default class PublicTimeline extends React.PureComponent {
class PublicTimeline extends React.PureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,

View File

@ -28,8 +28,8 @@ const messages = defineMessages({
embed: { id: 'status.embed', defaultMessage: 'Embed' },
});
@injectIntl
export default class ActionBar extends React.PureComponent {
export default @injectIntl
class ActionBar extends React.PureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -104,9 +104,9 @@ const makeMapStateToProps = () => {
return mapStateToProps;
};
@injectIntl
export default @injectIntl
@connect(makeMapStateToProps)
export default class Status extends ImmutablePureComponent {
class Status extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -13,8 +13,8 @@ const messages = defineMessages({
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
});
@injectIntl
export default class BoostModal extends ImmutablePureComponent {
export default @injectIntl
class BoostModal extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,

View File

@ -35,8 +35,8 @@ const messages = defineMessages({
const shouldHideFAB = path => path.match(/^\/statuses\//);
@component => injectIntl(component, { withRef: true })
export default class ColumnsArea extends ImmutablePureComponent {
export default @(component => injectIntl(component, { withRef: true }))
class ColumnsArea extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,

View File

@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from 'react-intl';
import Button from '../../../components/button';
@injectIntl
export default class ConfirmationModal extends React.PureComponent {
export default @injectIntl
class ConfirmationModal extends React.PureComponent {
static propTypes = {
message: PropTypes.node.isRequired,

View File

@ -4,8 +4,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage, injectIntl } from 'react-intl';
import api from '../../../api';
@injectIntl
export default class EmbedModal extends ImmutablePureComponent {
export default @injectIntl
class EmbedModal extends ImmutablePureComponent {
static propTypes = {
url: PropTypes.string.isRequired,

View File

@ -19,8 +19,8 @@ const mapDispatchToProps = (dispatch, { id }) => ({
});
@connect(mapStateToProps, mapDispatchToProps)
export default class FocalPointModal extends ImmutablePureComponent {
export default @connect(mapStateToProps, mapDispatchToProps)
class FocalPointModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,

View File

@ -18,8 +18,8 @@ const messages = defineMessages({
export const previewState = 'previewMediaModal';
@injectIntl
export default class MediaModal extends ImmutablePureComponent {
export default @injectIntl
class MediaModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.list.isRequired,
@ -149,7 +149,7 @@ export default class MediaModal extends ImmutablePureComponent {
startTime={time || 0}
onCloseVideo={onClose}
detailed
description={image.get('description')}
alt={image.get('description')}
key={image.get('url')}
/>
);

View File

@ -33,9 +33,9 @@ const mapDispatchToProps = dispatch => {
};
};
@connect(mapStateToProps, mapDispatchToProps)
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default class MuteModal extends React.PureComponent {
class MuteModal extends React.PureComponent {
static propTypes = {
isSubmitting: PropTypes.bool.isRequired,

View File

@ -177,9 +177,9 @@ const mapStateToProps = state => ({
domain: state.getIn(['meta', 'domain']),
});
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
export default class OnboardingModal extends React.PureComponent {
class OnboardingModal extends React.PureComponent {
static propTypes = {
onClose: PropTypes.func.isRequired,

View File

@ -37,9 +37,9 @@ const makeMapStateToProps = () => {
return mapStateToProps;
};
@connect(makeMapStateToProps)
export default @connect(makeMapStateToProps)
@injectIntl
export default class ReportModal extends ImmutablePureComponent {
class ReportModal extends ImmutablePureComponent {
static propTypes = {
isSubmitting: PropTypes.bool,
@ -106,6 +106,7 @@ export default class ReportModal extends ImmutablePureComponent {
onChange={this.handleCommentChange}
onKeyDown={this.handleKeyDown}
disabled={isSubmitting}
autoFocus
/>
{domain && (

View File

@ -24,9 +24,9 @@ export function getLink (index) {
return links[index].props.to;
}
@injectIntl
export default @injectIntl
@withRouter
export default class TabsBar extends React.PureComponent {
class TabsBar extends React.PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,

View File

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

View File

@ -137,6 +137,7 @@ export default class ZoomableImage extends React.PureComponent {
role='presentation'
ref={this.setImageRef}
alt={alt}
title={alt}
src={src}
style={{
transform: `scale(${scale})`,

View File

@ -187,10 +187,10 @@ class SwitchingColumnsArea extends React.PureComponent {
}
@connect(mapStateToProps)
export default @connect(mapStateToProps)
@injectIntl
@withRouter
export default class UI extends React.PureComponent {
class UI extends React.PureComponent {
static contextTypes = {
router: PropTypes.object.isRequired,

View File

@ -26,7 +26,7 @@ WrappedSwitch.propTypes = {
children: PropTypes.node,
};
// Small Wraper to extract the params from the route and pass
// Small Wrapper to extract the params from the route and pass
// them to the rendered component, together with the content to
// be rendered inside (the children)
export class WrappedRoute extends React.Component {

View File

@ -84,8 +84,8 @@ export const getPointerPosition = (el, event) => {
return position;
};
@injectIntl
export default class Video extends React.PureComponent {
export default @injectIntl
class Video extends React.PureComponent {
static propTypes = {
preview: PropTypes.string,
@ -252,11 +252,12 @@ export default class Video extends React.PureComponent {
}
handleOpenVideo = () => {
const { src, preview, width, height } = this.props;
const { src, preview, width, height, alt } = this.props;
const media = fromJS({
type: 'video',
url: src,
preview_url: preview,
description: alt,
width,
height,
});

View File

@ -15,6 +15,7 @@
"account.follows.empty": "هذا المستخدِم لا يتبع أحدًا بعد.",
"account.follows_you": "يتابعك",
"account.hide_reblogs": "إخفاء ترقيات @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "وسائط",
"account.mention": "أُذكُر @{name}",
"account.moved_to": "{name} إنتقل إلى :",

View File

@ -1,174 +1,175 @@
{
"account.badges.bot": "Bot",
"account.block": "Block @{name}",
"account.badges.bot": "Robó",
"account.block": "Bloquiar a @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
"account.direct": "Direct message @{name}",
"account.direct": "Unviar un mensaxe direutu a @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Edit profile",
"account.edit_profile": "Editar perfil",
"account.endorse": "Feature on profile",
"account.follow": "Follow",
"account.followers": "Followers",
"account.followers": "Siguidores",
"account.followers.empty": "No one follows this user yet.",
"account.follows": "Follows",
"account.follows.empty": "This user doesn't follow anyone yet.",
"account.follows.empty": "Esti usuariu entá nun sigue a naide.",
"account.follows_you": "Follows you",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Media",
"account.mention": "Mention @{name}",
"account.mention": "Mentar a @{name}",
"account.moved_to": "{name} has moved to:",
"account.mute": "Mute @{name}",
"account.mute": "Silenciar a @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.muted": "Muted",
"account.posts": "Toots",
"account.posts_with_replies": "Toots and replies",
"account.posts_with_replies": "Toots y rempuestes",
"account.report": "Report @{name}",
"account.requested": "Awaiting approval. Click to cancel follow request",
"account.share": "Share @{name}'s profile",
"account.show_reblogs": "Show boosts from @{name}",
"account.unblock": "Unblock @{name}",
"account.unblock": "Desbloquiar a @{name}",
"account.unblock_domain": "Unhide {domain}",
"account.unendorse": "Don't feature on profile",
"account.unfollow": "Unfollow",
"account.unmute": "Unmute @{name}",
"account.unmute_notifications": "Unmute notifications from @{name}",
"account.view_full_profile": "View full profile",
"alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!",
"boost_modal.combo": "You can press {combo} to skip this next time",
"alert.unexpected.message": "Asocedió un fallu inesperáu.",
"alert.unexpected.title": "¡Ups!",
"boost_modal.combo": "Pues primir {combo} pa saltar esto la próxima vegada",
"bundle_column_error.body": "Something went wrong while loading this component.",
"bundle_column_error.retry": "Try again",
"bundle_column_error.title": "Network error",
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.blocks": "Usuarios bloquiaos",
"column.community": "Local timeline",
"column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
"column.home": "Home",
"column.lists": "Lists",
"column.mutes": "Muted users",
"column.notifications": "Notifications",
"column.pins": "Pinned toot",
"column.public": "Federated timeline",
"column_back_button.label": "Back",
"column.direct": "Mensaxes direutos",
"column.domain_blocks": "Dominios anubríos",
"column.favourites": "Favoritos",
"column.follow_requests": "Solicitúes de siguimientu",
"column.home": "Aniciu",
"column.lists": "Llistes",
"column.mutes": "Usuarios silenciaos",
"column.notifications": "Avisos",
"column.pins": "Toots fixaos",
"column.public": "Llinia temporal federada",
"column_back_button.label": "Atrás",
"column_header.hide_settings": "Hide settings",
"column_header.moveLeft_settings": "Move column to the left",
"column_header.moveRight_settings": "Move column to the right",
"column_header.moveLeft_settings": "Mover la columna a la esquierda",
"column_header.moveRight_settings": "Mover la columna a la drecha",
"column_header.pin": "Pin",
"column_header.show_settings": "Show settings",
"column_header.unpin": "Unpin",
"column_subheading.settings": "Settings",
"column_header.unpin": "Desfixar",
"column_subheading.settings": "Axustes",
"community.column_settings.media_only": "Media Only",
"compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
"compose_form.direct_message_warning": "Esti toot namái va unviase a los usuarios mentaos.",
"compose_form.direct_message_warning_learn_more": "Learn more",
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
"compose_form.placeholder": "What is on your mind?",
"compose_form.placeholder": "¿En qué pienses?",
"compose_form.publish": "Toot",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Media is marked as sensitive",
"compose_form.sensitive.unmarked": "Media is not marked as sensitive",
"compose_form.spoiler.marked": "Text is hidden behind warning",
"compose_form.spoiler.unmarked": "Text is not hidden",
"compose_form.spoiler_placeholder": "Write your warning here",
"confirmation_modal.cancel": "Cancel",
"compose_form.spoiler.marked": "El testu nun va anubrise darrera d'una alvertencia",
"compose_form.spoiler.unmarked": "El testu va anubrise",
"compose_form.spoiler_placeholder": "Escribi equí l'avertencia",
"confirmation_modal.cancel": "Encaboxar",
"confirmations.block.confirm": "Block",
"confirmations.block.message": "Are you sure you want to block {name}?",
"confirmations.block.message": "¿De xuru que quies bloquiar a {name}?",
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete.message": "¿De xuru que quies desaniciar esti estáu?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.delete_list.message": "¿De xuru que quies desaniciar dafechu esta llista?",
"confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.mute.message": "¿De xuru que quies silenciar a {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Here is what it will look like:",
"emoji_button.activity": "Activity",
"emoji_button.activity": "Activi",
"emoji_button.custom": "Custom",
"emoji_button.flags": "Flags",
"emoji_button.food": "Food & Drink",
"emoji_button.flags": "Banderes",
"emoji_button.food": "Comída y bébora",
"emoji_button.label": "Insert emoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objects",
"emoji_button.people": "People",
"emoji_button.nature": "Natura",
"emoji_button.not_found": "¡Nun hai fustaxes! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Oxetos",
"emoji_button.people": "Xente",
"emoji_button.recent": "Frequently used",
"emoji_button.search": "Search...",
"emoji_button.search_results": "Search results",
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.blocks": "You haven't blocked any users yet.",
"emoji_button.symbols": "Símbolos",
"emoji_button.travel": "Viaxes y llugares",
"empty_column.blocks": "Entá nun bloquiesti a dengún usuariu.",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
"empty_column.domain_blocks": "There are no hidden domains yet.",
"empty_column.direct": "Entá nun tienes dengún mensaxe direutu. Cuando unvies o recibas dalgún, va apaecer equí",
"empty_column.domain_blocks": "Entá nun hai dominios anubríos.",
"empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
"empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
"empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
"empty_column.follow_requests": "Entá nun tienes denguna solicitú de siguimientu. Cuando recibas una, va amosase equí.",
"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.home.public_timeline": "la llinia temporal pública",
"empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.",
"empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.",
"empty_column.mutes": "You haven't muted any users yet.",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
"empty_column.lists": "Entá nun tienes denguna llista. Cuando crees una, va amosase equí.",
"empty_column.mutes": "Enta nun silenciesti a dengún usuariu.",
"empty_column.notifications": "Entá nun tienes dengún avisu. Interactua con otros p'aniciar la conversación.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
"follow_request.authorize": "Authorize",
"follow_request.reject": "Reject",
"getting_started.developers": "Developers",
"getting_started.documentation": "Documentation",
"getting_started.find_friends": "Find friends from Twitter",
"follow_request.authorize": "Autorizar",
"follow_request.reject": "Refugar",
"getting_started.developers": "Desendolcadores",
"getting_started.documentation": "Documentación",
"getting_started.find_friends": "Alcontrar collacios de Twitter",
"getting_started.heading": "Getting started",
"getting_started.invite": "Invite people",
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
"getting_started.security": "Security",
"getting_started.terms": "Terms of service",
"getting_started.invite": "Convidar xente",
"getting_started.open_source_notice": "Mastodon ye software de códigu abiertu. Pues collaborar o informar de fallos en {github} (GitHub).",
"getting_started.security": "Seguranza",
"getting_started.terms": "Términos del serviciu",
"home.column_settings.basic": "Basic",
"home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies",
"keyboard_shortcuts.back": "to navigate back",
"keyboard_shortcuts.blocked": "to open blocked users list",
"keyboard_shortcuts.back": "pa dir p'atrás",
"keyboard_shortcuts.blocked": "p'abrir la llista d'usuarios bloquiaos",
"keyboard_shortcuts.boost": "to boost",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.direct": "to open direct messages column",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.description": "Descripción",
"keyboard_shortcuts.direct": "p'abrir la columna de los mensaxes direutos",
"keyboard_shortcuts.down": "pa baxar na llista",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.favourites": "to open favourites list",
"keyboard_shortcuts.federated": "to open federated timeline",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.home": "to open home timeline",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.local": "to open local timeline",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.muted": "to open muted users list",
"keyboard_shortcuts.favourites": "p'abrir la llista de favoritos",
"keyboard_shortcuts.federated": "p'abrir la llinia temporal federada",
"keyboard_shortcuts.heading": "Atayos del tecláu",
"keyboard_shortcuts.home": "p'abrir la llinia temporal d'aniciu",
"keyboard_shortcuts.hotkey": "Atayu",
"keyboard_shortcuts.legend": "p'amosar esta lleenda",
"keyboard_shortcuts.local": "p'abrir la llinia temporal llocal",
"keyboard_shortcuts.mention": "pa mentar al autor",
"keyboard_shortcuts.muted": "p'abrir la llista d'usuarios silenciaos",
"keyboard_shortcuts.my_profile": "to open your profile",
"keyboard_shortcuts.notifications": "to open notifications column",
"keyboard_shortcuts.pinned": "to open pinned toots list",
"keyboard_shortcuts.profile": "to open author's profile",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.requests": "to open follow requests list",
"keyboard_shortcuts.notifications": "p'abrir la columna d'avisos",
"keyboard_shortcuts.pinned": "p'abrir la llista de toots fixaos",
"keyboard_shortcuts.profile": "p'abrir el perfil del autor",
"keyboard_shortcuts.reply": "pa responder",
"keyboard_shortcuts.requests": "p'abrir la llista de solicitúes de siguimientu",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.start": "to open \"get started\" column",
"keyboard_shortcuts.start": "p'abrir la columna «entamar»",
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.toot": "p'apenzar un toot nuevu",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"keyboard_shortcuts.up": "pa xubir na llista",
"lightbox.close": "Close",
"lightbox.next": "Next",
"lightbox.next": "Siguiente",
"lightbox.previous": "Previous",
"lists.account.add": "Add to list",
"lists.account.remove": "Remove from list",
@ -180,55 +181,55 @@
"lists.subheading": "Your lists",
"loading_indicator.label": "Loading...",
"media_gallery.toggle_visible": "Toggle visibility",
"missing_indicator.label": "Not found",
"missing_indicator.sublabel": "This resource could not be found",
"missing_indicator.label": "Nun s'alcontró",
"missing_indicator.sublabel": "Esti recursu nun pudo alcontrase",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users",
"navigation_bar.apps": "Aplicaciones móviles",
"navigation_bar.blocks": "Usuarios bloquiaos",
"navigation_bar.community_timeline": "Local timeline",
"navigation_bar.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages",
"navigation_bar.direct": "Mensaxes direutos",
"navigation_bar.discover": "Discover",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Edit profile",
"navigation_bar.favourites": "Favourites",
"navigation_bar.domain_blocks": "Dominios anubríos",
"navigation_bar.edit_profile": "Editar perfil",
"navigation_bar.favourites": "Favoritos",
"navigation_bar.filters": "Muted words",
"navigation_bar.follow_requests": "Follow requests",
"navigation_bar.info": "About this instance",
"navigation_bar.keyboard_shortcuts": "Hotkeys",
"navigation_bar.follow_requests": "Solicitúes de siguimientu",
"navigation_bar.info": "Tocante a esta instancia",
"navigation_bar.keyboard_shortcuts": "Atayos",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Logout",
"navigation_bar.mutes": "Muted users",
"navigation_bar.logout": "Zarrar sesión",
"navigation_bar.mutes": "Usuarios silenciaos",
"navigation_bar.personal": "Personal",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.preferences": "Preferences",
"navigation_bar.public_timeline": "Federated timeline",
"navigation_bar.security": "Security",
"navigation_bar.pins": "Toots fixaos",
"navigation_bar.preferences": "Preferencies",
"navigation_bar.public_timeline": "Llinia temporal federada",
"navigation_bar.security": "Seguranza",
"notification.favourite": "{name} favourited your status",
"notification.follow": "{name} followed you",
"notification.mention": "{name} mentioned you",
"notification.follow": "{name} siguióte",
"notification.mention": "{name} mentóte",
"notification.reblog": "{name} boosted your status",
"notifications.clear": "Clear notifications",
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.clear": "Llimpiar avisos",
"notifications.clear_confirmation": "¿De xuru que quies llimpiar dafechu tolos avisos?",
"notifications.column_settings.alert": "Avisos d'escritoriu",
"notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.follow": "New followers:",
"notifications.column_settings.mention": "Mentions:",
"notifications.column_settings.follow": "Siguidores nuevos:",
"notifications.column_settings.mention": "Menciones:",
"notifications.column_settings.push": "Push notifications",
"notifications.column_settings.push_meta": "This device",
"notifications.column_settings.push_meta": "Esti preséu",
"notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done",
"onboarding.next": "Next",
"notifications.column_settings.show": "Amosar en columna",
"notifications.column_settings.sound": "Reproducir soníu",
"notifications.group": "{count} avisos",
"onboarding.done": "Fecho",
"onboarding.next": "Siguiente",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
"onboarding.page_four.home": "The home timeline shows posts from people you follow.",
"onboarding.page_four.home": "La llinia temporal d'aniciu amuesa artículos de xente a la que sigues.",
"onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
"onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
"onboarding.page_one.federation": "Mastodon ye una rede de sividores independientes xuníos pa facer una rede social grande. Nós llamamos instancies a esos sirvidores.",
"onboarding.page_one.full_handle": "Your full handle",
"onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
"onboarding.page_one.welcome": "Welcome to Mastodon!",
"onboarding.page_one.welcome": "¡Afáyate en Mastodon!",
"onboarding.page_six.admin": "Your instance's admin is {admin}.",
"onboarding.page_six.almost_done": "Almost done...",
"onboarding.page_six.appetoot": "Bon Appetoot!",
@ -236,7 +237,7 @@
"onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
"onboarding.page_six.guidelines": "community guidelines",
"onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
"onboarding.page_six.various_app": "mobile apps",
"onboarding.page_six.various_app": "aplicaciones móviles",
"onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
"onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
"onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
@ -245,7 +246,7 @@
"privacy.direct.long": "Post to mentioned users only",
"privacy.direct.short": "Direct",
"privacy.private.long": "Post to followers only",
"privacy.private.short": "Followers-only",
"privacy.private.short": "Namái siguidores",
"privacy.public.long": "Post to public timelines",
"privacy.public.short": "Public",
"privacy.unlisted.long": "Do not show in public timelines",
@ -254,44 +255,44 @@
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
"relative_time.days": "{number}d",
"relative_time.hours": "{number}h",
"relative_time.just_now": "now",
"relative_time.just_now": "agora",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancel",
"reply_indicator.cancel": "Encaboxar",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.placeholder": "Comentarios adicionales",
"report.submit": "Submit",
"report.target": "Report {target}",
"search.placeholder": "Search",
"search_popout.search_format": "Advanced search format",
"search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.",
"search_popout.tips.hashtag": "hashtag",
"search_popout.tips.status": "status",
"search_popout.tips.hashtag": "etiqueta",
"search_popout.tips.status": "estáu",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_popout.tips.user": "usuariu",
"search_results.accounts": "Xente",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
"status.block": "Bloquiar a @{name}",
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
"status.detailed_status": "Detailed conversation view",
"status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.direct": "Unviar un mensaxe direutu a @{name}",
"status.embed": "Empotrar",
"status.favourite": "Favourite",
"status.filtered": "Filtered",
"status.load_more": "Load more",
"status.load_more": "Cargar más",
"status.media_hidden": "Media hidden",
"status.mention": "Mention @{name}",
"status.more": "More",
"status.mute": "Mute @{name}",
"status.mention": "Mentar a @{name}",
"status.more": "Más",
"status.mute": "Silenciar a @{name}",
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this status",
"status.open": "Espander esti estáu",
"status.pin": "Pin on profile",
"status.pinned": "Pinned toot",
"status.reblog": "Boost",
@ -299,25 +300,25 @@
"status.reblogged_by": "{name} boosted",
"status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.reply": "Responder",
"status.replyAll": "Reply to thread",
"status.report": "Report @{name}",
"status.sensitive_toggle": "Click to view",
"status.sensitive_warning": "Sensitive content",
"status.share": "Share",
"status.show_less": "Show less",
"status.show_less": "Amosar menos",
"status.show_less_all": "Show less for all",
"status.show_more": "Show more",
"status.show_more": "Amosar más",
"status.show_more_all": "Show more for all",
"status.unmute_conversation": "Unmute conversation",
"status.unpin": "Unpin from profile",
"tabs_bar.federated_timeline": "Federated",
"tabs_bar.home": "Home",
"tabs_bar.home": "Aniciu",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notifications",
"tabs_bar.notifications": "Avisos",
"tabs_bar.search": "Search",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"ui.beforeunload": "El borrador va perdese si coles de Mastodon.",
"upload_area.title": "Drag & drop to upload",
"upload_button.label": "Add media",
"upload_form.description": "Describe for the visually impaired",

View File

@ -15,6 +15,7 @@
"account.follows.empty": "This user doesn't follow anyone yet.",
"account.follows_you": "Твой последовател",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Media",
"account.mention": "Споменаване",
"account.moved_to": "{name} has moved to:",

View File

@ -15,6 +15,7 @@
"account.follows.empty": "Aquest usuari encara no segueix a ningú.",
"account.follows_you": "Et segueix",
"account.hide_reblogs": "Amaga els impulsos de @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Media",
"account.mention": "Esmentar @{name}",
"account.moved_to": "{name} s'ha mogut a:",

View File

@ -15,6 +15,7 @@
"account.follows.empty": "St'utilizatore ùn seguita nisunu.",
"account.follows_you": "Vi seguita",
"account.hide_reblogs": "Piattà spartere da @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Media",
"account.mention": "Mintuvà @{name}",
"account.moved_to": "{name} hè partutu nant'à:",

View File

@ -15,6 +15,7 @@
"account.follows.empty": "Tento uživatel ještě nikoho nesleduje.",
"account.follows_you": "Sleduje vás",
"account.hide_reblogs": "Skrýt boosty od uživatele @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Média",
"account.mention": "Zmínit uživatele @{name}",
"account.moved_to": "{name} se přesunul/a na:",

View File

@ -1,121 +1,122 @@
{
"account.badges.bot": "Bot",
"account.block": "Block @{name}",
"account.block_domain": "Hide everything from {domain}",
"account.blocked": "Blocked",
"account.direct": "Direct message @{name}",
"account.disclaimer_full": "Information below may reflect the user's profile incompletely.",
"account.block": "Blociwch @{name}",
"account.block_domain": "Cuddiwch bopeth rhag {domain}",
"account.blocked": "Blociwyd",
"account.direct": "Neges breifat @{name}",
"account.disclaimer_full": "Gall y wybodaeth isod adlewyrchu darlun anghyflawn o broffil defnyddiwr.",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "Edit profile",
"account.edit_profile": "Golygu proffil",
"account.endorse": "Feature on profile",
"account.follow": "Follow",
"account.followers": "Followers",
"account.followers.empty": "No one follows this user yet.",
"account.follows": "Follows",
"account.follows.empty": "This user doesn't follow anyone yet.",
"account.follows_you": "Follows you",
"account.follow": "Dilyn",
"account.followers": "Dilynwyr",
"account.followers.empty": "Nid oes neb yn dilyn y defnyddiwr hwn eto.",
"account.follows": "Yn dilyn",
"account.follows.empty": "Nid yw'r defnyddiwr hwn yn dilyn unrhyw un eto.",
"account.follows_you": "Yn eich dilyn chi",
"account.hide_reblogs": "Hide boosts from @{name}",
"account.media": "Media",
"account.mention": "Mention @{name}",
"account.moved_to": "{name} has moved to:",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Cyfryngau",
"account.mention": "Crybwyll @{name}",
"account.moved_to": "Mae @{name} wedi symud i:",
"account.mute": "Mute @{name}",
"account.mute_notifications": "Mute notifications from @{name}",
"account.muted": "Muted",
"account.posts": "Toots",
"account.muted": "Distewyd",
"account.posts": "Tŵtiau",
"account.posts_with_replies": "Toots and replies",
"account.report": "Report @{name}",
"account.report": "Adroddwch @{name}",
"account.requested": "Awaiting approval. Click to cancel follow request",
"account.share": "Share @{name}'s profile",
"account.share": "Rhannwch broffil @{name}",
"account.show_reblogs": "Show boosts from @{name}",
"account.unblock": "Unblock @{name}",
"account.unblock_domain": "Unhide {domain}",
"account.unblock": "Dadflociwch @{name}",
"account.unblock_domain": "Dadguddiwch {domain}",
"account.unendorse": "Don't feature on profile",
"account.unfollow": "Unfollow",
"account.unfollow": "Daddilynwch",
"account.unmute": "Unmute @{name}",
"account.unmute_notifications": "Unmute notifications from @{name}",
"account.view_full_profile": "View full profile",
"alert.unexpected.message": "An unexpected error occurred.",
"alert.unexpected.title": "Oops!",
"alert.unexpected.message": "Digwyddodd gwall annisgwyl.",
"alert.unexpected.title": "Wps!",
"boost_modal.combo": "You can press {combo} to skip this next time",
"bundle_column_error.body": "Something went wrong while loading this component.",
"bundle_column_error.retry": "Try again",
"bundle_column_error.title": "Network error",
"bundle_column_error.body": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
"bundle_column_error.retry": "Ceisiwch eto",
"bundle_column_error.title": "Gwall rhwydwaith",
"bundle_modal_error.close": "Close",
"bundle_modal_error.message": "Something went wrong while loading this component.",
"bundle_modal_error.retry": "Try again",
"column.blocks": "Blocked users",
"column.community": "Local timeline",
"column.direct": "Direct messages",
"column.domain_blocks": "Hidden domains",
"column.favourites": "Favourites",
"column.follow_requests": "Follow requests",
"bundle_modal_error.message": "Aeth rhywbeth o'i le tra'n llwytho'r elfen hon.",
"bundle_modal_error.retry": "Ceiswich eto",
"column.blocks": "Defnyddwyr a flociwyd",
"column.community": "Llinell amser lleol",
"column.direct": "Negeseuon preifat",
"column.domain_blocks": "Parthau cuddiedig",
"column.favourites": "Ffefrynnau",
"column.follow_requests": "Ceisiadau dilyn",
"column.home": "Hafan",
"column.lists": "Lists",
"column.mutes": "Muted users",
"column.notifications": "Notifications",
"column.lists": "Rhestrau",
"column.mutes": "Defnyddwyr a ddistewyd",
"column.notifications": "Hysbysiadau",
"column.pins": "Pinned toot",
"column.public": "Federated timeline",
"column_back_button.label": "Nôl",
"column_header.hide_settings": "Hide settings",
"column_header.moveLeft_settings": "Move column to the left",
"column_header.moveRight_settings": "Move column to the right",
"column_header.pin": "Pin",
"column_header.show_settings": "Show settings",
"column_header.unpin": "Unpin",
"column_subheading.settings": "Settings",
"community.column_settings.media_only": "Media Only",
"compose_form.direct_message_warning": "This toot will only be sent to all the mentioned users.",
"compose_form.direct_message_warning_learn_more": "Learn more",
"compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.",
"compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.",
"compose_form.lock_disclaimer.lock": "locked",
"compose_form.placeholder": "What is on your mind?",
"compose_form.publish": "Toot",
"column_header.moveLeft_settings": "Symudwch y golofn i'r chwith",
"column_header.moveRight_settings": "Symudwch y golofn i'r dde",
"column_header.pin": "Piniwch",
"column_header.show_settings": "Dangos gosodiadau",
"column_header.unpin": "Dadbiniwch",
"column_subheading.settings": "Gosodiadau",
"community.column_settings.media_only": "Cyfryngau yn unig",
"compose_form.direct_message_warning": "Mi fydd y tŵt hwn ond yn cael ei anfon at y defnyddwyr sy'n cael eu crybwyll.",
"compose_form.direct_message_warning_learn_more": "Dysgwch fwy",
"compose_form.hashtag_warning": "Ni fydd y tŵt hwn wedi ei restru o dan unrhyw hashnod gan ei fod heb ei restru. Dim ond tŵtiau cyhoeddus gellid chwilota amdanynt drwy hashnod.",
"compose_form.lock_disclaimer": "Nid yw eich cyfri wedi'i {locked}. Gall unrhyw un eich dilyn i weld eich POSTS dilynwyr-yn-unig.",
"compose_form.lock_disclaimer.lock": "wedi ei gloi",
"compose_form.placeholder": "Be syd ar eich meddwl?",
"compose_form.publish": "Tŵt",
"compose_form.publish_loud": "{publish}!",
"compose_form.sensitive.marked": "Media is marked as sensitive",
"compose_form.sensitive.unmarked": "Media is not marked as sensitive",
"compose_form.spoiler.marked": "Text is hidden behind warning",
"compose_form.spoiler.unmarked": "Text is not hidden",
"compose_form.spoiler_placeholder": "Write your warning here",
"compose_form.spoiler.marked": "Testun wedi ei guddio gan rybudd",
"compose_form.spoiler.unmarked": "Nid yw'r testun wedi ei guddio",
"compose_form.spoiler_placeholder": "Ysgrifenwch eich rhybudd yma",
"confirmation_modal.cancel": "Cancel",
"confirmations.block.confirm": "Block",
"confirmations.block.message": "Are you sure you want to block {name}?",
"confirmations.delete.confirm": "Delete",
"confirmations.delete.message": "Are you sure you want to delete this status?",
"confirmations.delete_list.confirm": "Delete",
"confirmations.delete_list.message": "Are you sure you want to permanently delete this list?",
"confirmations.block.confirm": "Blociwch",
"confirmations.block.message": "Ydych chi'n sicr eich bod eisiau blocio {name}?",
"confirmations.delete.confirm": "Dileu",
"confirmations.delete.message": "Ydych chi'n sicr eich bod eisiau dileu y statws hwn?",
"confirmations.delete_list.confirm": "Dileu",
"confirmations.delete_list.message": "Ydych chi'n sicr eich bod eisiau dileu y rhestr hwn am byth?",
"confirmations.domain_block.confirm": "Hide entire domain",
"confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.",
"confirmations.mute.confirm": "Mute",
"confirmations.mute.message": "Are you sure you want to mute {name}?",
"confirmations.mute.message": "Ydych chi'n sicr eich bod am ddistewi {name}?",
"confirmations.redraft.confirm": "Delete & redraft",
"confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.",
"confirmations.unfollow.confirm": "Unfollow",
"confirmations.unfollow.message": "Are you sure you want to unfollow {name}?",
"confirmations.unfollow.confirm": "Dad-ddilynwch",
"confirmations.unfollow.message": "Ydych chi'n sicr eich bod am ddad-ddilyn {name}?",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Here is what it will look like:",
"emoji_button.activity": "Activity",
"embed.preview": "Dyma sut olwg fydd arno:",
"emoji_button.activity": "Gweithgarwch",
"emoji_button.custom": "Custom",
"emoji_button.flags": "Flags",
"emoji_button.food": "Food & Drink",
"emoji_button.label": "Insert emoji",
"emoji_button.nature": "Nature",
"emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Objects",
"emoji_button.people": "People",
"emoji_button.recent": "Frequently used",
"emoji_button.search": "Search...",
"emoji_button.search_results": "Search results",
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.blocks": "You haven't blocked any users yet.",
"emoji_button.flags": "Baneri",
"emoji_button.food": "Bwyd a Diod",
"emoji_button.label": "Mewnosodwch emoji",
"emoji_button.nature": "Natur",
"emoji_button.not_found": "Dim emojos!! (╯°□°)╯︵ ┻━┻",
"emoji_button.objects": "Gwrthrychau",
"emoji_button.people": "Pobl",
"emoji_button.recent": "Defnyddir yn aml",
"emoji_button.search": "Chwilio...",
"emoji_button.search_results": "Canlyniadau chwilio",
"emoji_button.symbols": "Symbolau",
"emoji_button.travel": "Teithio & Llefydd",
"empty_column.blocks": "Nid ydych wedi blocio unrhyw ddefnyddwyr eto.",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.",
"empty_column.domain_blocks": "There are no hidden domains yet.",
"empty_column.favourited_statuses": "You don't have any favourite toots yet. When you favourite one, it will show up here.",
"empty_column.favourites": "No one has favourited this toot yet. When someone does, they will show up here.",
"empty_column.direct": "Nid oes gennych unrhyw negeseuon preifat eto. Pan y byddwch yn anfon neu derbyn un, mi fydd yn ymddangos yma.",
"empty_column.domain_blocks": "Nid oes yna unrhyw barthau cuddiedig eto.",
"empty_column.favourited_statuses": "Nid oes gennych unrhyw hoff dwtiau eto. Pan y byddwch yn hoffi un, mi fydd yn ymddangos yma.",
"empty_column.favourites": "Nid oes neb wedi hoffi'r tŵt yma eto. Pan bydd rhywun yn ei hoffi, mi fyddent yn ymddangos yma.",
"empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.",
"empty_column.hashtag": "There is nothing in this hashtag yet.",
"empty_column.hashtag": "Nid oes dim ar yr hashnod hwn eto.",
"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.",
@ -123,120 +124,120 @@
"empty_column.mutes": "You haven't muted any users yet.",
"empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
"empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up",
"follow_request.authorize": "Authorize",
"follow_request.reject": "Reject",
"getting_started.developers": "Developers",
"getting_started.documentation": "Documentation",
"getting_started.find_friends": "Find friends from Twitter",
"getting_started.heading": "Getting started",
"getting_started.invite": "Invite people",
"follow_request.authorize": "Caniatau",
"follow_request.reject": "Gwrthod",
"getting_started.developers": "Datblygwyr",
"getting_started.documentation": "Dogfennaeth",
"getting_started.find_friends": "Canfod ffrindiau o Twitter",
"getting_started.heading": "Dechrau",
"getting_started.invite": "Gwahoddwch bobl",
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.",
"getting_started.security": "Security",
"getting_started.security": "Diogelwch",
"getting_started.terms": "Terms of service",
"home.column_settings.basic": "Basic",
"home.column_settings.basic": "Syml",
"home.column_settings.show_reblogs": "Show boosts",
"home.column_settings.show_replies": "Show replies",
"home.column_settings.show_replies": "Dangoswch ymatebion",
"keyboard_shortcuts.back": "to navigate back",
"keyboard_shortcuts.blocked": "to open blocked users list",
"keyboard_shortcuts.boost": "to boost",
"keyboard_shortcuts.column": "to focus a status in one of the columns",
"keyboard_shortcuts.compose": "to focus the compose textarea",
"keyboard_shortcuts.description": "Description",
"keyboard_shortcuts.direct": "to open direct messages column",
"keyboard_shortcuts.down": "to move down in the list",
"keyboard_shortcuts.enter": "to open status",
"keyboard_shortcuts.favourite": "to favourite",
"keyboard_shortcuts.favourites": "to open favourites list",
"keyboard_shortcuts.description": "Disgrifiad",
"keyboard_shortcuts.direct": "i agor colofn negeseuon preifat",
"keyboard_shortcuts.down": "i symud lawr yn y rhestr",
"keyboard_shortcuts.enter": "i agor statws",
"keyboard_shortcuts.favourite": "i hoffi",
"keyboard_shortcuts.favourites": "i agor rhestr hoffi",
"keyboard_shortcuts.federated": "to open federated timeline",
"keyboard_shortcuts.heading": "Keyboard Shortcuts",
"keyboard_shortcuts.home": "to open home timeline",
"keyboard_shortcuts.hotkey": "Hotkey",
"keyboard_shortcuts.legend": "to display this legend",
"keyboard_shortcuts.local": "to open local timeline",
"keyboard_shortcuts.mention": "to mention author",
"keyboard_shortcuts.mention": "i grybwyll yr awdur",
"keyboard_shortcuts.muted": "to open muted users list",
"keyboard_shortcuts.my_profile": "to open your profile",
"keyboard_shortcuts.notifications": "to open notifications column",
"keyboard_shortcuts.my_profile": "i agor eich proffil",
"keyboard_shortcuts.notifications": "i agor colofn hysbysiadau",
"keyboard_shortcuts.pinned": "to open pinned toots list",
"keyboard_shortcuts.profile": "to open author's profile",
"keyboard_shortcuts.reply": "to reply",
"keyboard_shortcuts.profile": "i agor proffil yr awdur",
"keyboard_shortcuts.reply": "i ateb",
"keyboard_shortcuts.requests": "to open follow requests list",
"keyboard_shortcuts.search": "to focus search",
"keyboard_shortcuts.start": "to open \"get started\" column",
"keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW",
"keyboard_shortcuts.toot": "to start a brand new toot",
"keyboard_shortcuts.toot": "i ddechrau tŵt newydd sbon",
"keyboard_shortcuts.unfocus": "to un-focus compose textarea/search",
"keyboard_shortcuts.up": "to move up in the list",
"lightbox.close": "Close",
"lightbox.next": "Next",
"lightbox.close": "Cau",
"lightbox.next": "Nesaf",
"lightbox.previous": "Previous",
"lists.account.add": "Add to list",
"lists.account.add": "Ychwanegwch at restr",
"lists.account.remove": "Remove from list",
"lists.delete": "Delete list",
"lists.edit": "Edit list",
"lists.new.create": "Add list",
"lists.delete": "Dileu rhestr",
"lists.edit": "Golygwch restr",
"lists.new.create": "Ychwanegwch restr",
"lists.new.title_placeholder": "New list title",
"lists.search": "Search among people you follow",
"lists.subheading": "Your lists",
"loading_indicator.label": "Loading...",
"lists.subheading": "Eich rhestrau",
"loading_indicator.label": "Llwytho...",
"media_gallery.toggle_visible": "Toggle visibility",
"missing_indicator.label": "Not found",
"missing_indicator.sublabel": "This resource could not be found",
"mute_modal.hide_notifications": "Hide notifications from this user?",
"navigation_bar.apps": "Mobile apps",
"navigation_bar.blocks": "Blocked users",
"missing_indicator.label": "Heb ei ganfod",
"missing_indicator.sublabel": "Ni ellid canfod yr adnodd hwn",
"mute_modal.hide_notifications": "Cuddiwch hysbysiadau rhag y defnyddiwr hwn?",
"navigation_bar.apps": "Apiau symudol",
"navigation_bar.blocks": "Defnyddwyr wedi eu blocio",
"navigation_bar.community_timeline": "Local timeline",
"navigation_bar.compose": "Compose new toot",
"navigation_bar.direct": "Direct messages",
"navigation_bar.discover": "Discover",
"navigation_bar.domain_blocks": "Hidden domains",
"navigation_bar.edit_profile": "Edit profile",
"navigation_bar.favourites": "Favourites",
"navigation_bar.compose": "Cyfansoddwch dŵt newydd",
"navigation_bar.direct": "Negeseuon preifat",
"navigation_bar.discover": "Darganfyddwch",
"navigation_bar.domain_blocks": "Parthau cuddiedig",
"navigation_bar.edit_profile": "Golygu proffil",
"navigation_bar.favourites": "Ffefrynnau",
"navigation_bar.filters": "Muted words",
"navigation_bar.follow_requests": "Follow requests",
"navigation_bar.follow_requests": "Ceisiadau dilyn",
"navigation_bar.info": "About this instance",
"navigation_bar.keyboard_shortcuts": "Hotkeys",
"navigation_bar.lists": "Lists",
"navigation_bar.logout": "Logout",
"navigation_bar.lists": "Rhestrau",
"navigation_bar.logout": "Allgofnodi",
"navigation_bar.mutes": "Muted users",
"navigation_bar.personal": "Personal",
"navigation_bar.pins": "Pinned toots",
"navigation_bar.preferences": "Preferences",
"navigation_bar.personal": "Personol",
"navigation_bar.pins": "Tŵtiau wedi eu pinio",
"navigation_bar.preferences": "Dewisiadau",
"navigation_bar.public_timeline": "Federated timeline",
"navigation_bar.security": "Security",
"notification.favourite": "{name} favourited your status",
"notification.follow": "{name} followed you",
"navigation_bar.security": "Diogelwch",
"notification.favourite": "hoffodd {name} eich statws",
"notification.follow": "dilynodd {name} chi",
"notification.mention": "{name} mentioned you",
"notification.reblog": "{name} boosted your status",
"notifications.clear": "Clear notifications",
"notifications.clear": "Clirio hysbysiadau",
"notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
"notifications.column_settings.alert": "Desktop notifications",
"notifications.column_settings.favourite": "Favourites:",
"notifications.column_settings.follow": "New followers:",
"notifications.column_settings.favourite": "Ffefrynnau:",
"notifications.column_settings.follow": "Dilynwyr newydd:",
"notifications.column_settings.mention": "Mentions:",
"notifications.column_settings.push": "Push notifications",
"notifications.column_settings.push_meta": "This device",
"notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"notifications.column_settings.sound": "Chwarae sain",
"notifications.group": "{count} o hysbysiadau",
"onboarding.done": "Done",
"onboarding.next": "Next",
"onboarding.next": "Nesaf",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",
"onboarding.page_four.home": "The home timeline shows posts from people you follow.",
"onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.",
"onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.",
"onboarding.page_one.full_handle": "Your full handle",
"onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.",
"onboarding.page_one.welcome": "Welcome to Mastodon!",
"onboarding.page_one.welcome": "Croeso i Mastodon!",
"onboarding.page_six.admin": "Your instance's admin is {admin}.",
"onboarding.page_six.almost_done": "Almost done...",
"onboarding.page_six.appetoot": "Bon Appetoot!",
"onboarding.page_six.appetoot": "Bon Apetŵt!",
"onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.",
"onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.",
"onboarding.page_six.guidelines": "community guidelines",
"onboarding.page_six.guidelines": "canllawiau cymunedol",
"onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!",
"onboarding.page_six.various_app": "mobile apps",
"onboarding.page_six.various_app": "apiau symudol",
"onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.",
"onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.",
"onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.",
@ -245,50 +246,50 @@
"privacy.direct.long": "Post to mentioned users only",
"privacy.direct.short": "Direct",
"privacy.private.long": "Post to followers only",
"privacy.private.short": "Followers-only",
"privacy.private.short": "Dilynwyr-yn-unig",
"privacy.public.long": "Post to public timelines",
"privacy.public.short": "Public",
"privacy.public.short": "Cyhoeddus",
"privacy.unlisted.long": "Do not show in public timelines",
"privacy.unlisted.short": "Unlisted",
"regeneration_indicator.label": "Loading…",
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
"privacy.unlisted.short": "Heb ei restru",
"regeneration_indicator.label": "Llwytho…",
"regeneration_indicator.sublabel": "Mae eich ffrwd cartref yn cael ei baratoi!",
"relative_time.days": "{number}d",
"relative_time.hours": "{number}h",
"relative_time.just_now": "now",
"relative_time.just_now": "nawr",
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"reply_indicator.cancel": "Cancel",
"reply_indicator.cancel": "Canslo",
"report.forward": "Forward to {target}",
"report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?",
"report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"report.placeholder": "Additional comments",
"report.placeholder": "Sylwadau ychwanegol",
"report.submit": "Submit",
"report.target": "Report {target}",
"search.placeholder": "Search",
"search.placeholder": "Chwilio",
"search_popout.search_format": "Advanced search format",
"search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.",
"search_popout.tips.hashtag": "hashtag",
"search_popout.tips.status": "status",
"search_popout.tips.hashtag": "hashnod",
"search_popout.tips.status": "statws",
"search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags",
"search_popout.tips.user": "user",
"search_results.accounts": "People",
"search_results.hashtags": "Hashtags",
"search_results.statuses": "Toots",
"search_popout.tips.user": "defnyddiwr",
"search_results.accounts": "Pobl",
"search_results.hashtags": "Hanshnodau",
"search_results.statuses": "Twtiau",
"search_results.total": "{count, number} {count, plural, one {result} other {results}}",
"standalone.public_title": "A look inside...",
"status.block": "Block @{name}",
"status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted",
"status.delete": "Delete",
"status.delete": "Dileu",
"status.detailed_status": "Detailed conversation view",
"status.direct": "Direct message @{name}",
"status.embed": "Embed",
"status.direct": "Neges breifat @{name}",
"status.embed": "Plannu",
"status.favourite": "Favourite",
"status.filtered": "Filtered",
"status.load_more": "Load more",
"status.load_more": "Llwythwch mwy",
"status.media_hidden": "Media hidden",
"status.mention": "Mention @{name}",
"status.more": "More",
"status.more": "Mwy",
"status.mute": "Mute @{name}",
"status.mute_conversation": "Mute conversation",
"status.open": "Expand this status",
@ -299,23 +300,23 @@
"status.reblogged_by": "{name} boosted",
"status.reblogs.empty": "No one has boosted this toot yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft",
"status.reply": "Reply",
"status.replyAll": "Reply to thread",
"status.reply": "Ateb",
"status.replyAll": "Ateb i edefyn",
"status.report": "Report @{name}",
"status.sensitive_toggle": "Click to view",
"status.sensitive_warning": "Sensitive content",
"status.share": "Share",
"status.show_less": "Show less",
"status.show_less_all": "Show less for all",
"status.show_more": "Show more",
"status.sensitive_warning": "Cynnwys sensitif",
"status.share": "Rhannwch",
"status.show_less": "Dangoswch lai",
"status.show_less_all": "Dangoswch lai i bawb",
"status.show_more": "Dangoswch fwy",
"status.show_more_all": "Show more for all",
"status.unmute_conversation": "Unmute conversation",
"status.unpin": "Unpin from profile",
"tabs_bar.federated_timeline": "Federated",
"tabs_bar.home": "Home",
"tabs_bar.local_timeline": "Local",
"tabs_bar.notifications": "Notifications",
"tabs_bar.search": "Search",
"tabs_bar.home": "Hafan",
"tabs_bar.local_timeline": "Lleol",
"tabs_bar.notifications": "Hysbysiadau",
"tabs_bar.search": "Chwilio",
"trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking",
"ui.beforeunload": "Your draft will be lost if you leave Mastodon.",
"upload_area.title": "Drag & drop to upload",
@ -323,7 +324,7 @@
"upload_form.description": "Describe for the visually impaired",
"upload_form.focus": "Crop",
"upload_form.undo": "Delete",
"upload_progress.label": "Uploading...",
"upload_progress.label": "Uwchlwytho...",
"video.close": "Close video",
"video.exit_fullscreen": "Exit full screen",
"video.expand": "Expand video",
@ -331,6 +332,6 @@
"video.hide": "Hide video",
"video.mute": "Mute sound",
"video.pause": "Pause",
"video.play": "Play",
"video.play": "Chwarae",
"video.unmute": "Unmute sound"
}

View File

@ -15,6 +15,7 @@
"account.follows.empty": "Denne bruger følger endnu ikke nogen.",
"account.follows_you": "Følger dig",
"account.hide_reblogs": "Skjul fremhævelserne fra @{name}",
"account.link_verified_on": "Ownership of this link was checked on {date}",
"account.media": "Medie",
"account.mention": "Nævn @{name}",
"account.moved_to": "{name} er flyttet til:",
@ -200,7 +201,7 @@
"navigation_bar.logout": "Logud",
"navigation_bar.mutes": "Dæmpede brugere",
"navigation_bar.personal": "Personligt",
"navigation_bar.pins": "Fastgjorte toots",
"navigation_bar.pins": "Fastgjorte trut",
"navigation_bar.preferences": "Præferencer",
"navigation_bar.public_timeline": "Fælles tidslinje",
"navigation_bar.security": "Sikkerhed",
@ -273,7 +274,7 @@
"search_popout.tips.user": "bruger",
"search_results.accounts": "Folk",
"search_results.hashtags": "Emnetags",
"search_results.statuses": "Toote",
"search_results.statuses": "Trut",
"search_results.total": "{count, number} {count, plural, et {result} andre {results}}",
"standalone.public_title": "Et kig indenfor...",
"status.block": "Bloker @{name}",

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