about summary refs log tree commit diff
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/application.rb15
-rw-r--r--config/environments/production.rb9
-rw-r--r--config/initializers/open_uri_redirection.rb8
-rw-r--r--config/initializers/paperclip.rb7
-rw-r--r--config/initializers/rabl_init.rb2
-rw-r--r--config/initializers/rack-attack.rb4
-rw-r--r--config/initializers/timeout.rb4
-rw-r--r--config/locales/de.yml3
-rw-r--r--config/locales/devise.fr.yml1
-rw-r--r--config/locales/devise.zh-CN.yml61
-rw-r--r--config/locales/doorkeeper.en.yml3
-rw-r--r--config/locales/doorkeeper.fr.yml7
-rw-r--r--config/locales/en.yml49
-rw-r--r--config/locales/es.yml16
-rw-r--r--config/locales/fr.yml151
-rw-r--r--config/locales/hu.yml6
-rw-r--r--config/locales/pt.yml4
-rw-r--r--config/locales/simple_form.en.yml5
-rw-r--r--config/locales/simple_form.fr.yml18
-rw-r--r--config/locales/simple_form.zh-CN.yml42
-rw-r--r--config/locales/uk.yml6
-rw-r--r--config/locales/zh-CN.yml154
-rw-r--r--config/navigation.rb4
-rw-r--r--config/routes.rb21
-rw-r--r--config/settings.yml1
25 files changed, 512 insertions, 89 deletions
diff --git a/config/application.rb b/config/application.rb
index 8da5ade3c..9d32f30cb 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -2,12 +2,14 @@ require_relative 'boot'
 
 require 'rails/all'
 
-require_relative '../app/lib/exceptions'
-
 # Require the gems listed in Gemfile, including any gems
 # you've limited to :test, :development, or :production.
 Bundler.require(*Rails.groups)
 
+require_relative '../app/lib/exceptions'
+require_relative '../lib/paperclip/gif_transcoder'
+require_relative '../lib/paperclip/video_transcoder'
+
 Dotenv::Railtie.load
 
 module Mastodon
@@ -22,7 +24,7 @@ module Mastodon
 
     # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
     # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
-    config.i18n.available_locales = [:en, :de, :es, :pt, :fr, :hu, :uk]
+    config.i18n.available_locales = [:en, :de, :es, :pt, :fr, :hu, :uk, 'zh-CN']
     config.i18n.default_locale    = :en
 
     # config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
@@ -49,12 +51,5 @@ module Mastodon
       Doorkeeper::AuthorizedApplicationsController.layout 'admin'
       Doorkeeper::Application.send :include, ApplicationExtension
     end
-
-    config.action_dispatch.default_headers = {
-      'Server'                 => 'Mastodon',
-      'X-Frame-Options'        => 'DENY',
-      'X-Content-Type-Options' => 'nosniff',
-      'X-XSS-Protection'       => '1; mode=block',
-    }
   end
 end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 62ea217ef..dc5dd4afd 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -43,7 +43,7 @@ Rails.application.configure do
   config.log_level = :debug
 
   # Prepend all log lines with the following tags.
-  config.log_tags = [ :request_id ]
+  config.log_tags = [:request_id]
 
   # Use a different logger for distributed setups.
   # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
@@ -109,4 +109,11 @@ Rails.application.configure do
   config.to_prepare do
     StatsD.backend = StatsD::Instrument::Backends::NullBackend.new if ENV['STATSD_ADDR'].blank?
   end
+
+  config.action_dispatch.default_headers = {
+    'Server'                 => 'Mastodon',
+    'X-Frame-Options'        => 'DENY',
+    'X-Content-Type-Options' => 'nosniff',
+    'X-XSS-Protection'       => '1; mode=block',
+  }
 end
diff --git a/config/initializers/open_uri_redirection.rb b/config/initializers/open_uri_redirection.rb
new file mode 100644
index 000000000..e24fdecab
--- /dev/null
+++ b/config/initializers/open_uri_redirection.rb
@@ -0,0 +1,8 @@
+require 'open-uri'
+
+module OpenURI
+  def OpenURI.redirectable?(uri1, uri2) # :nodoc:
+    uri1.scheme.downcase == uri2.scheme.downcase ||
+      (/\A(?:http|https|ftp)\z/i =~ uri1.scheme && /\A(?:http|https|ftp)\z/i =~ uri2.scheme)
+  end
+end
diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb
index 71a7b514e..2a2ef8fea 100644
--- a/config/initializers/paperclip.rb
+++ b/config/initializers/paperclip.rb
@@ -2,11 +2,16 @@
 
 Paperclip.options[:read_timeout] = 60
 
+Paperclip.interpolates :filename do |attachment, style|
+  return attachment.original_filename if style == :original
+  [basename(attachment, style), extension(attachment, style)].delete_if(&:empty?).join('.')
+end
+
 if ENV['S3_ENABLED'] == 'true'
   Aws.eager_autoload!(services: %w(S3))
 
   Paperclip::Attachment.default_options[:storage]        = :s3
-  Paperclip::Attachment.default_options[:s3_protocol]    = 'https'
+  Paperclip::Attachment.default_options[:s3_protocol]    = ENV.fetch('S3_PROTOCOL') { 'https' }
   Paperclip::Attachment.default_options[:url]            = ':s3_domain_url'
   Paperclip::Attachment.default_options[:s3_host_name]   = ENV.fetch('S3_HOSTNAME') { "s3-#{ENV.fetch('S3_REGION')}.amazonaws.com" }
   Paperclip::Attachment.default_options[:path]           = '/:class/:attachment/:id_partition/:style/:filename'
diff --git a/config/initializers/rabl_init.rb b/config/initializers/rabl_init.rb
index 325bf0c78..f7be0c607 100644
--- a/config/initializers/rabl_init.rb
+++ b/config/initializers/rabl_init.rb
@@ -1,6 +1,6 @@
 Rabl.configure do |config|
   config.cache_all_output  = false
-  config.cache_sources     = !!Rails.env.production?
+  config.cache_sources     = Rails.env.production?
   config.include_json_root = false
   config.view_paths        = [Rails.root.join('app/views')]
 end
diff --git a/config/initializers/rack-attack.rb b/config/initializers/rack-attack.rb
index 3f0ee1d7a..70f7846d1 100644
--- a/config/initializers/rack-attack.rb
+++ b/config/initializers/rack-attack.rb
@@ -1,6 +1,6 @@
 class Rack::Attack
   # Rate limits for the API
-  throttle('api', limit: 150, period: 5.minutes) do |req|
+  throttle('api', limit: 300, period: 5.minutes) do |req|
     req.ip if req.path.match(/\A\/api\/v/)
   end
 
@@ -11,7 +11,7 @@ class Rack::Attack
     headers = {
       'X-RateLimit-Limit'     => match_data[:limit].to_s,
       'X-RateLimit-Remaining' => '0',
-      'X-RateLimit-Reset'     => (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6)
+      'X-RateLimit-Reset'     => (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6),
     }
 
     [429, headers, [{ error: 'Throttled' }.to_json]]
diff --git a/config/initializers/timeout.rb b/config/initializers/timeout.rb
index 06a29492e..de87fd906 100644
--- a/config/initializers/timeout.rb
+++ b/config/initializers/timeout.rb
@@ -1,4 +1,6 @@
+Rack::Timeout::Logger.disable
+Rack::Timeout.service_timeout = false
+
 if Rails.env.production?
   Rack::Timeout.service_timeout = 90
-  Rack::Timeout::Logger.disable
 end
diff --git a/config/locales/de.yml b/config/locales/de.yml
index f36cc64c8..320bd3144 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1,7 +1,6 @@
 ---
 de:
   about:
-    about_instance: "<em>%{instance}</em> ist eine Instanz von Mastodon."
     about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Eine <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen, verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
     get_started: Erste Schritte
     source_code: Quellcode
@@ -82,8 +81,6 @@ de:
     preferences: Einstellungen
   stream_entries:
     click_to_show: Klicken um zu zeigen
-    favourited: favorisierte einen Beitrag von
-    is_now_following: folgt nun
     reblogged: teilte
     sensitive_content: Sensible Inhalte
   time:
diff --git a/config/locales/devise.fr.yml b/config/locales/devise.fr.yml
index b64601e7b..ce44d041a 100644
--- a/config/locales/devise.fr.yml
+++ b/config/locales/devise.fr.yml
@@ -58,3 +58,4 @@ fr:
       not_locked: n'était pas verrouillé(e)
       not_saved:
         one: '1 erreur a empêché ce(tte) %{resource} d''être sauvegardé(e) :'
+        other: '%{count} erreurs ont empêché ce(tte) %{resource} d''être sauvegardé(e): '
diff --git a/config/locales/devise.zh-CN.yml b/config/locales/devise.zh-CN.yml
new file mode 100644
index 000000000..398055b36
--- /dev/null
+++ b/config/locales/devise.zh-CN.yml
@@ -0,0 +1,61 @@
+---
+zh-CN:
+  devise:
+    confirmations:
+      confirmed: 邮件已确认。
+      send_instructions: 发送确认邮件
+      send_paranoid_instructions: 发送确认邮件
+    failure:
+      already_authenticated: 已登录。
+      inactive: 账号未激活。
+      invalid: 激活码 %{authentication_keys} 或密码无效。
+      last_attempt: 因多次失败账号已锁。
+      locked: 账号已锁。
+      not_found_in_database: 激活码 %{authentication_keys} 或密码无效。
+      timeout: 登录已过期,请重新登录。
+      unauthenticated: 请先登录
+      unconfirmed: 请先通过邮件激活。
+    mailer:
+      confirmation_instructions:
+        subject: 'Mastodon: 激活指引'
+      password_change:
+        subject: 'Mastodon: 密码变更'
+      reset_password_instructions:
+        subject: 'Mastodon: 密码重置指引'
+      unlock_instructions:
+        subject: 'Mastodon: 账号解锁指引'
+    omniauth_callbacks:
+      failure: 从 %{kind} 授权失败:"%{reason}" 。
+      success: 成功从 %{kind} 授权。
+    passwords:
+      no_token: 仅允许通过密码重置邮件访问本页面,或确认完整 URL。
+      send_instructions: 你将收到密码重置指引邮件。
+      send_paranoid_instructions: 你将收到密码重置邮件。
+      updated: 密码重置成功。
+      updated_not_active: 密码重置成功。
+    registrations:
+      destroyed: 撒油娜啦!账号已经注销。有缘再会。
+      signed_up: 欢迎回来!
+      signed_up_but_inactive: 账号未激活。
+      signed_up_but_locked: 账号已锁定。
+      signed_up_but_unconfirmed: 确认邮件已发,请先激活。
+      update_needs_confirmation: 账号需要重新激活,请先激活。
+      updated: 更新成功。
+    sessions:
+      already_signed_out: 登出成功。
+      signed_in: 登录成功。
+      signed_out: 登出成功。
+    unlocks:
+      send_instructions: 解锁邮件已发,请先解锁。
+      send_paranoid_instructions: 解锁邮件已发,请先解锁。
+      unlocked: 账号已解锁,请登录。
+  errors:
+    messages:
+      already_confirmed: 已激活,请登录。
+      confirmation_period_expired: 需要在 %{period} 内激活,请重新申请。
+      expired: 已过期,请重新申请。
+      not_found: 未发现
+      not_locked: 未锁定
+      not_saved:
+        one: '保存失败: %{resource}'
+        other: "保存失败:%{count}"
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
index aaf5df6fc..6412b8b48 100644
--- a/config/locales/doorkeeper.en.yml
+++ b/config/locales/doorkeeper.en.yml
@@ -65,8 +65,9 @@ en:
         revoke: Are you sure?
       index:
         application: Application
-        created_at: Created At
+        created_at: Authorized
         date_format: "%Y-%m-%d %H:%M:%S"
+        scopes: Scopes
         title: Your authorized applications
     errors:
       messages:
diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml
index 6f3c0864a..c94e5c095 100644
--- a/config/locales/doorkeeper.fr.yml
+++ b/config/locales/doorkeeper.fr.yml
@@ -54,7 +54,7 @@ fr:
         title: Une erreur est survenue
       new:
         able_to: Cette application pourra
-        prompt: Autorisez %{client_name} à utiliser votre compte?
+        prompt: Autoriser %{client_name} à utiliser votre compte?
         title: Autorisation requise
       show:
         title: Code d'autorisation
@@ -66,7 +66,8 @@ fr:
       index:
         application: Application
         created_at: Créé le
-        date_format: "%Y-%m-%d %H:%M:%S"
+        date_format: "%d-%m-%Y %H:%M:%S"
+        scopes: permissions
         title: Vos applications autorisées
     errors:
       messages:
@@ -80,7 +81,7 @@ fr:
         invalid_scope: La portée demandée n'est pas valide, est inconnue, ou est mal formée.
         invalid_token:
           expired: Le jeton d'accès a expiré
-          revoked: Le jeton d'accès a été annulé
+          revoked: Le jeton d'accès a été révoqué
           unknown: Le jeton d'accès n'est pas valide
         resource_owner_authenticator_not_configured: La recherche du propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_authenticator n'est pas configuré.
         server_error: Le serveur d'autorisation a rencontré une condition inattendue qui l'a empêché de remplir la demande.
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e7d39327e..157f107a5 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,14 +1,25 @@
 ---
 en:
   about:
-    about_instance: "<em>%{instance}</em> is a Mastodon instance."
-    about_mastodon: Mastodon is a <em>free, open-source</em> social network server. A <em>decentralized</em> alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Anyone can run Mastodon and participate in the <em>social network</em> seamlessly.
+    about_mastodon: Mastodon is a <em>free, open-source</em> social network. A <em>decentralized</em> alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust &mdash; whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the <em>social network</em> seamlessly.
+    about_this: About this instance
+    apps: Apps
     business_email: 'Business e-mail:'
     contact: Contact
+    description_headline: What is %{domain}?
     domain_count_after: other instances
     domain_count_before: Connected to
+    features:
+      api: Open API for apps and services
+      blocks: Rich block and muting tools
+      characters: 500 characters per post
+      chronology: Timelines are chronological
+      ethics: 'Ethical design: no ads, no tracking'
+      gifv: GIFV sets and short videos
+      privacy: Granular, per-post privacy settings
+      public: Public timelines
+    features_headline: What sets Mastodon apart
     get_started: Get started
-    learn_more: Learn more
     links: Links
     other_instances: Other instances
     source_code: Source code
@@ -28,7 +39,9 @@ en:
     remote_follow: Remote follow
     unfollow: Unfollow
   application_mailer:
+    settings: 'Change e-mail preferences: %{link}'
     signature: Mastodon notifications from %{instance}
+    view: 'View:'
   applications:
     invalid_url: The provided URL is invalid
   auth:
@@ -60,6 +73,11 @@ en:
       x_minutes: "%{count}m"
       x_months: "%{count}mo"
       x_seconds: "%{count}s"
+  exports:
+    blocks: You block
+    csv: CSV
+    follows: You follow
+    storage: Media storage
   generic:
     changes_saved_msg: Changes successfully saved!
     powered_by: powered by %{link}
@@ -67,7 +85,24 @@ en:
     validation_errors:
       one: Something isn't quite right yet! Please review the error below
       other: Something isn't quite right yet! Please review %{count} errors below
+  imports:
+    preface: You can import certain data like all the people you are following or blocking into your account on this instance, from files created by an export on another instance.
+    success: Your data was successfully uploaded and will now be processed in due time
+    types:
+      blocking: Blocking list
+      following: Following list
+    upload: Upload
+  landing_strip_html: <strong>%{name}</strong> is a user on <strong>%{domain}</strong>. You can follow them or interact with them if you have an account anywhere in the fediverse. If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
   notification_mailer:
+    digest:
+      body: 'Here is a brief summary of what you missed on %{instance} since your last visit on %{since}:'
+      mention: "%{name} mentioned you in:"
+      new_followers_summary:
+        one: You have acquired one new follower! Yay!
+        other: You have gotten %{count} new followers! Amazing!
+      subject:
+        one: "1 new notification since your last visit \U0001F418"
+        other: "%{count} new notifications since your last visit \U0001F418"
     favourite:
       body: 'Your status was favourited by %{name}:'
       subject: "%{name} favourited your status"
@@ -92,22 +127,24 @@ en:
     proceed: Proceed to follow
     prompt: 'You are going to follow:'
   settings:
+    authorized_apps: Authorized apps
     back: Back to Mastodon
     edit_profile: Edit profile
+    export: Data export
+    import: Import
     preferences: Preferences
     settings: Settings
     two_factor_auth: Two-factor Authentication
   statuses:
     open_in_web: Open in web
     over_character_limit: character limit of %{max} exceeded
+    show_more: Show more
     visibilities:
       private: Only show to followers
       public: Public
       unlisted: Public, but do not display on the public timeline
   stream_entries:
     click_to_show: Click to show
-    favourited: favourited a post by
-    is_now_following: is now following
     reblogged: boosted
     sensitive_content: Sensitive content
   time:
@@ -118,7 +155,7 @@ en:
     disable: Disable
     enable: Enable
     instructions_html: "<strong>Scan this QR code into Google Authenticator or a similiar app on your phone</strong>. From now on, that app will generate tokens that you will have to enter when logging in."
-    plaintext_secret_html: "Plain-text secret: <samp>%{secret}</samp>"
+    plaintext_secret_html: 'Plain-text secret: <samp>%{secret}</samp>'
     warning: If you cannot configure an authenticator app right now, you should click "disable" or you won't be able to login.
   users:
     invalid_email: The e-mail address is invalid
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 2e0adb742..19f2c71b8 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1,7 +1,6 @@
 ---
 es:
   about:
-    about_instance: "<em>%{instance}</em> es una instancia de Mastodon."
     about_mastodon: Mastodon es un servidor de red social <em>libre y de código abierto</em>. Una alternativa <em>descentralizada</em> a plataformas comerciales, que evita el riesgo de que una única compañía monopolice tu comunicación. Cualquiera puede ejecutar Mastodon y participar sin problemas en la <em>red social</em>.
     get_started: Comenzar
     source_code: Código fuente
@@ -10,7 +9,7 @@ es:
     follow: Seguir
     followers: Seguidores
     following: Siguiendo
-    nothing_here: ¡No hay nada aquí!
+    nothing_here: "¡No hay nada aquí!"
     people_followed_by: Usuarios a quien %{name} sigue
     people_who_follow: Usuarios que siguen a %{name}
     posts: Publicaciones
@@ -19,20 +18,20 @@ es:
     signature: Notificaciones de Mastodon desde %{instance}
   auth:
     change_password: Cambiar contraseña
-    didnt_get_confirmation: ¿No recibió instrucciones de confirmación?
-    forgot_password: ¿Olvidó su contraseña?
+    didnt_get_confirmation: "¿No recibió instrucciones de confirmación?"
+    forgot_password: "¿Olvidó su contraseña?"
     login: Iniciar sesión
     register: Registrarse
     resend_confirmation: Volver a enviar las instrucciones de confirmación
     reset_password: Restablecer contraseña
     set_new_password: Establecer nueva contraseña
   generic:
-    changes_saved_msg: ¡Cambios guardados con éxito!
+    changes_saved_msg: "¡Cambios guardados con éxito!"
     powered_by: powered by %{link}
     save_changes: Guardar cambios
     validation_errors:
-      one: ¡Algo no está todavía bien! Por favor, revise el error más abajo
-      other: ¡Algo no está todavía bien! Por favor, revise %{count} errores más abajo
+      one: "¡Algo no está todavía bien! Por favor, revise el error más abajo"
+      other: "¡Algo no está todavía bien! Por favor, revise %{count} errores más abajo"
   notification_mailer:
     favourite:
       body: 'Su estado fue marcado como favorito por %{name}:'
@@ -52,8 +51,5 @@ es:
   settings:
     edit_profile: Editar perfil
     preferences: Preferencias
-  stream_entries:
-    favourited: marcado como favorito por
-    is_now_following: está ahora siguiendo
   will_paginate:
     page_gap: "&hellip;"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index f78cd0de5..198ec2ef9 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -1,39 +1,91 @@
 ---
 fr:
   about:
-    about_instance: "<em>%{instance}</em> est une instance de Mastodon."
-    about_mastodon: "Mastodon est un serveur <em>libre</em> de réseautage social. Alternative <em>décentralisée</em> aux plateformes commerciales, la monopolisation de vos communications par une entreprise unique est évitée. Tout un chacun peut faire tourner Mastodon et participer au <em>réseau social</em> de manière transparente."
-    get_started: "Rejoindre le réseau"
-    source_code: "Code source"
-    terms: "Conditions d’utilisation"
+    about_mastodon: Mastodon est un serveur <em>libre</em> de réseautage social. Alternative <em>décentralisée</em> aux plateformes commerciales, la monopolisation de vos communications par une entreprise unique est évitée. Tout un chacun peut faire tourner Mastodon et participer au <em>réseau social</em> de manière transparente.
+    about_this: À propos de cette instance
+    apps: Applications
+    business_email: E-mail professionnel
+    description_headline: Qu'est-ce que %{domain} ?
+    domain_count_after: autres instances
+    domain_count_before: Connectés à
+    features:
+      api: API ouverte aux apps et services
+      blocking: Outils complets de bloquage et masquage
+      characters: 500 caractères par post
+      chronology: Fil chronologique
+      ethics: 'Pas de pubs, pas de pistage'
+      gifv: Partage de vidéos et de GIFs
+      privacy: Réglages de confidentialité au niveau des posts
+      public: Fils publics
+    features_headline: Ce qui rend Mastodon différent
+    get_started: Rejoindre le réseau
+    links: Liens
+    source_code: Code source
+    status_count_after: posts
+    status_count_before: Ayant publiés
+    terms: Conditions d’utilisation
+    user_count_after: utilisateurs
+    user_count_before: Abrite
   accounts:
-    follow: "Suivre"
-    followers: "Abonnés"
-    following: "Abonnements"
-    nothing_here: "Rien à voir ici !"
-    people_followed_by: "Personnes suivies par %{name}"
-    people_who_follow: "Personnes qui suivent %{name}"
-    posts: "Statuts"
-    unfollow: "Ne plus suivre"
+    follow: Suivre
+    followers: Abonnés
+    following: Abonnements
+    nothing_here: Rien à voir ici !
+    people_followed_by: Personnes suivies par %{name}
+    people_who_follow: Personnes qui suivent %{name}
+    posts: Statuts
+    remote_follow: Suivre à distance
+    unfollow: Ne plus suivre
   application_mailer:
-    signature: "Notifications de Mastodon depuis %{instance}"
+    settings: 'Changer les préférences e-mail: ${link}'
+    signature: Notifications de Mastodon depuis %{instance}
+    view: 'Voir:'
+  applications:
+    invalid_url: L'URL fournie est invalide
   auth:
-    change_password: "Changer de mot de passe"
-    didnt_get_confirmation: "Vous n’avez pas reçu les consignes de confirmation ?"
-    forgot_password: "Mode passe oublié ?"
-    login: "Se connecter"
-    register: "S’inscrire"
-    resend_confirmation: "Envoyer à nouveau les consignes de confirmation"
-    reset_password: "Réinitialiser le mot de passe"
-    set_new_password: "Établir le nouveau mot de passe"
+    change_password: Changer de mot de passe
+    didnt_get_confirmation: Vous n’avez pas reçu les consignes de confirmation ?
+    forgot_password: Mode passe oublié ?
+    login: Se connecter
+    logout: Se déconnecter
+    register: S’inscrire
+    resend_confirmation: Envoyer à nouveau les consignes de confirmation
+    reset_password: Réinitialiser le mot de passe
+    set_new_password: Définir le nouveau mot de passe
+  authorize_follow:
+    follow: Suivre
+    prompt_html: 'Vous (<strong>%{self}</strong>) avez demandé à suivre:'
+    title: Suivre %{acct}
+  exports:
+    blocks: Vous bloquez
+    csv: CSV
+    follows: Vous suivez
+    storage: Médias stockés
   generic:
-    changes_saved_msg: "Les modifications ont été enregistrées avec succès !"
-    powered_by: "propulsé par %{link}"
-    save_changes: "Enregistrer les modifications"
+    changes_saved_msg: Les modifications ont été enregistrées avec succès !
+    powered_by: propulsé par %{link}
+    save_changes: Enregistrer les modifications
     validation_errors:
-      one: "Quelque chose ne va pas ! Vérifiez l’erreur ci-dessous."
-      other: "Quelques choses ne vont pas ! Vérifiez les erreurs ci-dessous."
+      one: Quelque chose ne va pas ! Vérifiez l’erreur ci-dessous.
+      other: Quelques choses ne vont pas ! Vérifiez les erreurs ci-dessous.
+  imports:
+    preface: Vous pouvez importer certaines données comme les personnes que vous suivez ou bloquez sur votre compte sur cette instance à partir de fichiers crées sur une autre instance.
+    success: Vos données ont été importées avec succès et seront traités en temps et en heure
+    types:
+      blocking: Liste d'utilisateurs bloqués
+      following: Liste d'utilisateurs suivis
+    upload: Importer
+  landing_strip_html: <strong>%{name}</strong> utilise <strong>%{domain}</strong>. Vous pouvez le/la suivre et intéragir si vous possédez un compte quelque part dans le "fediverse". Si ce n'est pas le cas, vous pouvez <a href="%{sign_up_path}">en créer un ici</a>.
   notification_mailer:
+    digest:
+      body: 'Voici ce que vous avez raté sur ${instance} depuis votre dernière visite (%{}):'
+      mention: '%{name} vous a mentionné⋅e'
+      new_followers_summary:
+        one: Vous avez un nouvel abonné! Youpi!
+        other: Vous avez %{count} nouveaux abonnés! Incroyable!
+      subject:
+        one: "Une nouvelle notification depuis votre dernière visite \U0001F418"
+        other: "%{count} nouvelles notifications depuis votre dernière visite \U0001F418"
     favourite:
       body: "%{name} a ajouté votre statut à ses favoris :"
       subject: "%{name} a ajouté votre statut à ses favoris"
@@ -47,13 +99,46 @@ fr:
       body: "%{name} a partagé votre statut :"
       subject: "%{name} a partagé votre statut"
   pagination:
-    next: "Suivant"
-    prev: "Précédent"
+    next: Suivant
+    prev: Précédent
+  remote_follow:
+    acct: Entrez votre pseudo@instance depuis lequel vous voulez suivre ce⋅tte utilisateur⋅trice
+    missing_resource: L'URL de redirection n'a pas pu être trouvée
+    proceed: Continuez pour suivre
+    prompt: 'Vous allez suivre :'
   settings:
-    edit_profile: "Modifier le profil"
-    preferences: "Préférences"
+    authorized_apps: Applications autorisées
+    back: Retour vers Mastodon
+    edit_profile: Modifier le profil
+    export: Export de données
+    import: Importer des données
+    preferences: Préférences
+    settings: Réglages
+    two_factor_auth: Identification à deux facteurs (Two-factor auth)
+  statuses:
+    open_in_web: Ouvrir sur le web
+    over_character_limit: limite de caractères dépassée de %{max} caractères
+    show_more: Montrer plus
+    visibilities:
+      private: Abonnés uniquement
+      public: Public
+      unlisted: Public sans être affiché sur le fil public
   stream_entries:
-    favourited: "a ajouté à ses favoris un statut de"
-    is_now_following: "suit désormais"
+    click_to_show: Clic pour afficher
+    reblogged: partagé
+    sensitive_content: Contenu sensible
+  time:
+    formats:
+      default: '%d %b %Y, %H:%M'
+  two_factor_auth:
+    description_html: Si vous activez <strong>l'identification à deux facteurs</strong> vous devrez être en posession de votre téléphone afin de générer un code de connexion.
+    disable: Désactiver
+    enable: Activer
+    instructions_html: "<strong>Scannez ce QR code grâce à Google Authenticator or une application similaire sur votre téléphone</strong>. Désormais, cette application générera des jetons que vous devrez saisir à chaque connexion"
+    plaintext_secret_html: 'Code secret en clair: <samp>%{secret}</samp>'
+    warning: Si vous ne pouvez pas configurer une application d'authentification maintenant, vous devriez cliquer sur "Désactiver" pour ne pas bloquer l'accès à votre compte
+  users:
+    invalid_email: L'adresse e-mail est invalide
+    invalid_otp_token: Le code d'identification à deux facteurs est invalide
   will_paginate:
     page_gap: "&hellip;"
diff --git a/config/locales/hu.yml b/config/locales/hu.yml
index d891b2b28..915d02c19 100644
--- a/config/locales/hu.yml
+++ b/config/locales/hu.yml
@@ -1,7 +1,6 @@
 ---
 hu:
   about:
-    about_instance: "<em>%{instance}</em> egy Mastodon másolat."
     about_mastodon: Mastodon egy <em>szabad, nyílt forráskódú</em> szociális hálózati kiszolgálo. Egy <em>központosítatlan</em> alternatíva a kereskedelmi platformokra, elkerüli a kommunikációd monopolizációját veszélyét. Bárki futtathatja a Mastodon-t és részt vehet a <em>szociális hálózatban</em>.
     get_started: Első lépések
     source_code: Forráskód
@@ -41,7 +40,7 @@ hu:
       body: "%{name} mostantól követ téged!"
       subject: "%{name} mostantól követ téged"
     mention:
-      body: '%{name} megemlített téged:'
+      body: "%{name} megemlített téged:"
       subject: "%{name} megemlített téged"
     reblog:
       body: 'Az állapotod reblogolta %{name}:'
@@ -52,8 +51,5 @@ hu:
   settings:
     edit_profile: Profil szerkesztése
     preferences: Beállítások
-  stream_entries:
-    favourited: kedvencnek jelölték a bejegyzésedet 
-    is_now_following: mostantól követ
   will_paginate:
     page_gap: "&hellip;"
diff --git a/config/locales/pt.yml b/config/locales/pt.yml
index d02c0bdc5..ad7d05e3b 100644
--- a/config/locales/pt.yml
+++ b/config/locales/pt.yml
@@ -1,7 +1,6 @@
 ---
 pt:
   about:
-    about_instance: "<em>%{instance}</em> é uma instância de Mastodon."
     about_mastodon: Mastodon é um servidor de rede social <em>grátis, e open-source</em>. Uma alternativa <em>descentralizada</em> ás plataformas comerciais, que evita o risco de uma única empresa monopolizar a sua comunicação. Qualquer um pode ter uma instância Mastodon e assim participar na <em>rede social federada</em> sem problemas.
     get_started: Como começar
     source_code: Source code
@@ -52,8 +51,5 @@ pt:
   settings:
     edit_profile: Editar perfil
     preferences: Preferências
-  stream_entries:
-    favourited: favoritou um post por
-    is_now_following: agora segue
   will_paginate:
     page_gap: "&hellip;"
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index 4d1758f82..df4f6ca00 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -8,12 +8,15 @@ en:
         header: PNG, GIF or JPG. At most 2MB. Will be downscaled to 700x335px
         locked: Requires you to manually approve followers and defaults post privacy to followers-only
         note: At most 160 characters
+      imports:
+        data: CSV file exported from another Mastodon instance
     labels:
       defaults:
         avatar: Avatar
         confirm_new_password: Confirm new password
         confirm_password: Confirm password
         current_password: Current password
+        data: Data
         display_name: Display name
         email: E-mail address
         header: Header
@@ -24,11 +27,13 @@ en:
         otp_attempt: Two-factor code
         password: Password
         setting_default_privacy: Post privacy
+        type: Import type
         username: Username
       interactions:
         must_be_follower: Block notifications from non-followers
         must_be_following: Block notifications from people you don't follow
       notification_emails:
+        digest: Send digest e-mails
         favourite: Send e-mail when someone favourites your status
         follow: Send e-mail when someone follows you
         follow_request: Send e-mail when someone requests to follow you
diff --git a/config/locales/simple_form.fr.yml b/config/locales/simple_form.fr.yml
index 0fcf89140..fd0373436 100644
--- a/config/locales/simple_form.fr.yml
+++ b/config/locales/simple_form.fr.yml
@@ -1,26 +1,42 @@
 ---
 fr:
   simple_form:
+    hints:
+      defaults:
+        avatar: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 120x120px
+        display_name: 30 caractères maximum
+        header: Au format PNG, GIF ou JPG. 2Mo maximum. Sera réduit à 700x335px
+        locked: Vous devrez approuver chaque abonné⋅e et vos statuts ne s'afficheront qu'à vos abonné⋅es
+        note: 160 caractères maximum
+      imports:
+        data: Un fichier CSV généré par une autre instance de Mastodon
     labels:
       defaults:
         avatar: Image de profil
         confirm_new_password: Confirmation du nouveau mot de passe
         confirm_password: Confirmation du mot de passe
         current_password: Mot de passe actuel
+        data: Données
         display_name: Nom public
         email: Adresse courriel
         header: Image d’en-tête
         locale: Langue
+        locked: Rendre le compte privé
         new_password: Nouveau mot de passe
         note: Présentation
+        otp_attempt: Code d'identification à deux facteurs
         password: Mot de passe
+        setting_default_privacy: Confidentialité des statuts
+        type: Type d'import
         username: Identifiant
       interactions:
         must_be_follower: Masquer les notifications des personnes qui ne vous suivent pas
         must_be_following: Masquer les notifications des personnes que vous ne suivez pas
       notification_emails:
-        favourite: Envoyer un courriel lorsque quelqu’un ajoute mes statut à ses favoris
+        digest: Envoyer des emails récapitulatifs
+        favourite: Envoyer un courriel lorsque quelqu’un ajoute mes statuts à ses favoris
         follow: Envoyer un courriel lorsque quelqu’un me suit
+        follow_request: Envoyer un courriel lorsque quelqu'un demande à me suivre
         mention: Envoyer un courriel lorsque quelqu’un me mentionne
         reblog: Envoyer un courriel lorsque quelqu’un partage mes statuts
     'no': Non
diff --git a/config/locales/simple_form.zh-CN.yml b/config/locales/simple_form.zh-CN.yml
new file mode 100644
index 000000000..cda4e6838
--- /dev/null
+++ b/config/locales/simple_form.zh-CN.yml
@@ -0,0 +1,42 @@
+---
+zh-CN:
+  simple_form:
+    hints:
+      defaults:
+        avatar: 不超过 2MB,限 PNG, GIF 或 JPG 格式,将缩到 120x120px
+        display_name: 不起过 30 个字符
+        header: 不超过 2MB,限 PNG, GIF 或 JPG 格式,将缩到 700x335px
+        locked: 默认仅向粉丝公开,需要手工设置通过的粉丝。
+        note: 不起过 160 个字符
+    labels:
+      defaults:
+        avatar: 头像
+        confirm_new_password: 确认新密码
+        confirm_password: 确认密码
+        current_password: 当前密码
+        display_name: 显示名
+        email: 邮箱
+        header: 头
+        locale: 语言
+        locked: 隐私模式
+        new_password: 新密码
+        note: Bio
+        otp_attempt: 两步难码
+        password: 密码
+        setting_default_privacy: 推文隐私
+        username: 用户名
+      interactions:
+        must_be_follower: 仅粉丝可私信
+        must_be_following: 仅关注中可私信
+      notification_emails:
+        digest: 发送摘要邮件
+        favourite: 有人收藏你的发送邮件通知
+        follow: 有人关注你时发送邮件通知
+        follow_request: 有人请求关注你时发送邮件通知
+        mention: 有人 AT 你时发送邮件通知
+        reblog: 有人转发时发送邮件通知
+    'no': '否'
+    required:
+      mark: "*"
+      text: 必须
+    'yes': '是'
diff --git a/config/locales/uk.yml b/config/locales/uk.yml
index 621dfb323..27e8135df 100644
--- a/config/locales/uk.yml
+++ b/config/locales/uk.yml
@@ -1,7 +1,6 @@
 ---
 uk:
   about:
-    about_instance: "<em>%{instance}</em> є інстанцією Mastodon."
     about_mastodon: Mastodon <em> - це вільний</em> соціальний мережевий сервер <em> з відкритим вихідним кодом</em>. Він є <em>децентралізованою</em> альтернативою комерційним платформам, що дозволяє уникнути ризиків монополізації вашого спілкування однією компанією. Будь-який користувач може запустити Mastodon та без проблем брати участь в <em>соціальній мережі</em>.
     get_started: Почати
     source_code: Вихідний код
@@ -36,7 +35,7 @@ uk:
   notification_mailer:
     favourite:
       body: 'Ваш статус подобається %{name}:'
-      subject: "Користувачу %{name} сподобвся ваш статус"
+      subject: Користувачу %{name} сподобвся ваш статус
     follow:
       body: "%{name} тепер підписаний на вас!"
       subject: "%{name} тепер підписаний на вас"
@@ -52,8 +51,5 @@ uk:
   settings:
     edit_profile: Редагувати профіль
     preferences: Налаштування
-  stream_entries:
-    favourited: сподобався допис від
-    is_now_following: тепер підписаний(-а) на
   will_paginate:
     page_gap: "&hellip;"
diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml
new file mode 100644
index 000000000..78c4d46e2
--- /dev/null
+++ b/config/locales/zh-CN.yml
@@ -0,0 +1,154 @@
+---
+zh-CN:
+  about:
+    about_mastodon: Mastodon <em>开源、自由</em>社交网络。<em>去中心化</em>的商业平台替代,避免单一商业公司垄断沟通。可选择、可信任地任意交流。任何人均可以运行自己的 Mastodon 并进行无缝交流。
+    about_this: 关于本实例
+    business_email: 商务邮件:
+    contact: 联络
+    description_headline: 去中心化 %{domain} 是什么?
+    domain_count_after: 其它实例
+    domain_count_before: Connected to
+    features:
+      api: 对APP 和服务开放的 API
+      blocks: Rich block and muting tools
+      characters: 每个推多达 500 字符
+      chronology: 按时间线排序
+      ethics: 良心之作:没有广告,没有数据追踪
+      gifv: GIFV 与小视频
+      privacy: 细粒度,可按推设置隐私
+      public: 公共时间线
+    features_headline: Mastodon 与众不同之处
+    get_started: 立即开始
+    links: 链接
+    other_instances: 其它实例
+    source_code: 源码
+    status_count_after: statuses
+    status_count_before: Who authored
+    terms: 条款
+    user_count_after: users
+    user_count_before: Home to
+  accounts:
+    follow: 关注
+    followers: 粉丝
+    following: 关注
+    nothing_here: 神马都没有!
+    people_followed_by: 正关注
+    people_who_follow: 粉丝
+    posts: 推
+    remote_follow: Remote follow
+    unfollow: 取关
+  application_mailer:
+    settings: '更改邮件设置: %{link}'
+    signature: 来自 %{instance} 的提醒
+    view: 查看:
+  applications:
+    invalid_url: URL 无效
+  auth:
+    change_password: 更换密码
+    didnt_get_confirmation: 没有收到确认邮件?
+    forgot_password: 忘记密码?
+    login: 登录
+    logout: 登出
+    register: 注册
+    resend_confirmation: 重发确认邮件
+    reset_password: 重置密码
+    set_new_password: 设置新密码
+  authorize_follow:
+    error: Unfortunately, there was an error looking up the remote account
+    follow: 关注
+    prompt_html: 'You (<strong>%{self}</strong>) have requested to follow:'
+    title: 关注 %{acct}
+  datetime:
+    distance_in_words:
+      about_x_hours: 大约 %{count} 小时
+      about_x_months: 大约 %{count} 月
+      about_x_years: 大约 %{count} 年
+      almost_x_years: 几乎 %{count} 年
+      half_a_minute: 刚刚
+      less_than_x_minutes: "%{count} 分"
+      less_than_x_seconds: 刚刚
+      over_x_years: 超过 %{count} 年
+      x_days: "%{count} 天"
+      x_minutes: "%{count} 分"
+      x_months: "%{count} 月"
+      x_seconds: "%{count} 秒"
+  exports:
+    blocks: You block
+    csv: CSV
+    follows: 关注
+    storage: 媒体文件
+  generic:
+    changes_saved_msg: 保存成功!
+    powered_by: 基于 %{link} 构建
+    save_changes: 保存
+    validation_errors:
+      one: 出错了!什么鬼?
+      other: 出错了!什么鬼?
+  landing_strip_html: <strong>%{name}</strong> is a user on <strong>%{domain}</strong>. You can follow them or interact with them if you have an account anywhere in the fediverse. If you don't, you can <a href="%{sign_up_path}">sign up here</a>.
+  notification_mailer:
+    digest:
+      body: 'Here is a brief summary of what you missed on %{instance} since your last visit on %{since}:'
+      mention: "%{name} mentioned you in:"
+      new_followers_summary:
+        one: 有人关注你了!耶!
+        other: 有 %{count} 个人关注了你!别鸡动!
+      subject:
+        one: "你有一个新提醒 \U0001F418"
+        other: "%{count} 个提醒太多,赶快去看看 \U0001F418"
+    favourite:
+      body: "%{name} 赞你"
+      subject: "%{name} 对你点赞"
+    follow:
+      body: "%{name} 关注了你"
+      subject: "%{name} 关注了你"
+    follow_request:
+      body: "%{name} 要关注你"
+      subject: 'Pending follower: %{name}'
+    mention:
+      body: 'You were mentioned by %{name} in:'
+      subject: You were mentioned by %{name}
+    reblog:
+      body: 'Your status was boosted by %{name}:'
+      subject: "%{name} boosted your status"
+  pagination:
+    next: 下一页
+    prev: 上一页
+  remote_follow:
+    acct: Enter your username@domain you want to follow from
+    missing_resource: Could not find the required redirect URL for your account
+    proceed: Proceed to follow
+    prompt: 'You are going to follow:'
+  settings:
+    authorized_apps: 已授权 APP
+    back: 返回
+    edit_profile: 更改个人信息
+    export: 数据导出
+    preferences: 设置
+    settings: 设置
+    two_factor_auth: 两步验证
+  statuses:
+    open_in_web: 浏览器中打开
+    over_character_limit: 超出范围 %{max}
+    visibilities:
+      private: 仅向粉丝公开
+      public: 公开
+      unlisted: 公开但不显示在公共时间线中
+  stream_entries:
+    click_to_show: 显示
+    reblogged: 转发
+    sensitive_content: 敏感内容Sensitive content
+  time:
+    formats:
+      default: "%b %d, %Y, %H:%M"
+  two_factor_auth:
+    description_html: 启用<strong>两步验证</strong>后,登录时强制要求手机上生成的两步验证码
+    disable: 禁用
+    enable: 启用
+    instructions_html: "<strong>使用 Google Authenticator 或类似 APP 扫描二维码</strong>。现在起,APP 将会生成登陆时必须的两步验证码。"
+    plaintext_secret_html: 密钥: <samp>%{secret}</samp>
+    warning: 如果你现在没有 Google Authenticator 或类似授权 APP,你应该先「禁用」本功能,否则你将不能正常登陆。
+  users:
+    invalid_email: 无效的邮箱
+    invalid_otp_token: 无效的两步验证码
+  will_paginate:
+    page_gap: "&hellip;"
diff --git a/config/navigation.rb b/config/navigation.rb
index 0d43a9f73..77556e5aa 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -9,7 +9,9 @@ SimpleNavigation::Configuration.run do |navigation|
       settings.item :preferences, safe_join([fa_icon('sliders fw'), t('settings.preferences')]), settings_preferences_url
       settings.item :password, safe_join([fa_icon('cog fw'), t('auth.change_password')]), edit_user_registration_url
       settings.item :two_factor_auth, safe_join([fa_icon('mobile fw'), t('settings.two_factor_auth')]), settings_two_factor_auth_url
-      # settings.item :authorized_apps, safe_join([fa_icon('list fw'), 'Authorized Apps']), oauth_authorized_applications_url
+      settings.item :import, safe_join([fa_icon('cloud-upload fw'), t('settings.import')]), settings_import_url
+      settings.item :export, safe_join([fa_icon('cloud-download fw'), t('settings.export')]), settings_export_url
+      settings.item :authorized_apps, safe_join([fa_icon('list fw'), t('settings.authorized_apps')]), oauth_authorized_applications_url
     end
 
     primary.item :admin, safe_join([fa_icon('cogs fw'), 'Administration']), admin_accounts_url, if: proc { current_user.admin? } do |admin|
diff --git a/config/routes.rb b/config/routes.rb
index 70e252409..bfca5c734 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -24,6 +24,8 @@ Rails.application.routes.draw do
     confirmations:      'auth/confirmations',
   }
 
+  get '/users/:username', to: redirect('/@%{username}'), constraints: { format: :html }
+
   resources :accounts, path: 'users', only: [:show], param: :username do
     resources :stream_entries, path: 'updates', only: [:show] do
       member do
@@ -43,9 +45,20 @@ Rails.application.routes.draw do
     end
   end
 
+  get '/@:username', to: 'accounts#show', as: :short_account
+  get '/@:account_username/:id', to: 'statuses#show', as: :short_account_status
+
   namespace :settings do
     resource :profile, only: [:show, :update]
     resource :preferences, only: [:show, :update]
+    resource :import, only: [:show, :create]
+
+    resource :export, only: [:show] do
+      collection do
+        get :follows, to: 'exports#download_following_list'
+        get :blocks, to: 'exports#download_blocking_list'
+      end
+    end
 
     resource :two_factor_auth, only: [:show] do
       member do
@@ -122,13 +135,18 @@ Rails.application.routes.draw do
       get '/timelines/public',   to: 'timelines#public', as: :public_timeline
       get '/timelines/tag/:id',  to: 'timelines#tag', as: :hashtag_timeline
 
+      get '/search', to: 'search#index', as: :search
+
       resources :follows,    only: [:create]
       resources :media,      only: [:create]
       resources :apps,       only: [:create]
       resources :blocks,     only: [:index]
+      resources :mutes,      only: [:index]
       resources :favourites, only: [:index]
       resources :reports,    only: [:index, :create]
 
+      resource :instance, only: [:show]
+
       resources :follow_requests, only: [:index] do
         member do
           post :authorize
@@ -151,7 +169,6 @@ Rails.application.routes.draw do
 
         member do
           get :statuses
-          get 'statuses/media', to: 'accounts#media_statuses', as: :media_statuses
           get :followers
           get :following
 
@@ -159,6 +176,8 @@ Rails.application.routes.draw do
           post :unfollow
           post :block
           post :unblock
+          post :mute
+          post :unmute
         end
       end
     end
diff --git a/config/settings.yml b/config/settings.yml
index 71ce12e63..6ae9217a4 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -11,6 +11,7 @@ defaults: &defaults
     favourite: false
     mention: false
     follow_request: true
+    digest: true
   interactions:
     must_be_follower: false
     must_be_following: false