From c2bee07dbc12c799f412a39a4d5499264baac81e Mon Sep 17 00:00:00 2001
From: Anna e só
Date: Sun, 10 Sep 2017 20:40:29 -0300
Subject: l10n: Full PT-BR translation (#4882)
* devise.pt-BR.yml now fully translated
* pt-BR.json now fully translated
* pt-BR.yml partially translated; 46 lines left
* pt-BR.yml now fully translated
* simple_form.pt-BR.yml fully translated
* doorkeeper.pt-BR.yml now fully translated
* E-mail instructions on app/views/user_mailer added and fully translated
* PT-BR translation for #4871
* Deleted an unwanted caracter on pt-BR.yml
* Fixing typos on pt-BR.yml
* Added translation for Pinned toots tab on pt-BR.json
* Added missing translation for navigation_bar.pins
---
.../user_mailer/confirmation_instructions.pt-BR.html.erb | 12 ++++++++++++
.../user_mailer/confirmation_instructions.pt-BR.text.erb | 12 ++++++++++++
app/views/user_mailer/password_change.pt-BR.html.erb | 3 +++
app/views/user_mailer/password_change.pt-BR.text.erb | 3 +++
.../user_mailer/reset_password_instructions.pt-BR.html.erb | 8 ++++++++
.../user_mailer/reset_password_instructions.pt-BR.text.erb | 8 ++++++++
6 files changed, 46 insertions(+)
create mode 100644 app/views/user_mailer/confirmation_instructions.pt-BR.html.erb
create mode 100644 app/views/user_mailer/confirmation_instructions.pt-BR.text.erb
create mode 100644 app/views/user_mailer/password_change.pt-BR.html.erb
create mode 100644 app/views/user_mailer/password_change.pt-BR.text.erb
create mode 100644 app/views/user_mailer/reset_password_instructions.pt-BR.html.erb
create mode 100644 app/views/user_mailer/reset_password_instructions.pt-BR.text.erb
(limited to 'app/views')
diff --git a/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb b/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb
new file mode 100644
index 000000000..80edcfda7
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.pt-BR.html.erb
@@ -0,0 +1,12 @@
+
Boas vindas, <%= @resource.email %>!
+
+
Você acabou de criar uma conta no <%= @instance %>.
+
+
Para confirmar o seu cadastro, por favor clique no link a seguir:
+<%= link_to 'Confirmar cadastro', confirmation_url(@resource, confirmation_token: @token) %>
+
+
Por favor, leia também os nossos <%= link_to 'termos de serviços', terms_url %>.
+
+
Atenciosamente,
+
+
A equipe do <%= @instance %>
diff --git a/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb b/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb
new file mode 100644
index 000000000..95efb3436
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.pt-BR.text.erb
@@ -0,0 +1,12 @@
+Boas vindas, <%= @resource.email %>!
+
+Você acabou de criar uma conta no <%= @instance %>.
+
+Para confirmar o seu cadastro, por favor clique no link a seguir:
+<%= confirmation_url(@resource, confirmation_token: @token) %>
+
+Por favor, leia também os nossos termos e condições de uso <%= terms_url %>
+
+Atenciosamente,
+
+A equipe do <%= @instance %>
diff --git a/app/views/user_mailer/password_change.pt-BR.html.erb b/app/views/user_mailer/password_change.pt-BR.html.erb
new file mode 100644
index 000000000..5f707ba09
--- /dev/null
+++ b/app/views/user_mailer/password_change.pt-BR.html.erb
@@ -0,0 +1,3 @@
+
Olá, <%= @resource.email %>!
+
+
Estamos te contatando para te notificar que a senha senha no <%= @instance %> foi modificada.
diff --git a/app/views/user_mailer/password_change.pt-BR.text.erb b/app/views/user_mailer/password_change.pt-BR.text.erb
new file mode 100644
index 000000000..d8b76648c
--- /dev/null
+++ b/app/views/user_mailer/password_change.pt-BR.text.erb
@@ -0,0 +1,3 @@
+Olá, <%= @resource.email %>!
+
+Estamos te contatando para te notificar que a senha senha no <%= @instance %> foi modificada.
diff --git a/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb b/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb
new file mode 100644
index 000000000..940438b7c
--- /dev/null
+++ b/app/views/user_mailer/reset_password_instructions.pt-BR.html.erb
@@ -0,0 +1,8 @@
+
Olá, <%= @resource.email %>!
+
+
Alguém solicitou um link para mudar a sua senha no <%= @instance %>. Você pode fazer isso através do link abaixo:
+
+
<%= link_to 'Mudar a minha senha', edit_password_url(@resource, reset_password_token: @token) %>
+
+
Se você não solicitou isso, por favor ignore este e-mail.
+
A senha senha não será modificada até que você acesse o link acima e crie uma nova.
diff --git a/app/views/user_mailer/reset_password_instructions.zh-cn.text.erb b/app/views/user_mailer/reset_password_instructions.zh-cn.text.erb
index 574a0bb2e..7df590f78 100644
--- a/app/views/user_mailer/reset_password_instructions.zh-cn.text.erb
+++ b/app/views/user_mailer/reset_password_instructions.zh-cn.text.erb
@@ -1,6 +1,6 @@
<%= @resource.email %> ,嗨呀!!
-有人(但愿是你)请求更改你Mastodon账户的密码。如果是你的话,请点击下面的链接:
+有人(但愿是你)请求更改你Mastodon帐户的密码。如果是你的话,请点击下面的链接:
<%= link_to '更改密码', edit_password_url(@resource, reset_password_token: @token) %>
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
index 95c24d0bc..44d0f3803 100644
--- a/config/locales/zh-CN.yml
+++ b/config/locales/zh-CN.yml
@@ -65,9 +65,9 @@ zh-CN:
salmon_url: Salmon 反馈 URL
search: 搜索
show:
- created_reports: 这个账户创建的报告
+ created_reports: 这个帐户创建的报告
report: 报告
- targeted_reports: 关于这个账户的报告
+ targeted_reports: 关于这个帐户的报告
silence: 静音
statuses: 嘟文
title: 用户
@@ -82,7 +82,7 @@ zh-CN:
domain: 域名阻隔
new:
create: 添加域名阻隔
- hint: "「域名阻隔」不会隔绝该域名用户的嘟账户入本站数据库,但会嘟文抵达后,自动套用特定的审批操作。"
+ hint: "「域名阻隔」不会隔绝该域名用户的嘟帐户入本站数据库,但会嘟文抵达后,自动套用特定的审批操作。"
severity:
desc_html: "「自动静音」令该域名用户的嘟文,设为只对关注者显示,没有关注的人会看不到。 「自动除名」会自动将该域名用户的嘟文、媒体文件、个人资料从本服务器实例删除。"
silence: 自动静音
@@ -96,11 +96,11 @@ zh-CN:
severity: 阻隔程度
show:
affected_accounts:
- one: 数据库中有1个账户受影响
- other: 数据库中有%{count}个账户受影响
+ one: 数据库中有1个帐户受影响
+ other: 数据库中有%{count}个帐户受影响
retroactive:
- silence: 对此域名的所有账户取消静音
- suspend: 对此域名的所有账户取消除名
+ silence: 对此域名的所有帐户取消静音
+ suspend: 对此域名的所有帐户取消除名
title: 撤销 %{domain} 的域名阻隔
undo: 撤销
title: 域名阻隔
@@ -209,12 +209,12 @@ zh-CN:
domain: 域名
explanation_html: 想要保护你的嘟文的话,请慎重考虑关注你的人。你的受保护的嘟文会发送到有你的关注者的所有实例上。你也许想要复查一下关注者列表来移除那些你无法信任的关注者。
followers_count: 关注者数量
- lock_link: 保护你的账户
+ lock_link: 保护你的帐户
purge: 从关注者中移除
success: 从 %{count} 个域名中移除了关注者。
true_privacy_html: "真正的隐私只能靠端到端加密来实现!"
unlocked_warning_html: 任何人都可以关注你然后查看被保护的嘟文, %{lock_link} 可以复核和拒绝关注请求。
- unlocked_warning_title: 你的账户没被保护
+ unlocked_warning_title: 你的帐户没被保护
generic:
changes_saved_msg: 更改已被保存。
powered_by: 基于 %{link} 构建
@@ -231,7 +231,7 @@ zh-CN:
muting: 静音名单
upload: 上载
landing_strip_html: "%{name} 是一个在 %{link_to_root_path} 的用户。只要你是象毛世界里(Mastodon、GNU social)任一服务器实例的用户,便可以跨站关注此站用户并与其沟通。"
- landing_strip_signup_html: 如果你没有这类账户,欢迎在此处登记。
+ landing_strip_signup_html: 如果你没有这类帐户,欢迎在此处登记。
media_attachments:
validations:
images_and_video: 无法添加视频到一个已经包含图片的嘟文中
@@ -247,8 +247,8 @@ zh-CN:
one: "你有一个新通知 \U0001F418"
other: "%{count} 个通知太多,赶快去看看 \U0001F418"
favourite:
- body: "%{name} 赞你"
- subject: "%{name} 对你点赞"
+ body: "%{name} 收藏了你"
+ subject: "%{name} 给你点了收藏"
follow:
body: "%{name} 关注了你"
subject: "%{name} 关注了你"
@@ -278,7 +278,7 @@ zh-CN:
truncate: "……"
remote_follow:
acct: 请输入你的︰用户名称@实例域名
- missing_resource: 无法找到您的账户转接网址
+ missing_resource: 无法找到您的帐户转接网址
proceed: 下一步
prompt: 你正准备关注︰
settings:
@@ -317,10 +317,10 @@ zh-CN:
enabled_success: 已成功启用两步认证
generate_recovery_codes: 生成恢复代码
instructions_html: "请用你手机的认证器应用(如 Google Authenticator、Authy),扫描这里的 QR 二维码。在两步认证启用后,你登录时将需要使用此应用程序产生的认证码。"
- lost_recovery_codes: 如果你丢了手机,你可以用恢复代码重新访问你的账户。如果你丢了恢复代码,也可以在这里重新生成一个,不过以前的恢复代码就失效了。(废话)
+ lost_recovery_codes: 如果你丢了手机,你可以用恢复代码重新访问你的帐户。如果你丢了恢复代码,也可以在这里重新生成一个,不过以前的恢复代码就失效了。(废话)
manual_instructions: 如果你无法扫描 QR 二维码,请手动输入这个文本密码︰
recovery_codes_regenerated: 已成功重新生成恢复代码
- recovery_instructions_html: 如果你的手机无法使用,你可以使用下面的任何恢复代码来恢复你的账号。请保管好你的恢复代码以防泄漏(例如你可以打印好它们并和重要文档一起保存)。
+ recovery_instructions_html: 如果你的手机无法使用,你可以使用下面的任何恢复代码来恢复你的帐号。请保管好你的恢复代码以防泄漏(例如你可以打印好它们并和重要文档一起保存)。
setup: 设置
wrong_code: 你输入的认证码并不正确!可能服务器时间和你手机不一致,请检查你手机的时钟,或与本站管理员联系。
users:
diff --git a/config/locales/zh-HK.yml b/config/locales/zh-HK.yml
index aa6b1ea6a..8ff6d1bf8 100644
--- a/config/locales/zh-HK.yml
+++ b/config/locales/zh-HK.yml
@@ -242,8 +242,8 @@ zh-HK:
one: "自從上次登入以來,你收到 1 則新的通知 \U0001F418"
other: "自從上次登入以來,你收到 %{count} 則新的通知 \U0001F418"
favourite:
- body: 你的文章獲得 %{name} 的喜愛
- subject: "%{name} 喜歡你的文章"
+ body: 你的文章是 %{name} 的最愛!
+ subject: "%{name} 收藏了你的文章"
follow:
body: "%{name} 開始關注你!"
subject: "%{name} 現正關注你"
diff --git a/config/locales/zh-TW.yml b/config/locales/zh-TW.yml
index 299a92da7..7a66a64ca 100644
--- a/config/locales/zh-TW.yml
+++ b/config/locales/zh-TW.yml
@@ -197,8 +197,8 @@ zh-TW:
one: "自從上次登入以來,您收到 1 則新的通知 \U0001F418"
other: "自從上次登入以來,您收到 %{count} 則新的通知 \U0001F418"
favourite:
- body: 您的文章被 %{name} 喜歡
- subject: "%{name} 喜歡您的文章"
+ body: 您的文章被 %{name} 收藏
+ subject: "%{name} 將您的文章加入了最愛"
follow:
body: "%{name} 開始關注您!"
subject: "%{name} 開始關注您"
--
cgit
From 4c14ff659b8a03c69123ef7b78f4db5c137deeb0 Mon Sep 17 00:00:00 2001
From: Lynx Kotoura
Date: Sun, 17 Sep 2017 22:23:44 +0900
Subject: Oauth code in input form and add description message (#4986)
* Oauth code in a input form and add description
* New authcode description
---
app/javascript/styles/forms.scss | 37 +++++++++++++++++++++++++++
app/views/oauth/authorizations/show.html.haml | 3 ++-
config/locales/doorkeeper.ar.yml | 2 +-
config/locales/doorkeeper.bg.yml | 2 +-
config/locales/doorkeeper.ca.yml | 2 +-
config/locales/doorkeeper.de.yml | 2 +-
config/locales/doorkeeper.en.yml | 2 +-
config/locales/doorkeeper.eo.yml | 2 +-
config/locales/doorkeeper.es.yml | 2 +-
config/locales/doorkeeper.fa.yml | 2 +-
config/locales/doorkeeper.fi.yml | 2 +-
config/locales/doorkeeper.fr.yml | 2 +-
config/locales/doorkeeper.he.yml | 2 +-
config/locales/doorkeeper.hr.yml | 2 +-
config/locales/doorkeeper.hu.yml | 2 +-
config/locales/doorkeeper.id.yml | 2 +-
config/locales/doorkeeper.io.yml | 2 +-
config/locales/doorkeeper.it.yml | 2 +-
config/locales/doorkeeper.ja.yml | 2 +-
config/locales/doorkeeper.nl.yml | 2 +-
config/locales/doorkeeper.no.yml | 2 +-
config/locales/doorkeeper.oc.yml | 2 +-
config/locales/doorkeeper.pl.yml | 2 +-
config/locales/doorkeeper.pt-BR.yml | 2 +-
config/locales/doorkeeper.pt.yml | 2 +-
config/locales/doorkeeper.ru.yml | 2 +-
config/locales/doorkeeper.th.yml | 2 +-
config/locales/doorkeeper.uk.yml | 2 +-
config/locales/doorkeeper.zh-CN.yml | 2 +-
config/locales/doorkeeper.zh-HK.yml | 2 +-
config/locales/doorkeeper.zh-TW.yml | 2 +-
31 files changed, 68 insertions(+), 30 deletions(-)
(limited to 'app/views')
diff --git a/app/javascript/styles/forms.scss b/app/javascript/styles/forms.scss
index 747610237..0526f174c 100644
--- a/app/javascript/styles/forms.scss
+++ b/app/javascript/styles/forms.scss
@@ -349,9 +349,46 @@ code {
box-shadow: 0 0 5px rgba($base-shadow-color, 0.2);
text-align: center;
+ p {
+ margin-bottom: 15px;
+ }
+
+ .oauth-code {
+ color: $ui-secondary-color;
+ outline: 0;
+ box-sizing: border-box;
+ display: block;
+ width: 100%;
+ border: none;
+ padding: 10px;
+ font-family: 'mastodon-font-monospace', monospace;
+ background: $ui-base-color;
+ color: $ui-primary-color;
+ font-size: 14px;
+ margin: 0;
+
+ &::-moz-focus-inner {
+ border: 0;
+ }
+
+ &::-moz-focus-inner,
+ &:focus,
+ &:active {
+ outline: 0 !important;
+ }
+
+ &:focus {
+ background: lighten($ui-base-color, 4%);
+ }
+ }
+
strong {
font-weight: 500;
}
+
+ @media screen and (max-width: 740px) and (min-width: 441px) {
+ margin-top: 40px;
+ }
}
.form-footer {
diff --git a/app/views/oauth/authorizations/show.html.haml b/app/views/oauth/authorizations/show.html.haml
index b56667f35..ad5236007 100644
--- a/app/views/oauth/authorizations/show.html.haml
+++ b/app/views/oauth/authorizations/show.html.haml
@@ -1,3 +1,4 @@
.form-container
.flash-message
- %code= params[:code]
+ %p= t('doorkeeper.authorizations.show.title')
+ %input{ type: 'text', class: 'oauth-code', readonly: true, value: params[:code], onClick: 'select()' }
diff --git a/config/locales/doorkeeper.ar.yml b/config/locales/doorkeeper.ar.yml
index cd4a9cb50..7980e107a 100644
--- a/config/locales/doorkeeper.ar.yml
+++ b/config/locales/doorkeeper.ar.yml
@@ -57,7 +57,7 @@ ar:
prompt: طلبَ تطبيق %{client_name} تصريحا لاستعمال حسابك.
title: إذن بالتصريح
show:
- title: رمز الترخيص
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: إبطال التصريح
diff --git a/config/locales/doorkeeper.bg.yml b/config/locales/doorkeeper.bg.yml
index 6fafdfc55..24de4aee0 100644
--- a/config/locales/doorkeeper.bg.yml
+++ b/config/locales/doorkeeper.bg.yml
@@ -57,7 +57,7 @@ bg:
prompt: Приложението %{client_name} заявява достъп до твоя акаунт
title: Изисква се упълномощаване
show:
- title: Код за упълномощаване
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Отмяна
diff --git a/config/locales/doorkeeper.ca.yml b/config/locales/doorkeeper.ca.yml
index ef937c4e6..38dbbdde9 100644
--- a/config/locales/doorkeeper.ca.yml
+++ b/config/locales/doorkeeper.ca.yml
@@ -57,7 +57,7 @@ ca:
prompt: La aplicació %{client_name} sol⋅licita tenir accés al teu compte
title: Es requereix autorizació
show:
- title: Codi de autorització
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revocar
diff --git a/config/locales/doorkeeper.de.yml b/config/locales/doorkeeper.de.yml
index b0ba2fb98..1588e4f9e 100644
--- a/config/locales/doorkeeper.de.yml
+++ b/config/locales/doorkeeper.de.yml
@@ -57,7 +57,7 @@ de:
prompt: Soll %{client_name} für die Benutzung dieses Accounts autorisiert werden?
title: Autorisierung erforderlich
show:
- title: Autorisierungscode
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Ungültig machen
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index efbd81d43..33d544bed 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -63,7 +63,7 @@ en:
prompt: Application %{client_name} requests access to your account
title: Authorization required
show:
- title: Authorization code
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revoke
diff --git a/config/locales/doorkeeper.eo.yml b/config/locales/doorkeeper.eo.yml
index 33cc7cc19..ce39f3bd1 100644
--- a/config/locales/doorkeeper.eo.yml
+++ b/config/locales/doorkeeper.eo.yml
@@ -57,7 +57,7 @@ eo:
prompt: La aplikaĵo %{client_name} petas aliron al via konto
title: Rajtigo bezonata
show:
- title: Rajtiga kodo
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Malrajtigi
diff --git a/config/locales/doorkeeper.es.yml b/config/locales/doorkeeper.es.yml
index f3efb2301..2c3bc724c 100644
--- a/config/locales/doorkeeper.es.yml
+++ b/config/locales/doorkeeper.es.yml
@@ -57,7 +57,7 @@ es:
prompt: La aplicación %{client_name} solicita tener acceso a su cuenta
title: Se requiere autorización
show:
- title: Código de autorización
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revocar
diff --git a/config/locales/doorkeeper.fa.yml b/config/locales/doorkeeper.fa.yml
index 343580530..6a4be575e 100644
--- a/config/locales/doorkeeper.fa.yml
+++ b/config/locales/doorkeeper.fa.yml
@@ -63,7 +63,7 @@ fa:
prompt: Application %{client_name} requests access to your account
title: Authorization required
show:
- title: Authorization code
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revoke
diff --git a/config/locales/doorkeeper.fi.yml b/config/locales/doorkeeper.fi.yml
index cd1a9d058..44aceec4c 100644
--- a/config/locales/doorkeeper.fi.yml
+++ b/config/locales/doorkeeper.fi.yml
@@ -57,7 +57,7 @@ fi:
prompt: Applikaatio %{client_name} pyytää lupaa tilillesi
title: Valtuutus vaaditaan
show:
- title: Valtuutus koodi
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Evää
diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml
index 487018209..3398b248d 100644
--- a/config/locales/doorkeeper.fr.yml
+++ b/config/locales/doorkeeper.fr.yml
@@ -59,7 +59,7 @@ fr:
prompt: Autoriser %{client_name} à utiliser votre compte ?
title: Autorisation requise
show:
- title: Code d’autorisation
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Annuler
diff --git a/config/locales/doorkeeper.he.yml b/config/locales/doorkeeper.he.yml
index 778902788..1d366b179 100644
--- a/config/locales/doorkeeper.he.yml
+++ b/config/locales/doorkeeper.he.yml
@@ -57,7 +57,7 @@ he :
prompt: ישום %{client_name} מבקש גישה לחשבונך
title: נדרשת הרשאה
show:
- title: קוד הרשאה
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: ביטול
diff --git a/config/locales/doorkeeper.hr.yml b/config/locales/doorkeeper.hr.yml
index 26d21c10d..e0240938e 100644
--- a/config/locales/doorkeeper.hr.yml
+++ b/config/locales/doorkeeper.hr.yml
@@ -57,7 +57,7 @@ hr:
prompt: Aplikacija %{client_name} je zatražila pristup tvom računu
title: Traži se autorizacija
show:
- title: Autorizacijski kod
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Odbij
diff --git a/config/locales/doorkeeper.hu.yml b/config/locales/doorkeeper.hu.yml
index b1c6dd6c9..583e0ad9f 100644
--- a/config/locales/doorkeeper.hu.yml
+++ b/config/locales/doorkeeper.hu.yml
@@ -57,7 +57,7 @@ hu:
prompt: "%{client_name} nevű alkalmazás engedélyt kér a fiókodhoz való hozzáféréshez."
title: Engedély szükséges
show:
- title: Engedély kódja
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Visszavonás
diff --git a/config/locales/doorkeeper.id.yml b/config/locales/doorkeeper.id.yml
index 4ae97c5df..95560ecf9 100644
--- a/config/locales/doorkeeper.id.yml
+++ b/config/locales/doorkeeper.id.yml
@@ -57,7 +57,7 @@ id:
prompt: Aplikasi %{client_name} meminta akses pada akun anda
title: Izin diperlukan
show:
- title: Kode izin
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Cabut izin
diff --git a/config/locales/doorkeeper.io.yml b/config/locales/doorkeeper.io.yml
index 8c093a9d8..28466d3ae 100644
--- a/config/locales/doorkeeper.io.yml
+++ b/config/locales/doorkeeper.io.yml
@@ -57,7 +57,7 @@ io:
prompt: Application %{client_name} requests access to your account
title: Authorization required
show:
- title: Authorization code
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revoke
diff --git a/config/locales/doorkeeper.it.yml b/config/locales/doorkeeper.it.yml
index 4b5e463b0..e5a2d3f6e 100644
--- a/config/locales/doorkeeper.it.yml
+++ b/config/locales/doorkeeper.it.yml
@@ -57,7 +57,7 @@ it:
prompt: L'applicazione %{client_name} richiede l'accesso al tuo account
title: Autorizzazione richiesta
show:
- title: Codice autorizzazione
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Disabilita
diff --git a/config/locales/doorkeeper.ja.yml b/config/locales/doorkeeper.ja.yml
index 9e3b72761..0b670fda4 100644
--- a/config/locales/doorkeeper.ja.yml
+++ b/config/locales/doorkeeper.ja.yml
@@ -63,7 +63,7 @@ ja:
prompt: アプリ %{client_name} があなたのアカウントへのアクセスを要求しています。
title: 認証が必要です。
show:
- title: 認証コード
+ title: 認証コードをコピーしてアプリに貼り付けて下さい。
authorized_applications:
buttons:
revoke: 取消
diff --git a/config/locales/doorkeeper.nl.yml b/config/locales/doorkeeper.nl.yml
index ae1f8bc52..66936d381 100644
--- a/config/locales/doorkeeper.nl.yml
+++ b/config/locales/doorkeeper.nl.yml
@@ -63,7 +63,7 @@ nl:
prompt: "%{client_name} autoriseren om uw account te gebruiken?"
title: Autorisatie vereist
show:
- title: Autorisatie-code
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Intrekken
diff --git a/config/locales/doorkeeper.no.yml b/config/locales/doorkeeper.no.yml
index 23ca61d4d..ba061e0ca 100644
--- a/config/locales/doorkeeper.no.yml
+++ b/config/locales/doorkeeper.no.yml
@@ -57,7 +57,7 @@
prompt: Applikasjon %{client_name} spør om tilgang til din konto
title: Autorisasjon påkrevd
show:
- title: Autoriserings kode
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Opphev
diff --git a/config/locales/doorkeeper.oc.yml b/config/locales/doorkeeper.oc.yml
index 8ebfe2137..1606b92c4 100644
--- a/config/locales/doorkeeper.oc.yml
+++ b/config/locales/doorkeeper.oc.yml
@@ -63,7 +63,7 @@ oc:
prompt: L’aplicacion %{client_name} demanda l’accès al vòstre compte.
title: Cal l’autorizacion
show:
- title: Còdi d’autorizacion
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revocar
diff --git a/config/locales/doorkeeper.pl.yml b/config/locales/doorkeeper.pl.yml
index ee3f4cad8..824a6be90 100644
--- a/config/locales/doorkeeper.pl.yml
+++ b/config/locales/doorkeeper.pl.yml
@@ -63,7 +63,7 @@ pl:
prompt: Aplikacja %{client_name} prosi o dostęp do Twojego konta
title: Wymagana jest autoryzacja
show:
- title: Kod autoryzacji
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Unieważnij
diff --git a/config/locales/doorkeeper.pt-BR.yml b/config/locales/doorkeeper.pt-BR.yml
index f0f3c6893..53cadec38 100644
--- a/config/locales/doorkeeper.pt-BR.yml
+++ b/config/locales/doorkeeper.pt-BR.yml
@@ -63,7 +63,7 @@ pt-BR:
prompt: O aplicativo %{client_name} solicita acesso à sua conta
title: Autorização necessária
show:
- title: Código de autorização
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revogar
diff --git a/config/locales/doorkeeper.pt.yml b/config/locales/doorkeeper.pt.yml
index 87e01ba94..30d9f7f5a 100644
--- a/config/locales/doorkeeper.pt.yml
+++ b/config/locales/doorkeeper.pt.yml
@@ -57,7 +57,7 @@ pt:
prompt: Aplicação %{client_name} pede acesso à tua conta
title: Autorização é necessária
show:
- title: Código de autorização
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Revogar
diff --git a/config/locales/doorkeeper.ru.yml b/config/locales/doorkeeper.ru.yml
index 8862936dc..2234a9bbe 100644
--- a/config/locales/doorkeeper.ru.yml
+++ b/config/locales/doorkeeper.ru.yml
@@ -57,7 +57,7 @@ ru:
prompt: Приложение %{client_name} запрашивает доступ к Вашему аккаунту
title: Требуется авторизация
show:
- title: Код авторизации
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Отозвать авторизацию
diff --git a/config/locales/doorkeeper.th.yml b/config/locales/doorkeeper.th.yml
index 29673971b..60edae1e4 100644
--- a/config/locales/doorkeeper.th.yml
+++ b/config/locales/doorkeeper.th.yml
@@ -57,7 +57,7 @@ th:
prompt: Application %{client_name} requests access to your account
title: Authorization required
show:
- title: Authorization code
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: ยกเลิกการอนุญาติ
diff --git a/config/locales/doorkeeper.uk.yml b/config/locales/doorkeeper.uk.yml
index a5289541b..d80abf01a 100644
--- a/config/locales/doorkeeper.uk.yml
+++ b/config/locales/doorkeeper.uk.yml
@@ -57,7 +57,7 @@ uk:
prompt: Податок %{client_name} просить доступу до вашого акаунту
title: Необхідна авторизація
show:
- title: Код авторизації
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: Відкликати авторизацію
diff --git a/config/locales/doorkeeper.zh-CN.yml b/config/locales/doorkeeper.zh-CN.yml
index 6db8697b8..12b38b81f 100644
--- a/config/locales/doorkeeper.zh-CN.yml
+++ b/config/locales/doorkeeper.zh-CN.yml
@@ -58,7 +58,7 @@ zh-CN:
prompt: 授权 %{client_name} 使用你的帐号?
title: 需要你授权
show:
- title: 授权码
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: 注销
diff --git a/config/locales/doorkeeper.zh-HK.yml b/config/locales/doorkeeper.zh-HK.yml
index bb44c272b..ac1e3180a 100644
--- a/config/locales/doorkeeper.zh-HK.yml
+++ b/config/locales/doorkeeper.zh-HK.yml
@@ -57,7 +57,7 @@ zh-HK:
prompt: 應用程式 %{client_name} 要求得到你用戶的部份權限
title: 需要用戶授權
show:
- title: 授權代碼
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: 取消授權
diff --git a/config/locales/doorkeeper.zh-TW.yml b/config/locales/doorkeeper.zh-TW.yml
index 7e8c78cd9..5110c8aa3 100644
--- a/config/locales/doorkeeper.zh-TW.yml
+++ b/config/locales/doorkeeper.zh-TW.yml
@@ -57,7 +57,7 @@ zh-TW:
prompt: 應用程式 %{client_name} 要求取得您帳號的部份權限
title: 需要授權
show:
- title: 授權代碼
+ title: Copy this authorization code and paste it to the application.
authorized_applications:
buttons:
revoke: 取消授權
--
cgit
From 9e0985d9e4face90519ddfa0446e3b3bc9370e7d Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 18 Sep 2017 11:55:23 +0900
Subject: Add `strip_insignificant_zeros: true` option to `number_to_human`
(#4993)
---
app/views/accounts/_header.html.haml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
(limited to 'app/views')
diff --git a/app/views/accounts/_header.html.haml b/app/views/accounts/_header.html.haml
index a6366b0f3..08c3891d2 100644
--- a/app/views/accounts/_header.html.haml
+++ b/app/views/accounts/_header.html.haml
@@ -37,15 +37,15 @@
.details-counters
.counter{ class: active_nav_class(short_account_url(account)) }
= link_to short_account_url(account), class: 'u-url u-uid' do
- %span.counter-number= number_to_human account.statuses_count
+ %span.counter-number= number_to_human account.statuses_count, strip_insignificant_zeros: true
%span.counter-label= t('accounts.posts')
.counter{ class: active_nav_class(account_following_index_url(account)) }
= link_to account_following_index_url(account) do
- %span.counter-number= number_to_human account.following_count
+ %span.counter-number= number_to_human account.following_count, strip_insignificant_zeros: true
%span.counter-label= t('accounts.following')
.counter{ class: active_nav_class(account_followers_url(account)) }
= link_to account_followers_url(account) do
- %span.counter-number= number_to_human account.followers_count
+ %span.counter-number= number_to_human account.followers_count, strip_insignificant_zeros: true
%span.counter-label= t('accounts.followers')
--
cgit
From dcf1139ebd65375fd130d71c2e664827d00e9d4f Mon Sep 17 00:00:00 2001
From: Yamagishi Kazutoshi
Date: Mon, 18 Sep 2017 22:00:29 +0900
Subject: Do not add image size without meta to OGP (regression from #4901)
(#4995)
---
app/views/stream_entries/_og_image.html.haml | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
(limited to 'app/views')
diff --git a/app/views/stream_entries/_og_image.html.haml b/app/views/stream_entries/_og_image.html.haml
index 66d9619b2..b5058583b 100644
--- a/app/views/stream_entries/_og_image.html.haml
+++ b/app/views/stream_entries/_og_image.html.haml
@@ -3,17 +3,20 @@
- if media.image?
= opengraph 'og:image', full_asset_url(media.file.url(:original))
= opengraph 'og:image:type', media.file_content_type
- = opengraph 'og:image:width', media.file.meta['original']['width']
- = opengraph 'og:image:height', media.file.meta['original']['height']
+ - unless media.file.meta.nil?
+ = opengraph 'og:image:width', media.file.meta['original']['width']
+ = opengraph 'og:image:height', media.file.meta['original']['height']
- elsif media.video?
= opengraph 'og:image', full_asset_url(media.file.url(:small))
= opengraph 'og:image:type', 'image/png'
- = opengraph 'og:image:width', media.file.meta['small']['width']
- = opengraph 'og:image:height', media.file.meta['small']['height']
+ - unless media.file.meta.nil?
+ = opengraph 'og:image:width', media.file.meta['small']['width']
+ = opengraph 'og:image:height', media.file.meta['small']['height']
= opengraph 'og:video', full_asset_url(media.file.url(:original))
= opengraph 'og:video:type', media.file_content_type
- = opengraph 'og:video:width', media.file.meta['small']['width']
- = opengraph 'og:video:height', media.file.meta['small']['height']
+ - unless media.file.meta.nil?
+ = opengraph 'og:video:width', media.file.meta['small']['width']
+ = opengraph 'og:video:height', media.file.meta['small']['height']
- else
= opengraph 'og:image', full_asset_url(account.avatar.url(:original))
= opengraph 'og:image:width', '120'
--
cgit
From c155d843f4d523d52ce4ce67491578385c06fd1b Mon Sep 17 00:00:00 2001
From: BruWalfas
Date: Mon, 18 Sep 2017 19:47:48 -0300
Subject: A few updates to the Spanish translation and some typos fixing
(#4997)
* So Spanish. Much changes. Wow.
* Some little fixes
* Updated es.yml, and fixed some ortographical errors
* Some little changes to simple_form.es.yml
* Yeah, so much translations
* Spanish e-mail messages
* Remove unused message
---
app/javascript/mastodon/locales/es.json | 12 +-
.../confirmation_instructions.es.html.erb | 12 +
.../confirmation_instructions.es.text.erb | 12 +
app/views/user_mailer/password_change.es.html.erb | 3 +
app/views/user_mailer/password_change.es.text.erb | 3 +
.../reset_password_instructions.es.html.erb | 8 +
.../reset_password_instructions.es.text.erb | 8 +
config/locales/doorkeeper.es.yml | 9 +-
config/locales/es.yml | 411 ++++++++++++++++++++-
config/locales/simple_form.es.yml | 13 +-
10 files changed, 474 insertions(+), 17 deletions(-)
create mode 100644 app/views/user_mailer/confirmation_instructions.es.html.erb
create mode 100644 app/views/user_mailer/confirmation_instructions.es.text.erb
create mode 100644 app/views/user_mailer/password_change.es.html.erb
create mode 100644 app/views/user_mailer/password_change.es.text.erb
create mode 100644 app/views/user_mailer/reset_password_instructions.es.html.erb
create mode 100644 app/views/user_mailer/reset_password_instructions.es.text.erb
(limited to 'app/views')
diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json
index 325ed3b26..5182b5094 100644
--- a/app/javascript/mastodon/locales/es.json
+++ b/app/javascript/mastodon/locales/es.json
@@ -5,16 +5,16 @@
"account.edit_profile": "Editar perfil",
"account.follow": "Seguir",
"account.followers": "Seguidores",
- "account.follows": "Seguir",
+ "account.follows": "Sigue",
"account.follows_you": "Te sigue",
"account.media": "Media",
- "account.mention": "Mencionar",
- "account.mute": "Silenciar",
+ "account.mention": "Mencionar a @{name}",
+ "account.mute": "Silenciar a @{name}",
"account.posts": "Publicaciones",
"account.report": "Reportar a @{name}",
"account.requested": "Esperando aprobación",
"account.share": "Compartir el perfil de @{name}",
- "account.unblock": "Desbloquear",
+ "account.unblock": "Desbloquear a @{name}",
"account.unblock_domain": "Mostrar a {domain}",
"account.unfollow": "Dejar de seguir",
"account.unmute": "Dejar de silenciar a @{name}",
@@ -27,9 +27,9 @@
"bundle_modal_error.message": "Algo salió mal al cargar este componente.",
"bundle_modal_error.retry": "Inténtalo de nuevo",
"column.blocks": "Usuarios bloqueados",
- "column.community": "Historia local",
+ "column.community": "Línea de tiempo local",
"column.favourites": "Favoritos",
- "column.follow_requests": "Solicitudes para seguirte",
+ "column.follow_requests": "Solicitudes de seguimiento",
"column.home": "Inicio",
"column.mutes": "Usuarios silenciados",
"column.notifications": "Notificaciones",
diff --git a/app/views/user_mailer/confirmation_instructions.es.html.erb b/app/views/user_mailer/confirmation_instructions.es.html.erb
new file mode 100644
index 000000000..1d46a12c0
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.es.html.erb
@@ -0,0 +1,12 @@
+
¡Bienvenido, <%= @resource.email %>!
+
+
Acabas de crear una cuenta en <%= @instance %>.
+
+
Para confirmar tu registro, por favor ingresa al siguiente enlace:
+<%= link_to 'Confirmar mi cuenta', confirmation_url(@resource, confirmation_token: @token) %>
+
+
También revisa nuestros <%= link_to 'términos y condiciones', terms_url %>.
+
+
Sinceramente,
+
+
El equipo de <%= @instance %>
\ No newline at end of file
diff --git a/app/views/user_mailer/confirmation_instructions.es.text.erb b/app/views/user_mailer/confirmation_instructions.es.text.erb
new file mode 100644
index 000000000..e9d83b3f8
--- /dev/null
+++ b/app/views/user_mailer/confirmation_instructions.es.text.erb
@@ -0,0 +1,12 @@
+¡Bienvenido, <%= @resource.email %>!
+
+Acabas de crear una cuenta en <%= @instance %>.
+
+Para confirmar tu registro, por favor ingresa al siguiente enlace:
+<%= confirmation_url(@resource, confirmation_token: @token) %>
+
+Por favor, también revisa nuestros términos y condiciones <%= terms_url %>
+
+Sinceramente,
+
+El equipo de <%= @instance %>
\ No newline at end of file
diff --git a/app/views/user_mailer/password_change.es.html.erb b/app/views/user_mailer/password_change.es.html.erb
new file mode 100644
index 000000000..0a9eb4c4c
--- /dev/null
+++ b/app/views/user_mailer/password_change.es.html.erb
@@ -0,0 +1,3 @@
+
¡Hola, <%= @resource.email %>!
+
+
Te contactamos para notificarte que tu contraseña en <%= @instance %> ha sido modificada.
\ No newline at end of file
diff --git a/app/views/user_mailer/password_change.es.text.erb b/app/views/user_mailer/password_change.es.text.erb
new file mode 100644
index 000000000..192faf9ad
--- /dev/null
+++ b/app/views/user_mailer/password_change.es.text.erb
@@ -0,0 +1,3 @@
+¡Hola, <%= @resource.email %>!
+
+Te contactamos para notificarte que tu contraseña en <%= @instance %> ha sido modificada.
\ No newline at end of file
diff --git a/app/views/user_mailer/reset_password_instructions.es.html.erb b/app/views/user_mailer/reset_password_instructions.es.html.erb
new file mode 100644
index 000000000..4eeb6601d
--- /dev/null
+++ b/app/views/user_mailer/reset_password_instructions.es.html.erb
@@ -0,0 +1,8 @@
+
¡Hola, <%= @resource.email %>!
+
+
Alguien pidió un enlace para cambiar tu contraseña en <%= @instance %>. Puedes hacer esto con el siguiente enlace.
+
+
<%= link_to 'Cambiar mi contraseña', edit_password_url(@resource, reset_password_token: @token) %>
+
+
Si no fuiste tú, por favor ignora este mensaje.
+
Tu contraseña no cambiará hasta que ingreses al enlace y crees una nueva.
diff --git a/app/views/user_mailer/reset_password_instructions.es.text.erb b/app/views/user_mailer/reset_password_instructions.es.text.erb
new file mode 100644
index 000000000..8abafcc99
--- /dev/null
+++ b/app/views/user_mailer/reset_password_instructions.es.text.erb
@@ -0,0 +1,8 @@
+¡Hola, <%= @resource.email %>!
+
+Alguien pidió un enlace para cambiar tu contraseña en <%= @instance %>. Puedes hacer esto con el siguiente enlace.
+
+<%= edit_password_url(@resource, reset_password_token: @token) %>
+
+Si no fuiste tú, por favor ignora este mensaje.
+Tu contraseña no cambiará hasta que ingreses al enlace y crees una nueva.
diff --git a/config/locales/doorkeeper.es.yml b/config/locales/doorkeeper.es.yml
index 2c3bc724c..af21ab76d 100644
--- a/config/locales/doorkeeper.es.yml
+++ b/config/locales/doorkeeper.es.yml
@@ -5,6 +5,8 @@ es:
doorkeeper/application:
name: Nombre
redirect_uri: URI para redirección
+ scopes: Ámbitos
+ website: Sitio web
errors:
models:
doorkeeper/application:
@@ -33,16 +35,20 @@ es:
redirect_uri: Utilice una línea por URI
scopes: Separe los ámbitos con espacios. Déjelo en blanco para utilizar los ámbitos por defecto.
index:
+ application: Aplicación
callback_url: Callback URL
+ delete: Eliminar
name: Nombre
new: Nueva aplicación
+ scopes: Ámbitos
+ show: Mostrar
title: Sus aplicaciones
new:
title: Nueva aplicación
show:
actions: Acciones
application_id: Id de la aplicación
- callback_urls: Callback urls
+ callback_urls: Callback URLs
scopes: Ámbitos
secret: Secreto
title: 'Aplicación: %{name}'
@@ -67,6 +73,7 @@ es:
application: Aplicación
created_at: Creado el
date_format: "%A-%m-%d %H:%M:%S"
+ scopes: Ámbitos
title: Sus aplicaciones autorizadas
errors:
messages:
diff --git a/config/locales/es.yml b/config/locales/es.yml
index a02330521..6e544e19d 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -5,33 +5,249 @@ es:
about_this: Acerca de esta instancia
closed_registrations: Los registros están actualmente cerrados en esta instancia.
contact: Contacto
+ contact_missing: No especificado
+ contact_unavailable: N/A
description_headline: "¿Qué es %{domain}?"
domain_count_after: otras instancias
domain_count_before: Conectado a
+ extended_description_html: |
+
Un buen lugar para las reglas
+
La descripción extendida no se ha colocado aún.
+ features:
+ humane_approach_body: Aprendiendo de los errores de otras redes, Mastodon apunta a las decisiones de diseño ético para combatir el desuso de las redes sociales.
+ humane_approach_title: Una misión más humana
+ not_a_product_body: Mastodon no es una red comercial. Nada de publicidad, nada de minado de datos, nada de jardines murados. No hay ninguna autoridad central.
+ not_a_product_title: Eres una persona, no un producto
+ real_conversation_body: Con 500 caracteres a tu disposición y soporte para contenido granular y advertencias de contenido, puedes expresarte como quieras.
+ real_conversation_title: Hecho para verdaderas conversaciones
+ within_reach_body: Aplicaciones múltiples para iOS, Android, y otras plataformas gracias a un ecosistema de APIs amigable al desarrollador para permitirte estar con tus amigos donde sea.
+ within_reach_title: Always within reach
+ find_another_instance: Busca otra instancia
+ generic_description: "%{domain} es un servidor en la red"
+ hosted_on: Mastodon hosteado en %{domain}
+ learn_more: Aprende más
other_instances: Otras instancias
source_code: Código fuente
status_count_after: estados
- status_count_before: Que han escrito
+ status_count_before: Qué han escrito
user_count_after: usuarios registrados
user_count_before: Tenemos
+ what_is_mastodon: ¿Qué es Mastodon?
accounts:
follow: Seguir
followers: Seguidores
following: Siguiendo
+ media: Media
nothing_here: "¡No hay nada aquí!"
people_followed_by: Usuarios a quien %{name} sigue
people_who_follow: Usuarios que siguen a %{name}
posts: Toots
+ posts_with_replies: Toots con respuestas
remote_follow: Seguir
+ reserved_username: El nombre de usuario está reservado
+ roles:
+ admin: Administrador
unfollow: Dejar de seguir
+ admin:
+ accounts:
+ are_you_sure: ¿Estás seguro?
+ confirm: Confirmar
+ confirmed: Confirmado
+ disable_two_factor_authentication: Desactivar autenticación de dos factores
+ display_name: Nombre
+ domain: Dominio
+ edit: Editar
+ email: E-mail
+ feed_url: URL de notificaciones
+ followers: Seguidores
+ followers_url: URL de los seguidores
+ follows: Sigue
+ inbox_url: URL de la bandeja de entrada
+ ip: IP
+ location:
+ all: Todos
+ local: Local
+ remote: Remoto
+ title: Localización
+ media_attachments: Multimedia
+ moderation:
+ all: Todos
+ silenced: Silenciados
+ suspended: Suspendidos
+ title: Moderación
+ most_recent_activity: Actividad más reciente
+ most_recent_ip: IP más reciente
+ not_subscribed: No se está suscrito
+ order:
+ alphabetic: Alfabético
+ most_recent: Más reciente
+ title: Orden
+ outbox_url: URL de bandeja de salida
+ perform_full_suspension: Performar suspensión completa
+ profile_url: URL del perfil
+ protocol: Protocolo
+ public: Público
+ push_subscription_expires: Expiración de la suscripción PuSH
+ redownload: Refrescar avatar
+ reset: Reiniciar
+ reset_password: Reiniciar contraseña
+ resubscribe: Re-suscribir
+ salmon_url: URL de salmón
+ search: Buscar
+ shared_inbox_url: URL de bandeja compartida
+ show:
+ created_reports: Reportes hechos por esta cuenta
+ report: reportar
+ targeted_reports: Reportes hechos sobre esta cuenta
+ silence: Silenciar
+ statuses: Estados
+ subscribe: Suscribir
+ title: Cuentas
+ undo_silenced: Des-silenciar
+ undo_suspension: Des-suspender
+ unsubscribe: Desuscribir
+ username: Nombre de usuario
+ web: Web
+ domain_blocks:
+ add_new: Añadir nuevo
+ created_msg: El bloque de dominio está siendo procesado
+ destroyed_msg: El bloque de dominio se deshizo
+ domain: Dominio
+ new:
+ create: Crear bloque
+ hint: El bloque de dominio no prevendrá la creación de entradas de cuenta en la base de datos, pero aplicará retroactiva y automáticamente métodos de moderación específica en dichas cuentas.
+ severity:
+ desc_html: "Silenciar hará los posts de la cuenta invisibles a cualquiera que no lo esté siguiendo. Suspender eliminará todo el contenido, media, y datos del perfil. Usa Ninguno si solo quieres rechazar archivos multimedia."
+ noop: Ninguno
+ silence: Silenciar
+ suspend: Suspender
+ title: Nuevo bloque de dominio
+ reject_media: Rechazar archivos multimedia
+ reject_media_hint: Remueve localmente archivos multimedia almacenados para descargar cualquiera en el futuro. Irrelevante para suspensiones
+ severities:
+ noop: Ninguno
+ silence: Silenciar
+ suspend: Suspender
+ severity: Severidad
+ show:
+ affected_accounts:
+ one: Una cuenta en la base de datos afectada
+ other: "%{count} cuentas en la base de datos afectadas"
+ retroactive:
+ silence: Des-silenciar todas las cuentas existentes de este dominio
+ suspend: Des-suspender todas las cuentas existentes de este dominio
+ title: Deshacer bloque de dominio para %{domain}
+ undo: Deshacer
+ title: Bloques de Dominio
+ undo: Deshacer
+ instances:
+ account_count: Cuentas conocidas
+ domain_name: Dominio
+ reset: Reiniciar
+ search: Buscar
+ title: Instancias conocidas
+ reports:
+ action_taken_by: Acción tomada por
+ are_you_sure: ¿Estás seguro?
+ comment:
+ label: Comentario
+ none: Ninguno
+ delete: Eliminar
+ id: ID
+ mark_as_resolved: Marcar como resuelto
+ nsfw:
+ 'false': Mostrar multimedia
+ 'true': Ocultar multimedia
+ report: 'Reportar #%{id}'
+ report_contents: Contenido
+ reported_account: Cuenta reportada
+ reported_by: Reportado por
+ resolved: Resuelto
+ silence_account: Silenciar cuenta
+ status: Estado
+ suspend_account: Suspender cuenta
+ target: Objetivo
+ title: Reportes
+ unresolved: No resuelto
+ view: Ver
+ settings:
+ bootstrap_timeline_accounts:
+ desc_html: Separa nombres de usuarios múltiples con coma. Solo funcionará con cuentas desbloqueadas. Si está vacío, el predeterminado son todos los administradores locales
+ title: Seguimientos predeterminados para usuarios nuevos
+ contact_information:
+ email: Correo de trabajo
+ username: Nombre de usuario
+ registrations:
+ closed_message:
+ desc_html: Se muestra en la portada cuando los registros están cerrados. Puedes usar tags HTML
+ title: Mensaje de registro cerrado
+ deletion:
+ desc_html: Permite a cualquiera a eliminar su cuenta
+ title: Eliminación de cuenta abierta
+ open:
+ desc_html: Permite a cualquiera a registrar una cuenta
+ title: Registro abierto
+ site_description:
+ desc_html: Párrafo introductorio en la portada y en meta tags. Puedes usar tags HTML, en particular <a> y <em>.
+ title: Descripción de instancia
+ site_description_extended:
+ desc_html: Un buen lugar para tu código de conducta, reglas, guías y otras cosas que estén impuestas aparte en tu instancia. Puedes usar tags HTML
+ title: Información extendida personalizada
+ site_terms:
+ desc_html: Puedes escribir tus propias políticas de privacidad, términos de servicio u otras legalidades. Puedes usar tags HTML
+ title: Términos de servicio personalizados
+ site_title: Nombre de instancia
+ thumbnail:
+ desc_html: Se usa para muestras con OpenGraph y APIs. Se recomienda 1200x630px
+ title: Portada de instancia
+ timeline_preview:
+ desc_html: Mostrar línea de tiempo pública en la portada
+ title: Previsualización
+ title: Ajustes del sitio
+ statuses:
+ back_to_account: Volver a la cuenta
+ batch:
+ delete: Eliminar
+ nsfw_off: NSFW OFF
+ nsfw_on: NSFW ON
+ execute: Ejecutar
+ failed_to_execute: Falló al ejecutar
+ media:
+ hide: Ocultar multimedia
+ show: Mostrar multimedia
+ title: Multimedia
+ no_media: No hay multimedia
+ title: Estado de las cuentas
+ with_media: Con multimedia
+ subscriptions:
+ callback_url: URL del callback
+ confirmed: Confirmado
+ expires_in: Expira en
+ last_delivery: Última entrega
+ title: WebSub
+ topic: Tópico
+ title: Administración
+ admin_mailer:
+ new_report:
+ body: "%{reporter} ha reportado a %{target}"
+ subject: Nuevo reporte para la %{instance} (#%{id})
application_mailer:
settings: 'Cambiar preferencias de correo: %{link}'
signature: Notificaciones de Mastodon desde %{instance}
view: 'Vista:'
applications:
+ created: Aplicación creada exitosamente
+ destroyed: Apicación eliminada exitosamente
+ regenerate_token: Regenerar token de acceso
+ token_regenerated: Token de acceso regenerado exitosamente
+ warning: Ten mucho cuidado con estos datos. ¡No los compartas con nadie!
+ your_token: Tu token de acceso
invalid_url: La URL proporcionada es incorrecta
auth:
+ agreement_html: Al registrarte aceptas nuestros y términos y condiciones del servicio y nuestras políticas de privacidda.
change_password: Cambiar contraseña
+ delete_account_html: Si desea eliminar su cuenta, puede proceder aquí. Será pedido de una confirmación.
+ invalid_reset_password_token: El token de reinicio de contraseña es inválido o expiró. Por favor pide uno nuevo.
didnt_get_confirmation: "¿No recibió el correo de confirmación?"
forgot_password: "¿Olvidaste tu contraseña?"
login: Iniciar sesión
@@ -43,7 +259,13 @@ es:
authorize_follow:
error: Desafortunadamente, ha ocurrido un error buscando la cuenta remota
follow: Seguir
- title: Seguir %{acct}
+ follow_request: 'Tienes una solicitud de seguimiento de:'
+ following: '¡Éxito! Ahora estás siguiendo a:'
+ post_follow:
+ close: O, puedes simplemente cerrar esta ventana.
+ return: Regresar al perfil del usuario
+ web: Ir al sitio web
+ title: Seguir a %{acct}
datetime:
distance_in_words:
about_x_hours: "%{count}h"
@@ -58,14 +280,43 @@ es:
x_minutes: "%{count}m"
x_months: "%{count}m"
x_seconds: "%{count}s"
+ deletes:
+ bad_password_msg: ¡Buen intento, hackers! Contraseña incorrecta
+ confirm_password: Ingresa tu contraseña actual para demostrar tu identidad
+ description_html: Esto removerá el contenido de tu cuenta y la desactivará permanente e irrevesiblemente. Tu nombre de usuario quedará reservado para prevenir futuros robos de identidad.
+ proceed: Eliminar cuenta
+ success_msg: Tu cuenta se eliminó con éxito
+ warning_html: Se garantiza únicamente la eliminación del contenido de esta instancia. El contenido que se haya compartido extensamente dejará sus huellas. Los servidores fuera de línea y los que se hayan desuscrito de tus actualizaciones ya no actualizarán sus bases de datos.
+ warning_title: Disponibilidad diseminada del contenido
+ errors:
+ '403': No tienes permiso para acceder a esta página.
+ '404': La página que estabas buscando no existe.
+ '410': La página que estabas buscando no existe más.
+ '422':
+ content: Verificación de seguridad fallida. ¿Estás bloqueando algunas cookies?
+ title: Verificación de seguridad fallida
+ '429': Asfixiado
+ noscript_html: Para usar la aplicación web de Mastodon, por favor activa Javascript. Alternativamente, prueba alguna de las aplicaciones nativas para Mastodon para tu plataforma.
exports:
blocks: Personas que has bloqueado
csv: CSV
follows: Personas que sigues
storage: Almacenamiento
+ followers:
+ domain: Dominio
+ explanation_html: Si deseas asegurar la privacidad de tus estados, tienes que cuidarte de quién te sigue. Tus estados privados son enviados a todas las instancias de tus seguidores. Puede que desees revisarlas, y remover seguidores si no confías en tu privacidad para ser respetado por el staff o software de esas instancias.
+ followers_count: Número de seguidores
+ lock_link: Bloquear tu cuenta
+ purge: Remover de los seguidores
+ success:
+ one: En el proceso de bloquear suavemente usuarios de un solo dominio...
+ other: En el proceso de bloquear suavemente usuarios de %{count} dominios...
+ true_privacy_html: Por favor ten en cuenta que la verdadera privacidad se consigue con encriptación de punto a punto.
+ unlocked_warning_html: Todos pueden seguirte para ver tus estados privados inmediatamente. %{lock_link} para poder chequear y rechazar seguidores.
+ unlocked_warning_title: Tu cuenta no está bloqueada
generic:
changes_saved_msg: "¡Cambios guardados con éxito!"
- powered_by: powered by %{link}
+ powered_by: gracias a %{link}
save_changes: Guardar cambios
validation_errors:
one: "¡Algo no está bien! Por favor, revisa el error"
@@ -76,9 +327,10 @@ es:
types:
blocking: Lista de bloqueados
following: Lista de seguidos
+ muting: Lista de silenciados
upload: Cargar
landing_strip_html: "%{name} es un usuario en %{link_to_root_path}. Puedes seguirlo(a) o interactuar con el o ella si tienes una cuenta en cualquier parte del fediverse."
- landing_strip_signup_html: Si no tienes una, puedes registrar aquí.
+ landing_strip_signup_html: Si no tienes una, puedes registrarte aquí.
media_attachments:
validations:
images_and_video: No se puede adjuntar un video a un estado que ya contenga imágenes
@@ -88,8 +340,8 @@ es:
body: 'Un resumen de lo que te perdiste en %{instance} desde tu última visita el %{since}:'
mention: "%{name} te ha mencionado en:"
new_followers_summary:
- one: "¡Hurra!. Alguien más te ha comenzado a seguir"
- other: "¡Genial!. Te han seguido %{count} nuevas personas"
+ one: "¡Hurra! Alguien más te ha comenzado a seguir"
+ other: "¡Genial! Te han seguido %{count} nuevas personas"
subject:
one: "1 nueva notificación desde tu última visita \U0001F418"
other: "%{count} nuevas notificaciones desde tu última visita \U0001F418"
@@ -122,11 +374,65 @@ es:
pagination:
next: Próximo
prev: Anterior
+ truncate: "…"
+ push_notifications:
+ favourite:
+ title: "%A {name} le gustó tu estado"
+ follow:
+ title: "%{name} te ha empezado a seguir"
+ group:
+ title: "%{count} notificaciones"
+ mention:
+ action_boost: Boost
+ action_expand: Mostrar más
+ action_favourite: Me Gusta
+ title: "%{name} te mencionó"
+ reblog:
+ title: "%{name} boosteó tu estado"
remote_follow:
acct: Ingesa el usuario@dominio de la persona que quieres seguir
missing_resource: No se pudo encontrar la URL de redirección necesaria para su cuenta.
proceed: Proceder a seguir
prompt: 'Vas a seguir a:'
+ sessions:
+ activity: Última actividad
+ browser: Navegador
+ browsers:
+ alipay: Alipay
+ blackberry: Blackberry
+ chrome: Chrome
+ edge: Microsoft Edge
+ firefox: Firefox
+ generic: Desconocido
+ ie: Internet Explorer
+ micro_messenger: MicroMessenger
+ nokia: Nokia S40 Ovi Browser
+ opera: Opera
+ phantom_js: PhantomJS
+ qq: QQ Browser
+ safari: Safari
+ uc_browser: UCBrowser
+ weibo: Weibo
+ current_session: Sesión actual
+ description: "%{browser} en %{platform}"
+ explanation: Estos son los navegadores web conectados actualmente en tu cuenta de Mastodon.
+ ip: IP
+ platforms:
+ adobe_air: Adobe Air
+ android: Android
+ blackberry: Blackberry
+ chrome_os: ChromeOS
+ firefox_os: Firefox OS
+ ios: iOS
+ linux: Linux
+ mac: Mac
+ other: Desconocido
+ windows: Windows
+ windows_mobile: Windows Mobile
+ windows_phone: Windows Phone
+ revoke: Revoke
+ revoke_success: Sesión revocada exitosamente
+ title: Sesiones
settings:
authorized_apps: Aplicaciones autorizadas
back: Volver al inicio
@@ -136,26 +442,115 @@ es:
preferences: Preferencias
settings: Ajustes
two_factor_authentication: Autenticación de dos factores
+ your_apps: Tus aplicaciones
statuses:
open_in_web: Abrir en web
over_character_limit: Límite de caracteres de %{max} superado
+ pin_errors:
+ limit: Demasiados toots fijados
+ ownership: El toot de alguien más no puede fijarse
+ private: Los toots no-públicos no pueden fijarse
+ reblog: Un boost no puede fijarse
show_more: Mostrar más
visibilities:
private: Sólo mostrar a seguidores
+ private_long: Solo mostrar a tus seguidores
public: Público
+ public_long: Todos pueden ver
unlisted: Público, pero no mostrar en la historia federada
+ unlisted_long: Todos pueden ver, pero no está listado en las líneas de tiempo públicas
stream_entries:
click_to_show: Click para mostrar
reblogged: retooteado
sensitive_content: Contenido sensible
+ pinned: Toot fijado
+ terms:
+ body_html: |
+
Políticas de privacidad
+
+
¿Qué información recolectamos?
+
+
Recolectamos información tuya cuando te registras en nuestro sitio y adquirimos datos cuando participas en el foro leyendo, escribiendo, y evaluando el contenido compartido aquí.
+
+
Cuando te registras en nuestro sitio, puede que se te pida tu nombre y dirección de correo electrónico. De todas formas, puedes visitar nuestro sitio sin registrarte. Tu dirección de correo electrónico será verificada por un e-mail conteniendo un enlace único. Si ese enlace es visitado, sabemos que tú controlas esa dirección.
+
+
Cuando te registras y posteas, grabamos la IP de la que se origina esa acción. También puede que retengamos logs del servidor, que incluyen la dirección IP de todos los pedidos a nuestro servidor.
+
+
¿Para qué usamos tu información?
+
+
Toda la información que recolectamos de ti puede usarse en una de las siguientes maneras:
+
+
+
Para personalizar tu experiencia — tu información nos ayuda a responder mejor tus necesidades individuales.
+
Para mejorar nuestro sitio — nos esforzamos continuamente en mejorar nuestras ofertas del sitio basándonos en la información y apoyo que recibimos de ti.
+
Para mejorar el servicio al cliente — tu información nos ayuda a responder más efectivamente al servicio al cliente y otras necesidades.
+
Para enviar e-mails periódicos — la dirección de e-mail que provees puede usarse para enviarte información, notificaciones que pides sobre cambios en tópicos o en respuesta a tu nombre de usuario, responder consultas, y/u otros pedidos o preguntas.
+
+
+
¿Cómo protegemos tu información?
+
+
Implementamos una variedad de medidas de seguridad para mantener a salvo tu información personal cuando entras, publicas, o accesas a ella.
+
+
¿Cuáles son sus políticas de retención de datos?
+
+
Haremos un gran esfuerzo en:
+
+
+
Retener logs del servidor conteniendo la dirección IP de todos los pedidos a este servidor en no más de 90 días.
+
Retener las direcciones IP asociadas con usuarios registrados y sus posts no más de 5 años.
+
+
+
+
+
Sí. Las cookies son pequeños archivos que un sitio web o su proveedor de servicio transfieren al disco duro de tu computadora a través de tu navegador web (si se le permite). Estas cookies permiten al sitio reconocer tu navegador y, si y tienes una cuenta registrada, asociarlo con ella.
+
+
Usamos cookies para entender y guardar tus preferencias para futuras visitas y agregar datos compilados sobre el tráfico del sitio e interacción para que podamos ofrecer una mejor experiencia y herramientas en el futuro. Puede que contratemos con proveedores de servicio de tercera mano para que nos asistan en el mejor entendimiento de nuestros visitantes del sitio. A estos proveedores de servicio no se les permite usar la información recolectada a nuestras espaldas excepto para ayudarnos a conducir y mejorar nuestro trabajo.
+
+
¿Revelamos alguna información a terceras manos?
+
+
No vendemos, intercambiamos, ni de ninguna otra manera transferimos tu información personal identificable a terceras partes. Esto no incluye las terceras manos que nos asisten en operar nuestro sitio, conducción o trabajo, o en servirte, tanto como que éstas acepten en mantener esta información confidencial. Puede que también liberemos tu información cuando creamos que es apropiado para cumplir con la ley, enforzar nuestras políticas del sitio, o proteger la nuestra u otros derechos, propiedad, o seguridad. De todas formas, la información del visitante autorizado no-personal puede proveerse a otras partes por marketing, publicidad, u otros usos.
+
+
Enlaces de terceras partes
+
+
Ocasionalmente, a nuestra discreción, puede que incluyamos u ofrezcamos productos de terceras partes o servicios en nuestro sitio. Estas terceras partes tienen políticas de privacidad separadas e independientes. Por lo tanto no tenemos responsabilidad u obligación por el contenido y actividades de estos sitios enlazados. Sin embargo, buscamos proteger la integridad de nuestro sitio y dar la bienvenida a cualquier ayuda sobre estos sitios.
+
+
Children's Online Privacy Protection Act Compliance (Cumplimiento de la Ley de la Protección Privada en Línea del Niño)
+
+
Nuestro sitio y todos nuestros productos y servicios están dirigidos a gente que tiene al menos 13 años de edad. Si el servidor está alojado en EE.UU, y tienes menos de 13 años, no uses este sitio por los requerimientos del COPPA (Children's Online Privacy Protection Act).
+
+
Solo Políticas de Privacidad en Línea
+
+
Estas políticas de privacidad aplican únicamente a la información recolectada a través de nuestro sitio y no a información recolectada offline.
+
+
Tu Consentimiento
+
+
Al usar nuestro sitio, estás consentido a nuestras políticas de privacidad del sitio.
+
+
Cambios a nuestras Políticas de Privacidad
+
+
Si decidimos cambiar nuestras políticas de privacidad, las publicaremos en esta página.
+
+
Este documento está publicado bajo la licencia CC-BY-SA. Última vez actualizado el 31 de Mayo del 2013.
+ title: "Términos del Servicio y Políticas de Privacidad de %{instance}"
time:
formats:
- default: "%b %d, %Y, %H:%M"
+ default: "%d de %b del %Y, %H:%M"
two_factor_authentication:
- description_html: Sí habilitas la autenticación de dos factores, se requerirá estar en posesión de su teléfono, lo que generará tokens para que usted pueda iniciar sesión.
+ generate_recovery_codes: generar códigos de recuperación
+ lost_recovery_codes: Los códigos de recuperación te permiten obtener acceso a tu cuenta si pierdes tu teléfono. Si has perdido tus códigos de recuperación, puedes regenerarlos aquí. Tus viejos códigos de recuperación se harán inválidos.
+ recovery_codes: Hacer copias de seguridad de tus códigos de recuperación
+ recovery_instructions_html: Si pierdes acceso a tu teléfono, puedes usar uno de los siguientes códigos de recuperación para obtener acceso a tu cuenta. Mantenlos a salvo. Por ejemplo, puedes imprimirlos y guardarlos con otros documentos importantes.
+ description_html: Si habilitas la autenticación de dos factores, se requerirá estar en posesión de su teléfono, lo que generará tokens para que usted pueda iniciar sesión.
disable: Deshabilitar
enable: Habilitar
+ enabled_success: Verificación de dos factores activada exitosamente
instructions_html: "Escanea este código QR desde Google Authenticator o una aplicación similar en su teléfono. Desde ahora, esta aplicación va a generar tokens que tienes que ingresar cuando quieras iniciar sesión."
+ code_hint: Ingresa el código generado por tu aplicación de autenticación para confirmar
+ setup: Configurar
+ wrong_code: ¡El código ingresado es inválido! ¿El dispositivo y tiempo del servidor están correctos?
users:
invalid_email: La dirección de correo es incorrecta
invalid_otp_token: Código de dos factores incorrecto
+ signed_in_as: "Sesión iniciada como:"
diff --git a/config/locales/simple_form.es.yml b/config/locales/simple_form.es.yml
index f260e600c..a6185915e 100644
--- a/config/locales/simple_form.es.yml
+++ b/config/locales/simple_form.es.yml
@@ -4,12 +4,21 @@ es:
hints:
defaults:
avatar: PNG, GIF o JPG. Máximo 2MB. Será escalado a 120x120px
- display_name: Máximo 30 caracteres
+ display_name:
+ one: 1 caracter restante
+ other: %{count} caracteres restantes
header: PNG, GIF o JPG. Máximo 2MB. Será escalado a 700x335px
locked: Requiere que manualmente apruebes seguidores y las publicaciones serán mostradas solamente a tus seguidores
- note: Máximo 160 caracteres
+ note:
+ one: 1 caracter restante
+ other: %{count} caracteres restantes
+ setting_noindex: Afecta a tu perfil público y páginas de estado
imports:
data: Archivo CSV exportado desde otra instancia de Mastodon
+ sessions:
+ otp: Ingresa el código de autenticación de dos factores de tu teléfono o usa uno de tus códigos de recuperación.
+ user:
+ filtered_languages: Los lenguajes seleccionados serán removidos de tus líneas de tiempo públicas.
labels:
defaults:
avatar: Avatar
--
cgit
From 81cec35dbf1b348d23363559e3f4e6b1ec3415c5 Mon Sep 17 00:00:00 2001
From: Eugen Rochko
Date: Tue, 19 Sep 2017 02:42:40 +0200
Subject: Custom emoji (#4988)
* Custom emoji
- In OStatus: ``
- In ActivityPub: `{ type: "Emoji", name: ":coolcat:", href: "http://..." }`
- In REST API: Status object includes `emojis` array (`shortcode`, `url`)
- Domain blocks with reject media stop emojis
- Emoji file up to 50KB
- Web UI handles custom emojis
- Static pages render custom emojis as `` tags
Side effects:
- Undo #4500 optimization, as I needed to modify it to restore
shortcode handling in emojify()
- Formatter#plaintext should now make sure stripped out line-breaks
and paragraphs are replaced with newlines
* Fix emoji at the start not being converted
---
app/javascript/mastodon/emoji.js | 60 ++++++++++------
app/javascript/mastodon/reducers/statuses.js | 9 ++-
app/lib/activitypub/activity/create.rb | 13 ++++
app/lib/formatter.rb | 54 +++++++++++++-
app/lib/ostatus/activity/creation.rb | 20 ++++++
app/lib/ostatus/atom_serializer.rb | 4 ++
app/models/custom_emoji.rb | 38 ++++++++++
app/models/status.rb | 4 ++
app/serializers/activitypub/note_serializer.rb | 20 +++++-
app/serializers/rest/status_serializer.rb | 11 +++
.../stream_entries/_detailed_status.html.haml | 2 +-
app/views/stream_entries/_simple_status.html.haml | 2 +-
db/migrate/20170917153509_create_custom_emojis.rb | 13 ++++
db/schema.rb | 14 +++-
spec/fabricators/custom_emoji_fabricator.rb | 5 ++
spec/fixtures/files/emojo.png | Bin 0 -> 29814 bytes
spec/lib/activitypub/activity/create_spec.rb | 25 +++++++
spec/lib/formatter_spec.rb | 78 +++++++++++++++++++++
spec/lib/ostatus/atom_serializer_spec.rb | 16 ++++-
spec/models/custom_emoji_spec.rb | 25 +++++++
20 files changed, 382 insertions(+), 31 deletions(-)
create mode 100644 app/models/custom_emoji.rb
create mode 100644 db/migrate/20170917153509_create_custom_emojis.rb
create mode 100644 spec/fabricators/custom_emoji_fabricator.rb
create mode 100644 spec/fixtures/files/emojo.png
create mode 100644 spec/models/custom_emoji_spec.rb
(limited to 'app/views')
diff --git a/app/javascript/mastodon/emoji.js b/app/javascript/mastodon/emoji.js
index a41dfdd1d..865b85b61 100644
--- a/app/javascript/mastodon/emoji.js
+++ b/app/javascript/mastodon/emoji.js
@@ -3,28 +3,48 @@ import Trie from 'substring-trie';
const trie = new Trie(Object.keys(unicodeMapping));
-const emojify = str => {
- let rtn = '';
- for (;;) {
- let match, i = 0;
- while (i < str.length && str[i] !== '<' && !(match = trie.search(str.slice(i)))) {
- i += str.codePointAt(i) < 65536 ? 1 : 2;
- }
- if (i === str.length)
- break;
- else if (str[i] === '<') {
- let tagend = str.indexOf('>', i + 1) + 1;
- if (!tagend)
- break;
- rtn += str.slice(0, tagend);
- str = str.slice(tagend);
- } else {
- const [filename, shortCode] = unicodeMapping[match];
- rtn += str.slice(0, i) + ``;
- str = str.slice(i + match.length);
+const emojify = (str, customEmojis = {}) => {
+ // This walks through the string from start to end, ignoring any tags (
, , etc.)
+ // and replacing valid unicode strings
+ // that _aren't_ within tags with an version.
+ // The goal is to be the same as an emojione.regUnicode replacement, but faster.
+ let i = -1;
+ let insideTag = false;
+ let insideShortname = false;
+ let shortnameStartIndex = -1;
+ let match;
+ while (++i < str.length) {
+ const char = str.charAt(i);
+ if (insideShortname && char === ':') {
+ const shortname = str.substring(shortnameStartIndex, i + 1);
+ if (shortname in customEmojis) {
+ const replacement = ``;
+ str = str.substring(0, shortnameStartIndex) + replacement + str.substring(i + 1);
+ i += (replacement.length - shortname.length - 1); // jump ahead the length we've added to the string
+ } else {
+ i--;
+ }
+ insideShortname = false;
+ } else if (insideTag && char === '>') {
+ insideTag = false;
+ } else if (char === '<') {
+ insideTag = true;
+ insideShortname = false;
+ } else if (!insideTag && char === ':') {
+ insideShortname = true;
+ shortnameStartIndex = i;
+ } else if (!insideTag && (match = trie.search(str.substring(i)))) {
+ const unicodeStr = match;
+ if (unicodeStr in unicodeMapping) {
+ const [filename, shortCode] = unicodeMapping[unicodeStr];
+ const alt = unicodeStr;
+ const replacement = ``;
+ str = str.substring(0, i) + replacement + str.substring(i + unicodeStr.length);
+ i += (replacement.length - unicodeStr.length); // jump ahead the length we've added to the string
+ }
}
}
- return rtn + str;
+ return str;
};
export default emojify;
diff --git a/app/javascript/mastodon/reducers/statuses.js b/app/javascript/mastodon/reducers/statuses.js
index 7f906bef6..38b23504e 100644
--- a/app/javascript/mastodon/reducers/statuses.js
+++ b/app/javascript/mastodon/reducers/statuses.js
@@ -58,9 +58,14 @@ const normalizeStatus = (state, status) => {
}
const searchContent = [status.spoiler_text, status.content].join(' ').replace(/ /g, '\n').replace(/<\/p>
/g, '\n\n');
+ const emojiMap = normalStatus.emojis.reduce((obj, emoji) => {
+ obj[`:${emoji.shortcode}:`] = emoji.url;
+ return obj;
+ }, {});
+
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
- normalStatus.contentHtml = emojify(normalStatus.content);
- normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''));
+ normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
+ normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(normalStatus.spoiler_text || ''), emojiMap);
return state.update(status.id, ImmutableMap(), map => map.mergeDeep(fromJS(normalStatus)));
};
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 894759d9a..41f2b0bad 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -61,6 +61,8 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
process_hashtag tag, status
when 'Mention'
process_mention tag, status
+ when 'Emoji'
+ process_emoji tag, status
end
end
end
@@ -79,6 +81,17 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
account.mentions.create(status: status)
end
+ def process_emoji(tag, _status)
+ shortcode = tag['name'].delete(':')
+ emoji = CustomEmoji.find_by(shortcode: shortcode, domain: @account.domain)
+
+ return if !emoji.nil? || skip_download?
+
+ emoji = CustomEmoji.new(domain: @account.domain, shortcode: shortcode)
+ emoji.image_remote_url = tag['href']
+ emoji.save
+ end
+
def process_attachments(status)
return unless @object['attachment'].is_a?(Array)
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 575830190..29fea27de 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -9,7 +9,7 @@ class Formatter
include ActionView::Helpers::TextHelper
- def format(status)
+ def format(status, options = {})
if status.reblog?
prepend_reblog = status.reblog.account.acct
status = status.proper
@@ -19,7 +19,11 @@ class Formatter
raw_content = status.text
- return reformat(raw_content) unless status.local?
+ unless status.local?
+ html = reformat(raw_content)
+ html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify]
+ return html
+ end
linkable_accounts = status.mentions.map(&:account)
linkable_accounts << status.account
@@ -27,6 +31,7 @@ class Formatter
html = raw_content
html = "RT @#{prepend_reblog} #{html}" if prepend_reblog
html = encode_and_link_urls(html, linkable_accounts)
+ html = encode_custom_emojis(html, status.emojis) if options[:custom_emojify]
html = simple_format(html, {}, sanitize: false)
html = html.delete("\n")
@@ -39,7 +44,9 @@ class Formatter
def plaintext(status)
return status.text if status.local?
- strip_tags(status.text)
+
+ text = status.text.gsub(/( | |<\/p>)+/) { |match| "#{match}\n" }
+ strip_tags(text)
end
def simplified_format(account)
@@ -76,6 +83,47 @@ class Formatter
end
end
+ def encode_custom_emojis(html, emojis)
+ return html if emojis.empty?
+
+ emoji_map = emojis.map { |e| [e.shortcode, full_asset_url(e.image.url)] }.to_h
+
+ i = -1
+ inside_tag = false
+ inside_shortname = false
+ shortname_start_index = -1
+
+ while i + 1 < html.size
+ i += 1
+
+ if inside_shortname && html[i] == ':'
+ shortcode = html[shortname_start_index + 1..i - 1]
+ emoji = emoji_map[shortcode]
+
+ if emoji
+ replacement = ""
+ before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : ''
+ html = before_html + replacement + html[i + 1..-1]
+ i += replacement.size - (shortcode.size + 2) - 1
+ else
+ i -= 1
+ end
+
+ inside_shortname = false
+ elsif inside_tag && html[i] == '>'
+ inside_tag = false
+ elsif html[i] == '<'
+ inside_tag = true
+ inside_shortname = false
+ elsif !inside_tag && html[i] == ':'
+ inside_shortname = true
+ shortname_start_index = i
+ end
+ end
+
+ html
+ end
+
def rewrite(text, entities)
chars = text.to_s.to_char_a
diff --git a/app/lib/ostatus/activity/creation.rb b/app/lib/ostatus/activity/creation.rb
index 1a23c9efa..d3f1629c4 100644
--- a/app/lib/ostatus/activity/creation.rb
+++ b/app/lib/ostatus/activity/creation.rb
@@ -42,6 +42,7 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
save_mentions(status)
save_hashtags(status)
save_media(status)
+ save_emojis(status)
end
if thread? && status.thread.nil?
@@ -150,6 +151,25 @@ class OStatus::Activity::Creation < OStatus::Activity::Base
end
end
+ def save_emojis(parent)
+ do_not_download = DomainBlock.find_by(domain: parent.account.domain)&.reject_media?
+
+ return if do_not_download
+
+ @xml.xpath('./xmlns:link[@rel="emoji"]', xmlns: TagManager::XMLNS).each do |link|
+ next unless link['href'] && link['name']
+
+ shortcode = link['name'].delete(':')
+ emoji = CustomEmoji.find_by(shortcode: shortcode, domain: parent.account.domain)
+
+ next unless emoji.nil?
+
+ emoji = CustomEmoji.new(shortcode: shortcode, domain: parent.account.domain)
+ emoji.image_remote_url = link['href']
+ emoji.save
+ end
+ end
+
def account_from_href(href)
url = Addressable::URI.parse(href).normalize
diff --git a/app/lib/ostatus/atom_serializer.rb b/app/lib/ostatus/atom_serializer.rb
index b8e22a381..a6a5cb0c4 100644
--- a/app/lib/ostatus/atom_serializer.rb
+++ b/app/lib/ostatus/atom_serializer.rb
@@ -368,5 +368,9 @@ class OStatus::AtomSerializer
end
append_element(entry, 'mastodon:scope', status.visibility)
+
+ status.emojis.each do |emoji|
+ append_element(entry, 'link', nil, rel: :emoji, href: full_asset_url(emoji.image.url), name: emoji.shortcode)
+ end
end
end
diff --git a/app/models/custom_emoji.rb b/app/models/custom_emoji.rb
new file mode 100644
index 000000000..f4d3b16a0
--- /dev/null
+++ b/app/models/custom_emoji.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+# == Schema Information
+#
+# Table name: custom_emojis
+#
+# id :integer not null, primary key
+# shortcode :string default(""), not null
+# domain :string
+# image_file_name :string
+# image_content_type :string
+# image_file_size :integer
+# image_updated_at :datetime
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class CustomEmoji < ApplicationRecord
+ SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
+
+ SCAN_RE = /(?<=[^[:alnum:]:]|\n|^)
+ :(#{SHORTCODE_RE_FRAGMENT}):
+ (?=[^[:alnum:]:]|$)/x
+
+ has_attached_file :image
+
+ validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes }
+ validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 }
+
+ include Remotable
+
+ class << self
+ def from_text(text, domain)
+ return [] if text.blank?
+ shortcodes = text.scan(SCAN_RE).map(&:first)
+ where(shortcode: shortcodes, domain: domain)
+ end
+ end
+end
diff --git a/app/models/status.rb b/app/models/status.rb
index 2a2cdcf6e..326d128d6 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -131,6 +131,10 @@ class Status < ApplicationRecord
!sensitive? && media_attachments.any?
end
+ def emojis
+ CustomEmoji.from_text(text, account.domain)
+ end
+
after_create :store_uri, if: :local?
before_validation :prepare_contents, if: :local?
diff --git a/app/serializers/activitypub/note_serializer.rb b/app/serializers/activitypub/note_serializer.rb
index 166214eee..e5d8e3f03 100644
--- a/app/serializers/activitypub/note_serializer.rb
+++ b/app/serializers/activitypub/note_serializer.rb
@@ -57,7 +57,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
end
def virtual_tags
- object.mentions + object.tags
+ object.mentions + object.tags + object.emojis
end
def atom_uri
@@ -137,4 +137,22 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer
"##{object.name}"
end
end
+
+ class CustomEmojiSerializer < ActiveModel::Serializer
+ include RoutingHelper
+
+ attributes :type, :href, :name
+
+ def type
+ 'Emoji'
+ end
+
+ def href
+ full_asset_url(object.image.url)
+ end
+
+ def name
+ ":#{object.shortcode}:"
+ end
+ end
end
diff --git a/app/serializers/rest/status_serializer.rb b/app/serializers/rest/status_serializer.rb
index 298a3bb40..d8efa8e60 100644
--- a/app/serializers/rest/status_serializer.rb
+++ b/app/serializers/rest/status_serializer.rb
@@ -17,6 +17,7 @@ class REST::StatusSerializer < ActiveModel::Serializer
has_many :media_attachments, serializer: REST::MediaAttachmentSerializer
has_many :mentions
has_many :tags
+ has_many :emojis
def current_user?
!current_user.nil?
@@ -106,4 +107,14 @@ class REST::StatusSerializer < ActiveModel::Serializer
tag_url(object)
end
end
+
+ class CustomEmojiSerializer < ActiveModel::Serializer
+ include RoutingHelper
+
+ attributes :shortcode, :url
+
+ def url
+ full_asset_url(object.image.url)
+ end
+ end
end
diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml
index dd9456260..692d5a6d5 100644
--- a/app/views/stream_entries/_detailed_status.html.haml
+++ b/app/views/stream_entries/_detailed_status.html.haml
@@ -17,7 +17,7 @@
%p{ style: 'margin-bottom: 0' }<
%span.p-summary> #{status.spoiler_text}
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
- .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status)
+ .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true)
- if !status.media_attachments.empty?
- if status.media_attachments.first.video?
diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml
index 55aa97f32..f9a530d38 100644
--- a/app/views/stream_entries/_simple_status.html.haml
+++ b/app/views/stream_entries/_simple_status.html.haml
@@ -18,7 +18,7 @@
%p{ style: 'margin-bottom: 0' }<
%span.p-summary> #{status.spoiler_text}
%a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more')
- .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status)
+ .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true)
- unless status.media_attachments.empty?
- if status.media_attachments.first.video?
diff --git a/db/migrate/20170917153509_create_custom_emojis.rb b/db/migrate/20170917153509_create_custom_emojis.rb
new file mode 100644
index 000000000..4040c8312
--- /dev/null
+++ b/db/migrate/20170917153509_create_custom_emojis.rb
@@ -0,0 +1,13 @@
+class CreateCustomEmojis < ActiveRecord::Migration[5.1]
+ def change
+ create_table :custom_emojis do |t|
+ t.string :shortcode, null: false, default: ''
+ t.string :domain
+ t.attachment :image
+
+ t.timestamps
+ end
+
+ add_index :custom_emojis, [:shortcode, :domain], unique: true
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index f2ca2af69..9f42d46dd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170913000752) do
+ActiveRecord::Schema.define(version: 20170917153509) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -89,6 +89,18 @@ ActiveRecord::Schema.define(version: 20170913000752) do
t.index ["uri"], name: "index_conversations_on_uri", unique: true
end
+ create_table "custom_emojis", force: :cascade do |t|
+ t.string "shortcode", default: "", null: false
+ t.string "domain"
+ t.string "image_file_name"
+ t.string "image_content_type"
+ t.integer "image_file_size"
+ t.datetime "image_updated_at"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["shortcode", "domain"], name: "index_custom_emojis_on_shortcode_and_domain", unique: true
+ end
+
create_table "domain_blocks", id: :serial, force: :cascade do |t|
t.string "domain", default: "", null: false
t.datetime "created_at", null: false
diff --git a/spec/fabricators/custom_emoji_fabricator.rb b/spec/fabricators/custom_emoji_fabricator.rb
new file mode 100644
index 000000000..18a7d23dc
--- /dev/null
+++ b/spec/fabricators/custom_emoji_fabricator.rb
@@ -0,0 +1,5 @@
+Fabricator(:custom_emoji) do
+ shortcode 'coolcat'
+ domain nil
+ image { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) }
+end
diff --git a/spec/fixtures/files/emojo.png b/spec/fixtures/files/emojo.png
new file mode 100644
index 000000000..cb5993499
Binary files /dev/null and b/spec/fixtures/files/emojo.png differ
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index fcb044ebc..1a9520f04 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe ActivityPub::Activity::Create do
before do
stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
+ stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png'))
end
describe '#perform' do
@@ -217,5 +218,29 @@ RSpec.describe ActivityPub::Activity::Create do
expect(status.tags.map(&:name)).to include('test')
end
end
+
+ context 'with emojis' do
+ let(:object_json) do
+ {
+ id: 'bar',
+ type: 'Note',
+ content: 'Lorem ipsum :tinking:',
+ tag: [
+ {
+ type: 'Emoji',
+ href: 'http://example.com/emoji.png',
+ name: 'tinking',
+ },
+ ],
+ }
+ end
+
+ it 'creates status' do
+ status = sender.statuses.first
+
+ expect(status).to_not be_nil
+ expect(status.emojis.map(&:shortcode)).to include('tinking')
+ end
+ end
end
end
diff --git a/spec/lib/formatter_spec.rb b/spec/lib/formatter_spec.rb
index b714b317a..71b6b78d2 100644
--- a/spec/lib/formatter_spec.rb
+++ b/spec/lib/formatter_spec.rb
@@ -223,6 +223,45 @@ RSpec.describe Formatter do
include_examples 'encode and link URLs'
end
+
+ context 'with custom_emojify option' do
+ let!(:emoji) { Fabricate(:custom_emoji) }
+ let(:status) { Fabricate(:status, account: local_account, text: text) }
+
+ subject { Formatter.instance.format(status, custom_emojify: true) }
+
+ context 'with emoji at the start' do
+ let(:text) { ':coolcat: Beep boop' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/
:coolcat: Beep boop ' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/
Beep :coolcat: boop
' }
+
+ it 'converts shortcode to image tag' do
+ is_expected.to match(/Beep :coolcat::coolcat:
' }
+
+ it 'does not touch the shortcodes' do
+ is_expected.to match(/
:coolcat::coolcat:<\/p>/)
+ end
+ end
+
+ context 'with emoji at the end' do
+ let(:text) { '