diff options
Diffstat (limited to 'app')
64 files changed, 594 insertions, 146 deletions
diff --git a/app/controllers/api/v1/push/subscriptions_controller.rb b/app/controllers/api/v1/push/subscriptions_controller.rb new file mode 100644 index 000000000..5038cc03c --- /dev/null +++ b/app/controllers/api/v1/push/subscriptions_controller.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +class Api::V1::Push::SubscriptionsController < Api::BaseController + before_action -> { doorkeeper_authorize! :push } + before_action :require_user! + before_action :set_web_push_subscription + + def create + @web_subscription&.destroy! + + @web_subscription = ::Web::PushSubscription.create!( + endpoint: subscription_params[:endpoint], + key_p256dh: subscription_params[:keys][:p256dh], + key_auth: subscription_params[:keys][:auth], + data: data_params, + user_id: current_user.id, + access_token_id: doorkeeper_token.id + ) + + render json: @web_subscription, serializer: REST::WebPushSubscriptionSerializer + end + + def update + raise ActiveRecord::RecordNotFound if @web_subscription.nil? + + @web_subscription.update!(data: data_params) + + render json: @web_subscription, serializer: REST::WebPushSubscriptionSerializer + end + + def destroy + @web_subscription&.destroy! + render_empty + end + + private + + def set_web_push_subscription + @web_subscription = ::Web::PushSubscription.find_by(access_token_id: doorkeeper_token.id) + end + + def subscription_params + params.require(:subscription).permit(:endpoint, keys: [:auth, :p256dh]) + end + + def data_params + return {} if params[:data].blank? + params.require(:data).permit(alerts: [:follow, :favourite, :reblog, :mention]) + end +end diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index 249e7c186..fe8e42580 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -31,22 +31,23 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController endpoint: subscription_params[:endpoint], key_p256dh: subscription_params[:keys][:p256dh], key_auth: subscription_params[:keys][:auth], - data: data + data: data, + user_id: active_session.user_id, + access_token_id: active_session.access_token_id ) active_session.update!(web_push_subscription: web_subscription) - render json: web_subscription.as_payload + render json: web_subscription, serializer: REST::WebPushSubscriptionSerializer end def update params.require([:id]) web_subscription = ::Web::PushSubscription.find(params[:id]) - web_subscription.update!(data: data_params) - render json: web_subscription.as_payload + render json: web_subscription, serializer: REST::WebPushSubscriptionSerializer end private @@ -56,6 +57,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController end def data_params - @data_params ||= params.require(:data).permit(:alerts) + @data_params ||= params.require(:data).permit(alerts: [:follow, :favourite, :reblog, :mention]) end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 158c0c10e..27ebc3333 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -9,6 +9,7 @@ class ApplicationController < ActionController::Base include Localized include UserTrackingConcern + include SessionTrackingConcern helper_method :current_account helper_method :current_session diff --git a/app/controllers/concerns/session_tracking_concern.rb b/app/controllers/concerns/session_tracking_concern.rb new file mode 100644 index 000000000..45361b019 --- /dev/null +++ b/app/controllers/concerns/session_tracking_concern.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module SessionTrackingConcern + extend ActiveSupport::Concern + + UPDATE_SIGN_IN_HOURS = 24 + + included do + before_action :set_session_activity + end + + private + + def set_session_activity + return unless session_needs_update? + current_session.touch + end + + def session_needs_update? + !current_session.nil? && current_session.updated_at < UPDATE_SIGN_IN_HOURS.hours.ago + end +end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 189e4072e..2e9f73bb8 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -9,9 +9,9 @@ class InvitesController < ApplicationController before_action :set_pack def index - authorize :invite, :create? + authorize :invite, :index? - @invites = Invite.where(user: current_user) + @invites = invites @invite = Invite.new(expires_in: 1.day.to_i) end @@ -24,13 +24,13 @@ class InvitesController < ApplicationController if @invite.save redirect_to invites_path else - @invites = Invite.where(user: current_user) + @invites = invites render :index end end def destroy - @invite = Invite.where(user: current_user).find(params[:id]) + @invite = invites.find(params[:id]) authorize @invite, :destroy? @invite.expire! redirect_to invites_path @@ -42,6 +42,10 @@ class InvitesController < ApplicationController use_pack 'settings' end + def invites + Invite.where(user: current_user) + end + def resource_params params.require(:invite).permit(:max_uses, :expires_in) end diff --git a/app/controllers/shares_controller.rb b/app/controllers/shares_controller.rb index 3cbaccb35..4624c29a6 100644 --- a/app/controllers/shares_controller.rb +++ b/app/controllers/shares_controller.rb @@ -16,6 +16,7 @@ class SharesController < ApplicationController def initial_state_params text = [params[:title], params[:text], params[:url]].compact.join(' ') + { settings: Web::Setting.find_by(user: current_user)&.data || {}, push_subscription: current_account.user.web_push_subscription(current_session), diff --git a/app/javascript/mastodon/features/compose/components/upload.js b/app/javascript/mastodon/features/compose/components/upload.js index 61b2d19e0..bfa2b4727 100644 --- a/app/javascript/mastodon/features/compose/components/upload.js +++ b/app/javascript/mastodon/features/compose/components/upload.js @@ -77,7 +77,7 @@ export default class Upload extends ImmutablePureComponent { {({ scale }) => ( <div className='compose-form__upload-thumbnail' style={{ transform: `scale(${scale})`, backgroundImage: `url(${media.get('preview_url')})`, backgroundPosition: `${x}% ${y}%` }}> <div className={classNames('compose-form__upload__actions', { active })}> - <button className='icon-button' onClick={this.handleUndoClick}><i className='fa fa-times' /> <FormattedMessage id='upload_form.undo' defaultMessage='Undo' /></button> + <button className='icon-button' onClick={this.handleUndoClick}><i className='fa fa-times' /> <FormattedMessage id='upload_form.undo' defaultMessage='Delete' /></button> {media.get('type') === 'image' && <button className='icon-button' onClick={this.handleFocalPointClick}><i className='fa fa-crosshairs' /> <FormattedMessage id='upload_form.focus' defaultMessage='Crop' /></button>} </div> diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index d531d8fd5..a4f27cd31 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "حظر @{name}", "account.block_domain": "إخفاء كل شيئ قادم من إسم النطاق {domain}", "account.blocked": "محظور", diff --git a/app/javascript/mastodon/locales/bg.json b/app/javascript/mastodon/locales/bg.json index 971475114..dd747ab3b 100644 --- a/app/javascript/mastodon/locales/bg.json +++ b/app/javascript/mastodon/locales/bg.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Блокирай", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/ca.json b/app/javascript/mastodon/locales/ca.json index f2e3699d5..22c5453ca 100644 --- a/app/javascript/mastodon/locales/ca.json +++ b/app/javascript/mastodon/locales/ca.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloca @{name}", "account.block_domain": "Amaga-ho tot de {domain}", "account.blocked": "Bloquejat", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json index 2d7427c55..9d8d950a8 100644 --- a/app/javascript/mastodon/locales/co.json +++ b/app/javascript/mastodon/locales/co.json @@ -1,9 +1,10 @@ { + "account.badges.bot": "Bot", "account.block": "Bluccà @{name}", "account.block_domain": "Piattà tuttu da {domain}", "account.blocked": "Bluccatu", "account.direct": "Missaghju direttu @{name}", - "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", + "account.disclaimer_full": "Ghjè pussibule chì l’infurmazione quì sottu ùn rifletta micca u prufile sanu di l’utilizatore.", "account.domain_blocked": "Duminiu piattatu", "account.edit_profile": "Mudificà u prufile", "account.follow": "Siguità", @@ -28,7 +29,7 @@ "account.unfollow": "Ùn siguità più", "account.unmute": "Ùn piattà più @{name}", "account.unmute_notifications": "Ùn piattà più nutificazione da @{name}", - "account.view_full_profile": "View full profile", + "account.view_full_profile": "Vede tuttu u prufile", "alert.unexpected.message": "Un prublemu inaspettatu hè accadutu.", "alert.unexpected.title": "Uups!", "boost_modal.combo": "Pudete appughjà nant'à {combo} per saltà quessa a prussima volta", @@ -78,7 +79,7 @@ "confirmations.delete.message": "Site sicuru·a che vulete supprime stu statutu?", "confirmations.delete_list.confirm": "Toglie", "confirmations.delete_list.message": "Site sicuru·a che vulete supprime sta lista?", - "confirmations.domain_block.confirm": "Piattà tuttu u duminiu?", + "confirmations.domain_block.confirm": "Piattà tuttu u duminiu", "confirmations.domain_block.message": "Site sicuru·a che vulete piattà tuttu à {domain}? Saria forse abbastanza di bluccà ò piattà alcuni conti da quallà.", "confirmations.mute.confirm": "Piattà", "confirmations.mute.message": "Site sicuru·a che vulete piattà @{name}?", @@ -107,13 +108,13 @@ "empty_column.home.public_timeline": "a linea pubblica", "empty_column.list": "Ùn c'hè ancu nunda quì. Quandu membri di sta lista manderanu novi statuti, i vidarete quì.", "empty_column.notifications": "Ùn avete ancu nisuna nutificazione. Interact with others to start the conversation.", - "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altre istanze per empie a linea pubblica.", + "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altre istanze per empie a linea pubblica", "follow_request.authorize": "Auturizà", "follow_request.reject": "Righjittà", "getting_started.appsshort": "Applicazione", "getting_started.faq": "FAQ", "getting_started.heading": "Per principià", - "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}", + "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}.", "getting_started.userguide": "Guida d'utilizazione", "home.column_settings.advanced": "Avanzati", "home.column_settings.basic": "Bàsichi", @@ -200,7 +201,7 @@ "onboarding.page_six.apps_available": "Ci sò {apps} dispunibule per iOS, Android è altre piattaforme.", "onboarding.page_six.github": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un prublemu, nant'à {github}.", "onboarding.page_six.guidelines": "regule di a cumunità", - "onboarding.page_six.read_guidelines": "Ùn vi scurdate di leghje e {guidelines} di {domain}", + "onboarding.page_six.read_guidelines": "Ùn vi scurdate di leghje e {guidelines} di {domain}!", "onboarding.page_six.various_app": "applicazione pè u telefuninu", "onboarding.page_three.profile": "Pudete mudificà u prufile per cambia u ritrattu, a descrizzione è u nome affissatu. Ci sò ancu alcun'altre preferenze.", "onboarding.page_three.search": "Fate usu di l'area di ricerca per truvà altre persone è vede hashtag cum'è {illustration} o {introductions}. Per vede qualcunu ch'ùn hè micca nant'à st'istanza, cercate u so identificatore complettu (pare un'email).", @@ -231,13 +232,13 @@ "report.target": "Signalamentu", "search.placeholder": "Circà", "search_popout.search_format": "Ricerca avanzata", - "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.full_text": "I testi simplici rimandanu i statuti ch'avete scritti, aghjunti à i vostri favuriti, spartuti o induve quelli site mintuvatu·a, è ancu i cugnomi, nomi pubblichi è hashtag chì currispondenu.", "search_popout.tips.hashtag": "hashtag", "search_popout.tips.status": "statutu", - "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.text": "Un testu simplice rimanda i nomi pubblichi, cugnomi è hashtag", "search_popout.tips.user": "utilizatore", "search_results.accounts": "Ghjente", - "search_results.hashtags": "Hashtags", + "search_results.hashtags": "Hashtag", "search_results.statuses": "Statuti", "search_results.total": "{count, number} {count, plural, one {risultatu} other {risultati}}", "standalone.public_title": "Una vista di...", diff --git a/app/javascript/mastodon/locales/de.json b/app/javascript/mastodon/locales/de.json index f442e0675..fe5bc4443 100644 --- a/app/javascript/mastodon/locales/de.json +++ b/app/javascript/mastodon/locales/de.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "@{name} blocken", "account.block_domain": "Alles von {domain} verstecken", "account.blocked": "Blockiert", diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json index b400349d2..74bf97361 100644 --- a/app/javascript/mastodon/locales/defaultMessages.json +++ b/app/javascript/mastodon/locales/defaultMessages.json @@ -552,6 +552,10 @@ { "defaultMessage": "Domain hidden", "id": "account.domain_blocked" + }, + { + "defaultMessage": "Bot", + "id": "account.badges.bot" } ], "path": "app/javascript/mastodon/features/account/components/header.json" @@ -815,7 +819,7 @@ "id": "upload_form.description" }, { - "defaultMessage": "Undo", + "defaultMessage": "Delete", "id": "upload_form.undo" }, { @@ -1866,4 +1870,4 @@ ], "path": "app/javascript/mastodon/features/video/index.json" } -] \ No newline at end of file +] diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index 5b36348eb..d1421be76 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Απόκλεισε τον/την @{name}", "account.block_domain": "Απόκρυψε τα πάντα από τον/την", "account.blocked": "Αποκλεισμένος/η", @@ -111,7 +112,7 @@ "follow_request.authorize": "Ενέκρινε", "follow_request.reject": "Απέρριψε", "getting_started.appsshort": "Εφαρμογές", - "getting_started.faq": "FAQ", + "getting_started.faq": "Συχνές Ερωτήσεις", "getting_started.heading": "Ξεκινώντας", "getting_started.open_source_notice": "Το Mastodon είναι ελεύθερο λογισμικό. Μπορείς να συνεισφέρεις ή να αναφέρεις ζητήματα στο GitHub στο {github}.", "getting_started.userguide": "Οδηγός Χρηστών", @@ -174,7 +175,7 @@ "notification.follow": "{name} followed you", "notification.mention": "{name} mentioned you", "notification.reblog": "{name} boosted your status", - "notifications.clear": "Clear notifications", + "notifications.clear": "Καθαρισμός ειδοποιήσεων", "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", "notifications.column_settings.alert": "Desktop notifications", "notifications.column_settings.favourite": "Favourites:", @@ -194,7 +195,7 @@ "onboarding.page_one.full_handle": "Your full handle", "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.", "onboarding.page_one.welcome": "Welcome to Mastodon!", - "onboarding.page_six.admin": "Your instance's admin is {admin}.", + "onboarding.page_six.admin": "Ο διαχειριστής του κόμβου σου είναι ο/η {admin}.", "onboarding.page_six.almost_done": "Almost done...", "onboarding.page_six.appetoot": "Bon Appetoot!", "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.", @@ -248,13 +249,13 @@ "status.direct": "Direct message @{name}", "status.embed": "Embed", "status.favourite": "Favourite", - "status.load_more": "Load more", + "status.load_more": "Φόρτωσε περισσότερα", "status.media_hidden": "Media hidden", "status.mention": "Mention @{name}", "status.more": "More", "status.mute": "Mute @{name}", "status.mute_conversation": "Mute conversation", - "status.open": "Expand this status", + "status.open": "Διεύρυνε αυτή την κατάσταση", "status.pin": "Pin on profile", "status.pinned": "Pinned toot", "status.reblog": "Boost", diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index d8e69fd3c..35c5a86e9 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Block @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", @@ -286,7 +287,7 @@ "upload_button.label": "Add media", "upload_form.description": "Describe for the visually impaired", "upload_form.focus": "Crop", - "upload_form.undo": "Undo", + "upload_form.undo": "Delete", "upload_progress.label": "Uploading...", "video.close": "Close video", "video.exit_fullscreen": "Exit full screen", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 1ab6d2aa0..4aa3d80a3 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloki @{name}", "account.block_domain": "Kaŝi ĉion de {domain}", "account.blocked": "Blokita", diff --git a/app/javascript/mastodon/locales/es.json b/app/javascript/mastodon/locales/es.json index 41d7db9da..8aac2d77d 100644 --- a/app/javascript/mastodon/locales/es.json +++ b/app/javascript/mastodon/locales/es.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloquear", "account.block_domain": "Ocultar todo de {domain}", "account.blocked": "Bloqueado", diff --git a/app/javascript/mastodon/locales/eu.json b/app/javascript/mastodon/locales/eu.json index 49cdf5630..e927547e3 100644 --- a/app/javascript/mastodon/locales/eu.json +++ b/app/javascript/mastodon/locales/eu.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokeatu @{name}", "account.block_domain": "{domain}(e)ko guztia ezkutatu", "account.blocked": "Blokeatuta", diff --git a/app/javascript/mastodon/locales/fa.json b/app/javascript/mastodon/locales/fa.json index 99aba00c3..e19b1cd85 100644 --- a/app/javascript/mastodon/locales/fa.json +++ b/app/javascript/mastodon/locales/fa.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "مسدودسازی @{name}", "account.block_domain": "پنهانسازی همه چیز از سرور {domain}", "account.blocked": "مسدودشده", @@ -125,17 +126,17 @@ "keyboard_shortcuts.boost": "برای بازبوقیدن", "keyboard_shortcuts.column": "برای برجستهکردن یک نوشته در یکی از ستونها", "keyboard_shortcuts.compose": "برای فعالکردن کادر نوشتهٔ تازه", - "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.description": "توضیح", "keyboard_shortcuts.down": "برای پایینرفتن در فهرست", - "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.enter": "برای گشودن نوشته", "keyboard_shortcuts.favourite": "برای پسندیدن", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.heading": "میانبرهای صفحهکلید", "keyboard_shortcuts.hotkey": "میانبر", "keyboard_shortcuts.legend": "برای نمایش این راهنما", "keyboard_shortcuts.mention": "برای نامبردن از نویسنده", "keyboard_shortcuts.reply": "برای پاسخدادن", "keyboard_shortcuts.search": "برای فعالکردن جستجو", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_hidden": "برای نمایش/نهفتن نوشتهٔ پشت هشدار محتوا", "keyboard_shortcuts.toot": "برای آغاز یک بوق تازه", "keyboard_shortcuts.unfocus": "برای برداشتن توجه از نوشتن/جستجو", "keyboard_shortcuts.up": "برای بالا رفتن در فهرست", @@ -211,7 +212,7 @@ "privacy.direct.short": "مستقیم", "privacy.private.long": "تنها به پیگیران نشان بده", "privacy.private.short": "خصوصی", - "privacy.public.long": "در فهرست عمومی نشان بده", + "privacy.public.long": "نمایش در فهرست عمومی", "privacy.public.short": "عمومی", "privacy.unlisted.long": "عمومی، ولی فهرست نکن", "privacy.unlisted.short": "فهرستنشده", diff --git a/app/javascript/mastodon/locales/fi.json b/app/javascript/mastodon/locales/fi.json index 07d4d9aa5..cfe9c4f33 100644 --- a/app/javascript/mastodon/locales/fi.json +++ b/app/javascript/mastodon/locales/fi.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Estä @{name}", "account.block_domain": "Piilota kaikki sisältö verkkotunnuksesta {domain}", "account.blocked": "Estetty", @@ -29,8 +30,8 @@ "account.unmute": "Poista käyttäjän @{name} mykistys", "account.unmute_notifications": "Poista mykistys käyttäjän @{name} ilmoituksilta", "account.view_full_profile": "Näytä koko profiili", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", + "alert.unexpected.message": "Tapahtui odottamaton virhe.", + "alert.unexpected.title": "Hups!", "boost_modal.combo": "Ensi kerralla voit ohittaa tämän painamalla {combo}", "bundle_column_error.body": "Jokin meni vikaan komponenttia ladattaessa.", "bundle_column_error.retry": "Yritä uudestaan", @@ -41,7 +42,7 @@ "column.blocks": "Estetyt käyttäjät", "column.community": "Paikallinen aikajana", "column.direct": "Direct messages", - "column.domain_blocks": "Hidden domains", + "column.domain_blocks": "Piilotetut verkkotunnukset", "column.favourites": "Suosikit", "column.follow_requests": "Seuraamispyynnöt", "column.home": "Koti", @@ -59,7 +60,7 @@ "column_header.unpin": "Poista kiinnitys", "column_subheading.navigation": "Navigaatio", "column_subheading.settings": "Asetukset", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", + "compose_form.direct_message_warning": "Tämä tuuttaus näkyy vain mainituille käyttäjille.", "compose_form.hashtag_warning": "Tämä tuuttaus ei näy hashtag-hauissa, koska se on listaamaton. Hashtagien avulla voi hakea vain julkisia tuuttauksia.", "compose_form.lock_disclaimer": "Tilisi ei ole {locked}. Kuka tahansa voi seurata tiliäsi ja nähdä vain seuraajille rajaamasi julkaisut.", "compose_form.lock_disclaimer.lock": "lukittu", @@ -135,7 +136,7 @@ "keyboard_shortcuts.mention": "mainitse julkaisija", "keyboard_shortcuts.reply": "vastaa", "keyboard_shortcuts.search": "siirry hakukenttään", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_hidden": "näytä/piilota sisältövaroituksella merkitty teksti", "keyboard_shortcuts.toot": "ala kirjoittaa uutta tuuttausta", "keyboard_shortcuts.unfocus": "siirry pois tekstikentästä tai hakukentästä", "keyboard_shortcuts.up": "siirry listassa ylöspäin", @@ -158,7 +159,7 @@ "navigation_bar.blocks": "Estetyt käyttäjät", "navigation_bar.community_timeline": "Paikallinen aikajana", "navigation_bar.direct": "Direct messages", - "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.domain_blocks": "Piilotetut verkkotunnukset", "navigation_bar.edit_profile": "Muokkaa profiilia", "navigation_bar.favourites": "Suosikit", "navigation_bar.follow_requests": "Seuraamispyynnöt", @@ -242,10 +243,10 @@ "search_results.total": "{count, number} {count, plural, one {result} other {results}}", "standalone.public_title": "Kurkistus sisälle...", "status.block": "Estä @{name}", - "status.cancel_reblog_private": "Unboost", + "status.cancel_reblog_private": "Peru buustaus", "status.cannot_reblog": "Tätä julkaisua ei voi buustata", "status.delete": "Poista", - "status.direct": "Direct message @{name}", + "status.direct": "Viesti käyttäjälle @{name}", "status.embed": "Upota", "status.favourite": "Tykkää", "status.load_more": "Lataa lisää", @@ -258,7 +259,7 @@ "status.pin": "Kiinnitä profiiliin", "status.pinned": "Kiinnitetty tuuttaus", "status.reblog": "Buustaa", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Buustaa alkuperäiselle yleisölle", "status.reblogged_by": "{name} buustasi", "status.reply": "Vastaa", "status.replyAll": "Vastaa ketjuun", @@ -276,7 +277,7 @@ "tabs_bar.home": "Koti", "tabs_bar.local_timeline": "Paikallinen", "tabs_bar.notifications": "Ilmoitukset", - "tabs_bar.search": "Search", + "tabs_bar.search": "Hae", "ui.beforeunload": "Luonnos häviää, jos poistut Mastodonista.", "upload_area.title": "Lataa raahaamalla ja pudottamalla tähän", "upload_button.label": "Lisää mediaa", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index 16bf4033c..b0bda275c 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloquer @{name}", "account.block_domain": "Tout masquer venant de {domain}", "account.blocked": "Bloqué", @@ -187,7 +188,7 @@ "notifications.column_settings.sound": "Émettre un son", "onboarding.done": "Effectué", "onboarding.next": "Suivant", - "onboarding.page_five.public_timelines": "Le fil public global affiche les messages de toutes les personnes suivies par les membres de {domain}. Le fil public local est identique mais se limite aux membres de {domain}.", + "onboarding.page_five.public_timelines": "Le fil public global affiche les messages de toutes les personnes suivies par les membres de {domain}. Le fil public local est identique, mais se limite aux membres de {domain}.", "onboarding.page_four.home": "L’Accueil affiche les messages des personnes que vous suivez.", "onboarding.page_four.notifications": "La colonne de notification vous avertit lors d'une interaction avec vous.", "onboarding.page_one.federation": "Mastodon est un réseau de serveurs indépendants qui se joignent pour former un réseau social plus vaste. Nous appelons ces serveurs des instances.", @@ -225,7 +226,7 @@ "reply_indicator.cancel": "Annuler", "report.forward": "Transférer à {target}", "report.forward_hint": "Le compte provient d'un autre serveur. Envoyez également une copie anonyme du rapport ?", - "report.hint": "Le rapport sera envoyé aux modérateurs de votre instance. Vous pouvez expliquer pourquoi vous signalez ce compte ci-dessous :", + "report.hint": "Le rapport sera envoyé aux modérateurs de votre instance. Vous pouvez expliquer pourquoi vous signalez le compte ci-dessous :", "report.placeholder": "Commentaires additionnels", "report.submit": "Envoyer", "report.target": "Signalement", diff --git a/app/javascript/mastodon/locales/gl.json b/app/javascript/mastodon/locales/gl.json index 652ca31d1..29885b896 100644 --- a/app/javascript/mastodon/locales/gl.json +++ b/app/javascript/mastodon/locales/gl.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloquear @{name}", "account.block_domain": "Ocultar calquer contido de {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/he.json b/app/javascript/mastodon/locales/he.json index 0ffbb14f3..a4bcba8ff 100644 --- a/app/javascript/mastodon/locales/he.json +++ b/app/javascript/mastodon/locales/he.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "חסימת @{name}", "account.block_domain": "להסתיר הכל מהקהילה {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/hr.json b/app/javascript/mastodon/locales/hr.json index c41cc3ea1..bd1dfac4c 100644 --- a/app/javascript/mastodon/locales/hr.json +++ b/app/javascript/mastodon/locales/hr.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokiraj @{name}", "account.block_domain": "Sakrij sve sa {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/hu.json b/app/javascript/mastodon/locales/hu.json index a0c186184..5059a45d4 100644 --- a/app/javascript/mastodon/locales/hu.json +++ b/app/javascript/mastodon/locales/hu.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "@{name} letiltása", "account.block_domain": "Minden elrejtése innen: {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/hy.json b/app/javascript/mastodon/locales/hy.json index a0442bad4..7fe723892 100644 --- a/app/javascript/mastodon/locales/hy.json +++ b/app/javascript/mastodon/locales/hy.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Արգելափակել @{name}֊ին", "account.block_domain": "Թաքցնել ամենը հետեւյալ տիրույթից՝ {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/id.json b/app/javascript/mastodon/locales/id.json index 2fd922544..07b26a0a5 100644 --- a/app/javascript/mastodon/locales/id.json +++ b/app/javascript/mastodon/locales/id.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokir @{name}", "account.block_domain": "Sembunyikan segalanya dari {domain}", "account.blocked": "Terblokir", diff --git a/app/javascript/mastodon/locales/io.json b/app/javascript/mastodon/locales/io.json index ed45ee11e..a8ab72339 100644 --- a/app/javascript/mastodon/locales/io.json +++ b/app/javascript/mastodon/locales/io.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokusar @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/it.json b/app/javascript/mastodon/locales/it.json index a7ca62015..9d3486152 100644 --- a/app/javascript/mastodon/locales/it.json +++ b/app/javascript/mastodon/locales/it.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blocca @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Bloccato", diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json index dbb4562de..1bdf34a81 100644 --- a/app/javascript/mastodon/locales/ja.json +++ b/app/javascript/mastodon/locales/ja.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "@{name}さんをブロック", "account.block_domain": "{domain}全体を非表示", "account.blocked": "ブロック済み", diff --git a/app/javascript/mastodon/locales/ko.json b/app/javascript/mastodon/locales/ko.json index 2a2734673..e72a7dff9 100644 --- a/app/javascript/mastodon/locales/ko.json +++ b/app/javascript/mastodon/locales/ko.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "@{name}을 차단", "account.block_domain": "{domain} 전체를 숨김", "account.blocked": "차단 됨", @@ -29,9 +30,9 @@ "account.unmute": "뮤트 해제", "account.unmute_notifications": "@{name}의 알림 뮤트 해제", "account.view_full_profile": "전체 프로필 보기", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", - "boost_modal.combo": "다음부터 {combo}를 누르면 이 과정을 건너뛸 수 있습니다.", + "alert.unexpected.message": "예측하지 못한 에러가 발생했습니다.", + "alert.unexpected.title": "앗!", + "boost_modal.combo": "{combo}를 누르면 다음부터 이 과정을 건너뛸 수 있습니다", "bundle_column_error.body": "컴포넌트를 불러오는 과정에서 문제가 발생했습니다.", "bundle_column_error.retry": "다시 시도", "bundle_column_error.title": "네트워크 에러", @@ -40,8 +41,8 @@ "bundle_modal_error.retry": "다시 시도", "column.blocks": "차단 중인 사용자", "column.community": "로컬 타임라인", - "column.direct": "Direct messages", - "column.domain_blocks": "Hidden domains", + "column.direct": "다이렉트 메시지", + "column.domain_blocks": "숨겨진 도메인", "column.favourites": "즐겨찾기", "column.follow_requests": "팔로우 요청", "column.home": "홈", @@ -59,17 +60,17 @@ "column_header.unpin": "고정 해제", "column_subheading.navigation": "내비게이션", "column_subheading.settings": "설정", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", + "compose_form.direct_message_warning": "이 툿은 멘션 된 유저들에게만 보여집니다.", "compose_form.hashtag_warning": "이 툿은 어떤 해시태그로도 검색 되지 않습니다. 전체공개로 게시 된 툿만이 해시태그로 검색 될 수 있습니다.", "compose_form.lock_disclaimer": "이 계정은 {locked}로 설정 되어 있지 않습니다. 누구나 이 계정을 팔로우 할 수 있으며, 팔로워 공개의 포스팅을 볼 수 있습니다.", "compose_form.lock_disclaimer.lock": "비공개", "compose_form.placeholder": "지금 무엇을 하고 있나요?", "compose_form.publish": "툿", "compose_form.publish_loud": "{publish}!", - "compose_form.sensitive.marked": "Media is marked as sensitive", - "compose_form.sensitive.unmarked": "Media is not marked as sensitive", - "compose_form.spoiler.marked": "Text is hidden behind warning", - "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.sensitive.marked": "미디어가 열람주의로 설정되어 있습니다", + "compose_form.sensitive.unmarked": "미디어가 열람주의로 설정 되어 있지 않습니다", + "compose_form.spoiler.marked": "열람주의가 설정되어 있습니다", + "compose_form.spoiler.unmarked": "열람주의가 설정 되어 있지 않습니다", "compose_form.spoiler_placeholder": "경고", "confirmation_modal.cancel": "취소", "confirmations.block.confirm": "차단", @@ -101,13 +102,13 @@ "emoji_button.symbols": "기호", "emoji_button.travel": "여행과 장소", "empty_column.community": "로컬 타임라인에 아무 것도 없습니다. 아무거나 적어 보세요!", - "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.direct": "아직 다이렉트 메시지가 없습니다. 다이렉트 메시지를 보내거나 받은 경우, 여기에 표시 됩니다.", "empty_column.hashtag": "이 해시태그는 아직 사용되지 않았습니다.", "empty_column.home": "아직 아무도 팔로우 하고 있지 않습니다. {public}를 보러 가거나, 검색하여 다른 사용자를 찾아 보세요.", "empty_column.home.public_timeline": "연합 타임라인", "empty_column.list": "리스트에 아직 아무 것도 없습니다.", - "empty_column.notifications": "아직 알림이 없습니다. 다른 사람과 대화를 시작해 보세요!", - "empty_column.public": "여기엔 아직 아무 것도 없습니다! 공개적으로 무언가 포스팅하거나, 다른 인스턴스 유저를 팔로우 해서 가득 채워보세요!", + "empty_column.notifications": "아직 알림이 없습니다. 다른 사람과 대화를 시작해 보세요.", + "empty_column.public": "여기엔 아직 아무 것도 없습니다! 공개적으로 무언가 포스팅하거나, 다른 인스턴스의 유저를 팔로우 해서 채워보세요", "follow_request.authorize": "허가", "follow_request.reject": "거부", "getting_started.appsshort": "애플리케이션", @@ -135,7 +136,7 @@ "keyboard_shortcuts.mention": "멘션", "keyboard_shortcuts.reply": "답장", "keyboard_shortcuts.search": "검색창에 포커스", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_hidden": "CW로 가려진 텍스트를 표시/비표시", "keyboard_shortcuts.toot": "새 툿 작성", "keyboard_shortcuts.unfocus": "작성창에서 포커스 해제", "keyboard_shortcuts.up": "리스트에서 위로 이동", @@ -157,8 +158,8 @@ "mute_modal.hide_notifications": "이 사용자로부터의 알림을 뮤트하시겠습니까?", "navigation_bar.blocks": "차단한 사용자", "navigation_bar.community_timeline": "로컬 타임라인", - "navigation_bar.direct": "Direct messages", - "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.direct": "다이렉트 메시지", + "navigation_bar.domain_blocks": "숨겨진 도메인", "navigation_bar.edit_profile": "프로필 편집", "navigation_bar.favourites": "즐겨찾기", "navigation_bar.follow_requests": "팔로우 요청", @@ -177,12 +178,12 @@ "notifications.clear": "알림 지우기", "notifications.clear_confirmation": "정말로 알림을 삭제하시겠습니까?", "notifications.column_settings.alert": "데스크탑 알림", - "notifications.column_settings.favourite": "즐겨찾기", - "notifications.column_settings.follow": "새 팔로워", - "notifications.column_settings.mention": "답글", + "notifications.column_settings.favourite": "즐겨찾기:", + "notifications.column_settings.follow": "새 팔로워:", + "notifications.column_settings.mention": "답글:", "notifications.column_settings.push": "푸시 알림", "notifications.column_settings.push_meta": "이 장치", - "notifications.column_settings.reblog": "부스트", + "notifications.column_settings.reblog": "부스트:", "notifications.column_settings.show": "컬럼에 표시", "notifications.column_settings.sound": "효과음 재생", "onboarding.done": "완료", @@ -200,7 +201,7 @@ "onboarding.page_six.apps_available": "iOS、Android 또는 다른 플랫폼에서 사용할 수 있는 {apps}이 있습니다.", "onboarding.page_six.github": "Mastodon는 오픈 소스 소프트웨어입니다. 버그 보고나 기능 추가 요청, 기여는 {github}에서 할 수 있습니다.", "onboarding.page_six.guidelines": "커뮤니티 가이드라인", - "onboarding.page_six.read_guidelines": "{guidelines}을 확인하는 것을 잊지 마세요.", + "onboarding.page_six.read_guidelines": "{domain}의 {guidelines}을 확인하는 것을 잊지 마세요!", "onboarding.page_six.various_app": "다양한 모바일 애플리케이션", "onboarding.page_three.profile": "[프로필 편집] 에서 자기 소개나 이름을 변경할 수 있습니다. 또한 다른 설정도 변경할 수 있습니다.", "onboarding.page_three.search": "검색 바에서 {illustration} 나 {introductions} 와 같이 특정 해시태그가 달린 포스트를 보거나, 사용자를 찾을 수 있습니다.", @@ -242,10 +243,10 @@ "search_results.total": "{count, number}건의 결과", "standalone.public_title": "지금 이런 이야기를 하고 있습니다…", "status.block": "@{name} 차단", - "status.cancel_reblog_private": "Unboost", + "status.cancel_reblog_private": "부스트 취소", "status.cannot_reblog": "이 포스트는 부스트 할 수 없습니다", "status.delete": "삭제", - "status.direct": "Direct message @{name}", + "status.direct": "@{name}에게 다이렉트 메시지", "status.embed": "공유하기", "status.favourite": "즐겨찾기", "status.load_more": "더 보기", @@ -258,7 +259,7 @@ "status.pin": "고정", "status.pinned": "고정 된 툿", "status.reblog": "부스트", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "원래의 수신자들에게 부스트", "status.reblogged_by": "{name}님이 부스트 했습니다", "status.reply": "답장", "status.replyAll": "전원에게 답장", @@ -267,16 +268,16 @@ "status.sensitive_warning": "민감한 미디어", "status.share": "공유", "status.show_less": "숨기기", - "status.show_less_all": "Show less for all", + "status.show_less_all": "모두 접기", "status.show_more": "더 보기", - "status.show_more_all": "Show more for all", + "status.show_more_all": "모두 펼치기", "status.unmute_conversation": "이 대화의 뮤트 해제하기", "status.unpin": "고정 해제", "tabs_bar.federated_timeline": "연합", "tabs_bar.home": "홈", "tabs_bar.local_timeline": "로컬", "tabs_bar.notifications": "알림", - "tabs_bar.search": "Search", + "tabs_bar.search": "검색", "ui.beforeunload": "지금 나가면 저장되지 않은 항목을 잃게 됩니다.", "upload_area.title": "드래그 & 드롭으로 업로드", "upload_button.label": "미디어 추가", diff --git a/app/javascript/mastodon/locales/nl.json b/app/javascript/mastodon/locales/nl.json index adc1d19a7..a6bfe36f9 100644 --- a/app/javascript/mastodon/locales/nl.json +++ b/app/javascript/mastodon/locales/nl.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokkeer @{name}", "account.block_domain": "Negeer alles van {domain}", "account.blocked": "Geblokkeerd", @@ -50,7 +51,7 @@ "column.notifications": "Meldingen", "column.pins": "Vastgezette toots", "column.public": "Globale tijdlijn", - "column_back_button.label": "terug", + "column_back_button.label": "Terug", "column_header.hide_settings": "Instellingen verbergen", "column_header.moveLeft_settings": "Kolom naar links verplaatsen", "column_header.moveRight_settings": "Kolom naar rechts verplaatsen", @@ -61,7 +62,7 @@ "column_subheading.settings": "Instellingen", "compose_form.direct_message_warning": "Deze toot zal alleen zichtbaar zijn voor alle vermelde gebruikers.", "compose_form.hashtag_warning": "Deze toot valt niet onder een hashtag te bekijken, omdat deze niet op openbare tijdlijnen wordt getoond. Alleen openbare toots kunnen via hashtags gevonden worden.", - "compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en toots zien die je alleen aan volgers hebt gericht.", + "compose_form.lock_disclaimer": "Jouw account is niet {locked}. Iedereen kan jou volgen en kan de toots zien die je alleen aan jouw volgers hebt gericht.", "compose_form.lock_disclaimer.lock": "besloten", "compose_form.placeholder": "Wat wil je kwijt?", "compose_form.publish": "Toot", @@ -76,10 +77,10 @@ "confirmations.block.message": "Weet je het zeker dat je {name} wilt blokkeren?", "confirmations.delete.confirm": "Verwijderen", "confirmations.delete.message": "Weet je het zeker dat je deze toot wilt verwijderen?", - "confirmations.delete_list.confirm": "Delete", + "confirmations.delete_list.confirm": "Verwijderen", "confirmations.delete_list.message": "Weet je zeker dat je deze lijst definitief wilt verwijderen?", "confirmations.domain_block.confirm": "Negeer alles van deze server", - "confirmations.domain_block.message": "Weet je het echt, echt zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gewenst.", + "confirmations.domain_block.message": "Weet je het echt heel erg zeker dat je alles van {domain} wil negeren? In de meeste gevallen is het blokkeren of negeren van een paar specifieke personen voldoende en gepaster.", "confirmations.mute.confirm": "Negeren", "confirmations.mute.message": "Weet je het zeker dat je {name} wilt negeren?", "confirmations.unfollow.confirm": "Ontvolgen", @@ -106,13 +107,13 @@ "empty_column.home": "Jij volgt nog niemand. Bezoek {public} of gebruik het zoekvenster om andere mensen te ontmoeten.", "empty_column.home.public_timeline": "de globale tijdlijn", "empty_column.list": "Er is nog niks in deze lijst. Wanneer lijstleden nieuwe toots publiceren, zijn deze hier te zien.", - "empty_column.notifications": "Je hebt nog geen meldingen. Heb interactie met andere mensen om het gesprek aan te gaan.", + "empty_column.notifications": "Je hebt nog geen meldingen. Begin met iemand een gesprek.", "empty_column.public": "Er is hier helemaal niks! Toot iets in het openbaar of volg mensen van andere servers om het te vullen", "follow_request.authorize": "Goedkeuren", "follow_request.reject": "Afkeuren", "getting_started.appsshort": "Apps", "getting_started.faq": "FAQ", - "getting_started.heading": "Beginnen", + "getting_started.heading": "Aan de slag", "getting_started.open_source_notice": "Mastodon is vrije software. Je kunt bijdragen of problemen melden op GitHub via {github}.", "getting_started.userguide": "Gebruikersgids", "home.column_settings.advanced": "Geavanceerd", @@ -131,7 +132,7 @@ "keyboard_shortcuts.favourite": "om als favoriet te markeren", "keyboard_shortcuts.heading": "Sneltoetsen", "keyboard_shortcuts.hotkey": "Sneltoets", - "keyboard_shortcuts.legend": "om deze legenda weer te geven", + "keyboard_shortcuts.legend": "om deze legenda te tonen", "keyboard_shortcuts.mention": "om de auteur te vermelden", "keyboard_shortcuts.reply": "om te reageren", "keyboard_shortcuts.search": "om het zoekvak te focussen", @@ -187,7 +188,7 @@ "notifications.column_settings.sound": "Geluid afspelen", "onboarding.done": "Klaar", "onboarding.next": "Volgende", - "onboarding.page_five.public_timelines": "De lokale tijdlijn toont openbare toots van iedereen op {domain}. De globale tijdlijn toont openbare toots van iedereen die door gebruikers van {domain} worden gevolgd, dus ook mensen van andere Mastodonservers. Dit zijn de openbare tijdlijnen en vormen een uitstekende manier om nieuwe mensen te ontdekken.", + "onboarding.page_five.public_timelines": "De lokale tijdlijn toont openbare toots van iedereen op {domain}. De globale tijdlijn toont openbare toots van iedereen die door gebruikers van {domain} worden gevolgd, dus ook mensen van andere Mastodonservers. Dit zijn de openbare tijdlijnen en vormen een uitstekende manier om nieuwe mensen te leren kennen.", "onboarding.page_four.home": "Deze tijdlijn laat toots zien van mensen die jij volgt.", "onboarding.page_four.notifications": "De kolom met meldingen toont alle interacties die je met andere Mastodongebruikers hebt.", "onboarding.page_one.federation": "Mastodon is een netwerk van onafhankelijke servers die samen een groot sociaal netwerk vormen.", @@ -231,7 +232,7 @@ "report.target": "Rapporteer {target}", "search.placeholder": "Zoeken", "search_popout.search_format": "Geavanceerd zoeken", - "search_popout.tips.full_text": "Gebruik gewone tekst om te zoeken naar jouw toots, gebooste toots, favorieten en naar toots waarin jij bent vermeldt, en naar gebruikersnamen, weergavenamen en hashtags.", + "search_popout.tips.full_text": "Gebruik gewone tekst om te zoeken in jouw toots, gebooste toots, favorieten en in toots waarin jij bent vermeldt, en tevens naar gebruikersnamen, weergavenamen en hashtags.", "search_popout.tips.hashtag": "hashtag", "search_popout.tips.status": "toot", "search_popout.tips.text": "Gebruik gewone tekst om te zoeken op weergavenamen, gebruikersnamen en hashtags", @@ -253,7 +254,7 @@ "status.mention": "Vermeld @{name}", "status.more": "Meer", "status.mute": "Negeer @{name}", - "status.mute_conversation": "Negeer conversatie", + "status.mute_conversation": "Negeer gesprek", "status.open": "Toot volledig tonen", "status.pin": "Aan profielpagina vastmaken", "status.pinned": "Vastgemaakte toot", diff --git a/app/javascript/mastodon/locales/no.json b/app/javascript/mastodon/locales/no.json index 0ee6d0722..05dae0630 100644 --- a/app/javascript/mastodon/locales/no.json +++ b/app/javascript/mastodon/locales/no.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokkér @{name}", "account.block_domain": "Skjul alt fra {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index c4cb996cf..ead57d63f 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blocar @{name}", "account.block_domain": "Tot amagar del domeni {domain}", "account.blocked": "Blocat", diff --git a/app/javascript/mastodon/locales/pl.json b/app/javascript/mastodon/locales/pl.json index 6d6db7c82..120edcb1c 100644 --- a/app/javascript/mastodon/locales/pl.json +++ b/app/javascript/mastodon/locales/pl.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokuj @{name}", "account.block_domain": "Blokuj wszystko z {domain}", "account.blocked": "Zablokowany", diff --git a/app/javascript/mastodon/locales/pt-BR.json b/app/javascript/mastodon/locales/pt-BR.json index 7f8690f91..2360c41e7 100644 --- a/app/javascript/mastodon/locales/pt-BR.json +++ b/app/javascript/mastodon/locales/pt-BR.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloquear @{name}", "account.block_domain": "Esconder tudo de {domain}", "account.blocked": "Bloqueado", diff --git a/app/javascript/mastodon/locales/pt.json b/app/javascript/mastodon/locales/pt.json index ce816dc41..3ac92dd57 100644 --- a/app/javascript/mastodon/locales/pt.json +++ b/app/javascript/mastodon/locales/pt.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Bloquear @{name}", "account.block_domain": "Esconder tudo do domínio {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/ru.json b/app/javascript/mastodon/locales/ru.json index 8eeebaf73..599873439 100644 --- a/app/javascript/mastodon/locales/ru.json +++ b/app/javascript/mastodon/locales/ru.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Блокировать", "account.block_domain": "Блокировать все с {domain}", "account.blocked": "Заблокирован(а)", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index d69648ccf..1cf7dee80 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokovať @{name}", "account.block_domain": "Ukryť všetko z {domain}", "account.blocked": "Blokovaný/á", diff --git a/app/javascript/mastodon/locales/sl.json b/app/javascript/mastodon/locales/sl.json new file mode 100644 index 000000000..202dc4bd0 --- /dev/null +++ b/app/javascript/mastodon/locales/sl.json @@ -0,0 +1,297 @@ +{ + "account.badges.bot": "Bot", + "account.block": "Blokiraj @{name}", + "account.block_domain": "Skrij vse iz {domain}", + "account.blocked": "Blokirano", + "account.direct": "Neposredno sporočilo @{name}", + "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", + "account.domain_blocked": "Domain hidden", + "account.edit_profile": "Edit profile", + "account.follow": "Follow", + "account.followers": "Followers", + "account.follows": "Follows", + "account.follows_you": "Follows you", + "account.hide_reblogs": "Hide boosts from @{name}", + "account.media": "Media", + "account.mention": "Mention @{name}", + "account.moved_to": "{name} has moved to:", + "account.mute": "Mute @{name}", + "account.mute_notifications": "Mute notifications from @{name}", + "account.muted": "Muted", + "account.posts": "Toots", + "account.posts_with_replies": "Toots and replies", + "account.report": "Report @{name}", + "account.requested": "Awaiting approval. Click to cancel follow request", + "account.share": "Share @{name}'s profile", + "account.show_reblogs": "Show boosts from @{name}", + "account.unblock": "Unblock @{name}", + "account.unblock_domain": "Unhide {domain}", + "account.unfollow": "Unfollow", + "account.unmute": "Unmute @{name}", + "account.unmute_notifications": "Unmute notifications from @{name}", + "account.view_full_profile": "View full profile", + "alert.unexpected.message": "An unexpected error occurred.", + "alert.unexpected.title": "Oops!", + "boost_modal.combo": "You can press {combo} to skip this next time", + "bundle_column_error.body": "Something went wrong while loading this component.", + "bundle_column_error.retry": "Try again", + "bundle_column_error.title": "Network error", + "bundle_modal_error.close": "Close", + "bundle_modal_error.message": "Something went wrong while loading this component.", + "bundle_modal_error.retry": "Try again", + "column.blocks": "Blocked users", + "column.community": "Local timeline", + "column.direct": "Direct messages", + "column.domain_blocks": "Hidden domains", + "column.favourites": "Favourites", + "column.follow_requests": "Follow requests", + "column.home": "Home", + "column.lists": "Lists", + "column.mutes": "Muted users", + "column.notifications": "Notifications", + "column.pins": "Pinned toot", + "column.public": "Federated timeline", + "column_back_button.label": "Back", + "column_header.hide_settings": "Hide settings", + "column_header.moveLeft_settings": "Move column to the left", + "column_header.moveRight_settings": "Move column to the right", + "column_header.pin": "Pin", + "column_header.show_settings": "Show settings", + "column_header.unpin": "Unpin", + "column_subheading.navigation": "Navigation", + "column_subheading.settings": "Settings", + "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", + "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", + "compose_form.lock_disclaimer": "Your account is not {locked}. Anyone can follow you to view your follower-only posts.", + "compose_form.lock_disclaimer.lock": "locked", + "compose_form.placeholder": "What is on your mind?", + "compose_form.publish": "Toot", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.marked": "Media is marked as sensitive", + "compose_form.sensitive.unmarked": "Media is not marked as sensitive", + "compose_form.spoiler.marked": "Text is hidden behind warning", + "compose_form.spoiler.unmarked": "Text is not hidden", + "compose_form.spoiler_placeholder": "Write your warning here", + "confirmation_modal.cancel": "Cancel", + "confirmations.block.confirm": "Block", + "confirmations.block.message": "Are you sure you want to block {name}?", + "confirmations.delete.confirm": "Delete", + "confirmations.delete.message": "Are you sure you want to delete this status?", + "confirmations.delete_list.confirm": "Delete", + "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "confirmations.domain_block.confirm": "Hide entire domain", + "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", + "confirmations.mute.confirm": "Mute", + "confirmations.mute.message": "Are you sure you want to mute {name}?", + "confirmations.unfollow.confirm": "Unfollow", + "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", + "embed.instructions": "Embed this status on your website by copying the code below.", + "embed.preview": "Here is what it will look like:", + "emoji_button.activity": "Activity", + "emoji_button.custom": "Custom", + "emoji_button.flags": "Flags", + "emoji_button.food": "Food & Drink", + "emoji_button.label": "Insert emoji", + "emoji_button.nature": "Nature", + "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Objects", + "emoji_button.people": "People", + "emoji_button.recent": "Frequently used", + "emoji_button.search": "Search...", + "emoji_button.search_results": "Search results", + "emoji_button.symbols": "Symbols", + "emoji_button.travel": "Travel & Places", + "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", + "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.hashtag": "There is nothing in this hashtag yet.", + "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", + "empty_column.home.public_timeline": "the public timeline", + "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", + "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", + "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", + "follow_request.authorize": "Authorize", + "follow_request.reject": "Reject", + "getting_started.appsshort": "Apps", + "getting_started.faq": "FAQ", + "getting_started.heading": "Getting started", + "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", + "getting_started.userguide": "User Guide", + "home.column_settings.advanced": "Advanced", + "home.column_settings.basic": "Basic", + "home.column_settings.filter_regex": "Filter out by regular expressions", + "home.column_settings.show_reblogs": "Show boosts", + "home.column_settings.show_replies": "Show replies", + "home.settings": "Column settings", + "keyboard_shortcuts.back": "to navigate back", + "keyboard_shortcuts.boost": "to boost", + "keyboard_shortcuts.column": "to focus a status in one of the columns", + "keyboard_shortcuts.compose": "to focus the compose textarea", + "keyboard_shortcuts.description": "Description", + "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.enter": "to open status", + "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.heading": "Keyboard Shortcuts", + "keyboard_shortcuts.hotkey": "Hotkey", + "keyboard_shortcuts.legend": "to display this legend", + "keyboard_shortcuts.mention": "to mention author", + "keyboard_shortcuts.reply": "to reply", + "keyboard_shortcuts.search": "to focus search", + "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", + "keyboard_shortcuts.up": "to move up in the list", + "lightbox.close": "Close", + "lightbox.next": "Next", + "lightbox.previous": "Previous", + "lists.account.add": "Add to list", + "lists.account.remove": "Remove from list", + "lists.delete": "Delete list", + "lists.edit": "Edit list", + "lists.new.create": "Add list", + "lists.new.title_placeholder": "New list title", + "lists.search": "Search among people you follow", + "lists.subheading": "Your lists", + "loading_indicator.label": "Loading...", + "media_gallery.toggle_visible": "Toggle visibility", + "missing_indicator.label": "Not found", + "missing_indicator.sublabel": "This resource could not be found", + "mute_modal.hide_notifications": "Hide notifications from this user?", + "navigation_bar.blocks": "Blocked users", + "navigation_bar.community_timeline": "Local timeline", + "navigation_bar.direct": "Direct messages", + "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.edit_profile": "Edit profile", + "navigation_bar.favourites": "Favourites", + "navigation_bar.follow_requests": "Follow requests", + "navigation_bar.info": "Extended information", + "navigation_bar.keyboard_shortcuts": "Keyboard shortcuts", + "navigation_bar.lists": "Lists", + "navigation_bar.logout": "Logout", + "navigation_bar.mutes": "Muted users", + "navigation_bar.pins": "Pinned toots", + "navigation_bar.preferences": "Preferences", + "navigation_bar.public_timeline": "Federated timeline", + "notification.favourite": "{name} favourited your status", + "notification.follow": "{name} followed you", + "notification.mention": "{name} mentioned you", + "notification.reblog": "{name} boosted your status", + "notifications.clear": "Clear notifications", + "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?", + "notifications.column_settings.alert": "Desktop notifications", + "notifications.column_settings.favourite": "Favourites:", + "notifications.column_settings.follow": "New followers:", + "notifications.column_settings.mention": "Mentions:", + "notifications.column_settings.push": "Push notifications", + "notifications.column_settings.push_meta": "This device", + "notifications.column_settings.reblog": "Boosts:", + "notifications.column_settings.show": "Show in column", + "notifications.column_settings.sound": "Play sound", + "onboarding.done": "Done", + "onboarding.next": "Next", + "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", + "onboarding.page_four.home": "The home timeline shows posts from people you follow.", + "onboarding.page_four.notifications": "The notifications column shows when someone interacts with you.", + "onboarding.page_one.federation": "Mastodon is a network of independent servers joining up to make one larger social network. We call these servers instances.", + "onboarding.page_one.full_handle": "Your full handle", + "onboarding.page_one.handle_hint": "This is what you would tell your friends to search for.", + "onboarding.page_one.welcome": "Welcome to Mastodon!", + "onboarding.page_six.admin": "Your instance's admin is {admin}.", + "onboarding.page_six.almost_done": "Almost done...", + "onboarding.page_six.appetoot": "Bon Appetoot!", + "onboarding.page_six.apps_available": "There are {apps} available for iOS, Android and other platforms.", + "onboarding.page_six.github": "Mastodon is free open-source software. You can report bugs, request features, or contribute to the code on {github}.", + "onboarding.page_six.guidelines": "community guidelines", + "onboarding.page_six.read_guidelines": "Please read {domain}'s {guidelines}!", + "onboarding.page_six.various_app": "mobile apps", + "onboarding.page_three.profile": "Edit your profile to change your avatar, bio, and display name. There, you will also find other preferences.", + "onboarding.page_three.search": "Use the search bar to find people and look at hashtags, such as {illustration} and {introductions}. To look for a person who is not on this instance, use their full handle.", + "onboarding.page_two.compose": "Write posts from the compose column. You can upload images, change privacy settings, and add content warnings with the icons below.", + "onboarding.skip": "Skip", + "privacy.change": "Adjust status privacy", + "privacy.direct.long": "Post to mentioned users only", + "privacy.direct.short": "Direct", + "privacy.private.long": "Post to followers only", + "privacy.private.short": "Followers-only", + "privacy.public.long": "Post to public timelines", + "privacy.public.short": "Public", + "privacy.unlisted.long": "Do not show in public timelines", + "privacy.unlisted.short": "Unlisted", + "regeneration_indicator.label": "Loading…", + "regeneration_indicator.sublabel": "Your home feed is being prepared!", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "now", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "reply_indicator.cancel": "Cancel", + "report.forward": "Forward to {target}", + "report.forward_hint": "The account is from another server. Send an anonymized copy of the report there as well?", + "report.hint": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:", + "report.placeholder": "Additional comments", + "report.submit": "Submit", + "report.target": "Report {target}", + "search.placeholder": "Search", + "search_popout.search_format": "Advanced search format", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "search_popout.tips.status": "status", + "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.user": "user", + "search_results.accounts": "People", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Toots", + "search_results.total": "{count, number} {count, plural, one {result} other {results}}", + "standalone.public_title": "A look inside...", + "status.block": "Block @{name}", + "status.cancel_reblog_private": "Unboost", + "status.cannot_reblog": "This post cannot be boosted", + "status.delete": "Delete", + "status.direct": "Direct message @{name}", + "status.embed": "Embed", + "status.favourite": "Favourite", + "status.load_more": "Load more", + "status.media_hidden": "Media hidden", + "status.mention": "Mention @{name}", + "status.more": "More", + "status.mute": "Mute @{name}", + "status.mute_conversation": "Mute conversation", + "status.open": "Expand this status", + "status.pin": "Pin on profile", + "status.pinned": "Pinned toot", + "status.reblog": "Boost", + "status.reblog_private": "Boost to original audience", + "status.reblogged_by": "{name} boosted", + "status.reply": "Reply", + "status.replyAll": "Reply to thread", + "status.report": "Report @{name}", + "status.sensitive_toggle": "Click to view", + "status.sensitive_warning": "Sensitive content", + "status.share": "Share", + "status.show_less": "Show less", + "status.show_less_all": "Show less for all", + "status.show_more": "Show more", + "status.show_more_all": "Show more for all", + "status.unmute_conversation": "Unmute conversation", + "status.unpin": "Unpin from profile", + "tabs_bar.federated_timeline": "Federated", + "tabs_bar.home": "Home", + "tabs_bar.local_timeline": "Local", + "tabs_bar.notifications": "Notifications", + "tabs_bar.search": "Search", + "ui.beforeunload": "Your draft will be lost if you leave Mastodon.", + "upload_area.title": "Drag & drop to upload", + "upload_button.label": "Add media", + "upload_form.description": "Describe for the visually impaired", + "upload_form.focus": "Crop", + "upload_form.undo": "Undo", + "upload_progress.label": "Uploading...", + "video.close": "Close video", + "video.exit_fullscreen": "Exit full screen", + "video.expand": "Expand video", + "video.fullscreen": "Full screen", + "video.hide": "Hide video", + "video.mute": "Mute sound", + "video.pause": "Pause", + "video.play": "Play", + "video.unmute": "Unmute sound" +} diff --git a/app/javascript/mastodon/locales/sr-Latn.json b/app/javascript/mastodon/locales/sr-Latn.json index b1ea0d179..490b3a51a 100644 --- a/app/javascript/mastodon/locales/sr-Latn.json +++ b/app/javascript/mastodon/locales/sr-Latn.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blokiraj korisnika @{name}", "account.block_domain": "Sakrij sve sa domena {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/sr.json b/app/javascript/mastodon/locales/sr.json index aa978675f..b331f9f48 100644 --- a/app/javascript/mastodon/locales/sr.json +++ b/app/javascript/mastodon/locales/sr.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Блокирај корисника @{name}", "account.block_domain": "Сакриј све са домена {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/sv.json b/app/javascript/mastodon/locales/sv.json index 4efe88a7e..36b200764 100644 --- a/app/javascript/mastodon/locales/sv.json +++ b/app/javascript/mastodon/locales/sv.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Blockera @{name}", "account.block_domain": "Dölj allt från {domain}", "account.blocked": "Blockerad", diff --git a/app/javascript/mastodon/locales/te.json b/app/javascript/mastodon/locales/te.json index a56720fee..038ac6abb 100644 --- a/app/javascript/mastodon/locales/te.json +++ b/app/javascript/mastodon/locales/te.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Block @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/th.json b/app/javascript/mastodon/locales/th.json index 82b44fe30..8d24395af 100644 --- a/app/javascript/mastodon/locales/th.json +++ b/app/javascript/mastodon/locales/th.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Block @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/tr.json b/app/javascript/mastodon/locales/tr.json index 056fbfe8f..a377e7b74 100644 --- a/app/javascript/mastodon/locales/tr.json +++ b/app/javascript/mastodon/locales/tr.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Engelle @{name}", "account.block_domain": "Hide everything from {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/uk.json b/app/javascript/mastodon/locales/uk.json index 1a7b58789..613d1a00d 100644 --- a/app/javascript/mastodon/locales/uk.json +++ b/app/javascript/mastodon/locales/uk.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "Заблокувати", "account.block_domain": "Заглушити {domain}", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/whitelist_sl.json b/app/javascript/mastodon/locales/whitelist_sl.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_sl.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/locales/zh-CN.json b/app/javascript/mastodon/locales/zh-CN.json index a3a4de0af..073dbe6cb 100644 --- a/app/javascript/mastodon/locales/zh-CN.json +++ b/app/javascript/mastodon/locales/zh-CN.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "屏蔽 @{name}", "account.block_domain": "隐藏来自 {domain} 的内容", "account.blocked": "Blocked", diff --git a/app/javascript/mastodon/locales/zh-HK.json b/app/javascript/mastodon/locales/zh-HK.json index 7719e08a6..0c012aa7d 100644 --- a/app/javascript/mastodon/locales/zh-HK.json +++ b/app/javascript/mastodon/locales/zh-HK.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "封鎖 @{name}", "account.block_domain": "隱藏來自 {domain} 的一切文章", "account.blocked": "封鎖", diff --git a/app/javascript/mastodon/locales/zh-TW.json b/app/javascript/mastodon/locales/zh-TW.json index 84ff25e03..0f4d04947 100644 --- a/app/javascript/mastodon/locales/zh-TW.json +++ b/app/javascript/mastodon/locales/zh-TW.json @@ -1,4 +1,5 @@ { + "account.badges.bot": "Bot", "account.block": "封鎖 @{name}", "account.block_domain": "隱藏來自 {domain} 的一切貼文", "account.blocked": "已被封鎖的", diff --git a/app/lib/request.rb b/app/lib/request.rb index fc7d398e0..731bf7687 100644 --- a/app/lib/request.rb +++ b/app/lib/request.rb @@ -51,16 +51,17 @@ class Request end def headers - (@account ? @headers.merge('Signature' => signature) : @headers).reverse_merge('Accept-Encoding' => 'gzip').without(REQUEST_TARGET) + (@account ? @headers.merge('Signature' => signature) : @headers).without(REQUEST_TARGET) end private def set_common_headers! - @headers[REQUEST_TARGET] = "#{@verb} #{@url.path}" - @headers['User-Agent'] = user_agent - @headers['Host'] = @url.host - @headers['Date'] = Time.now.utc.httpdate + @headers[REQUEST_TARGET] = "#{@verb} #{@url.path}" + @headers['User-Agent'] = user_agent + @headers['Host'] = @url.host + @headers['Date'] = Time.now.utc.httpdate + @headers['Accept-Encoding'] = 'gzip' if @verb != :head end def set_digest! diff --git a/app/models/concerns/remotable.rb b/app/models/concerns/remotable.rb index 7f1ef5191..20ddbca53 100644 --- a/app/models/concerns/remotable.rb +++ b/app/models/concerns/remotable.rb @@ -41,6 +41,9 @@ module Remotable rescue HTTP::TimeoutError, HTTP::ConnectionError, OpenSSL::SSL::SSLError, Paperclip::Errors::NotIdentifiedByImageMagickError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e Rails.logger.debug "Error fetching remote #{attachment_name}: #{e}" nil + rescue Paperclip::Error => e + Rails.logger.debug "Error processing remote #{attachment_name}: #{e}" + nil end end diff --git a/app/models/user.rb b/app/models/user.rb index 82d165079..d5ca9be36 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -245,7 +245,7 @@ class User < ApplicationRecord end def web_push_subscription(session) - session.web_push_subscription.nil? ? nil : session.web_push_subscription.as_payload + session.web_push_subscription.nil? ? nil : session.web_push_subscription end def invite_code=(code) diff --git a/app/models/web/push_subscription.rb b/app/models/web/push_subscription.rb index 1736106f7..df549c6d3 100644 --- a/app/models/web/push_subscription.rb +++ b/app/models/web/push_subscription.rb @@ -3,38 +3,51 @@ # # Table name: web_push_subscriptions # -# id :bigint(8) not null, primary key -# endpoint :string not null -# key_p256dh :string not null -# key_auth :string not null -# data :json -# created_at :datetime not null -# updated_at :datetime not null +# id :bigint(8) not null, primary key +# endpoint :string not null +# key_p256dh :string not null +# key_auth :string not null +# data :json +# created_at :datetime not null +# updated_at :datetime not null +# access_token_id :bigint(8) +# user_id :bigint(8) # -require 'webpush' - class Web::PushSubscription < ApplicationRecord + belongs_to :user, optional: true + belongs_to :access_token, class_name: 'Doorkeeper::AccessToken', optional: true + has_one :session_activation def push(notification) - I18n.with_locale(session_activation.user.locale || I18n.default_locale) do + I18n.with_locale(associated_user.locale || I18n.default_locale) do push_payload(message_from(notification), 48.hours.seconds) end end def pushable?(notification) - data&.key?('alerts') && data['alerts'][notification.type.to_s] + data&.key?('alerts') && ActiveModel::Type::Boolean.new.cast(data['alerts'][notification.type.to_s]) end - def as_payload - payload = { id: id, endpoint: endpoint } - payload[:alerts] = data['alerts'] if data&.key?('alerts') - payload + def associated_user + return @associated_user if defined?(@associated_user) + + @associated_user = if user_id.nil? + session_activation.user + else + user + end end - def access_token - find_or_create_access_token.token + def associated_access_token + return @associated_access_token if defined?(@associated_access_token) + + @associated_access_token = if access_token_id.nil? + find_or_create_access_token.token + else + access_token + end end private diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 1d17e2b0a..eefd853ff 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -2,19 +2,15 @@ class InitialStateSerializer < ActiveModel::Serializer attributes :meta, :compose, :accounts, - :media_attachments, :settings, :push_subscription, + :media_attachments, :settings :max_toot_chars - has_many :custom_emojis, serializer: REST::CustomEmojiSerializer + has_one :push_subscription, serializer: REST::WebPushSubscriptionSerializer def max_toot_chars StatusLengthValidator::MAX_CHARS end - def custom_emojis - CustomEmoji.local.where(disabled: false) - end - def meta store = { streaming_api_base_url: Rails.configuration.x.streaming_api_base_url, diff --git a/app/serializers/rest/web_push_subscription_serializer.rb b/app/serializers/rest/web_push_subscription_serializer.rb new file mode 100644 index 000000000..7fd952a56 --- /dev/null +++ b/app/serializers/rest/web_push_subscription_serializer.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class REST::WebPushSubscriptionSerializer < ActiveModel::Serializer + attributes :id, :endpoint, :alerts, :server_key + + def alerts + object.data&.dig('alerts') || {} + end + + def server_key + Rails.configuration.x.vapid_public_key + end +end diff --git a/app/serializers/web/notification_serializer.rb b/app/serializers/web/notification_serializer.rb index e5524fe7a..31c703832 100644 --- a/app/serializers/web/notification_serializer.rb +++ b/app/serializers/web/notification_serializer.rb @@ -54,7 +54,7 @@ class Web::NotificationSerializer < ActiveModel::Serializer def access_token return if actions.empty? - current_push_subscription.access_token + current_push_subscription.associated_access_token end def message diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index ba086449c..6490d2735 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -9,6 +9,7 @@ class NotifyService < BaseService return if recipient.user.nil? || blocked? create_notification + push_notification if @notification.browserable? send_email if email_enabled? rescue ActiveRecord::RecordInvalid return @@ -101,25 +102,27 @@ class NotifyService < BaseService def create_notification @notification.save! - return unless @notification.browserable? + end + + def push_notification + return if @notification.activity.nil? + Redis.current.publish("timeline:#{@recipient.id}", Oj.dump(event: :notification, payload: InlineRenderer.render(@notification, @recipient, :notification))) send_push_notifications end def send_push_notifications - # HACK: Can be caused by quickly unfavouriting a status, since creating - # a favourite and creating a notification are not wrapped in a transaction. - return if @notification.activity.nil? - - sessions_with_subscriptions = @recipient.user.session_activations.where.not(web_push_subscription: nil) - sessions_with_subscriptions_ids = sessions_with_subscriptions.select { |session| session.web_push_subscription.pushable? @notification }.map(&:id) + subscriptions_ids = ::Web::PushSubscription.where(user_id: @recipient.user.id) + .select { |subscription| subscription.pushable?(@notification) } + .map(&:id) - WebPushNotificationWorker.push_bulk(sessions_with_subscriptions_ids) do |session_activation_id| - [session_activation_id, @notification.id] + ::Web::PushNotificationWorker.push_bulk(subscriptions_ids) do |subscription_id| + [subscription_id, @notification.id] end end def send_email + return if @notification.activity.nil? NotificationMailer.public_send(@notification.type, @recipient, @notification).deliver_later end diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml index bbf2139a5..cfdd3a945 100644 --- a/app/views/accounts/show.html.haml +++ b/app/views/accounts/show.html.haml @@ -8,6 +8,7 @@ %meta{ name: 'robots', content: 'noindex' }/ %link{ rel: 'salmon', href: api_salmon_url(@account.id) }/ + %link{ rel: 'alternate', type: 'application/rss+xml', href: account_url(@account, format: 'rss') }/ %link{ rel: 'alternate', type: 'application/atom+xml', href: account_url(@account, format: 'atom') }/ %link{ rel: 'alternate', type: 'application/activity+json', href: ActivityPub::TagManager.instance.uri_for(@account) }/ diff --git a/app/views/tags/_og.html.haml b/app/views/tags/_og.html.haml index 853a499ae..a7c289bcb 100644 --- a/app/views/tags/_og.html.haml +++ b/app/views/tags/_og.html.haml @@ -2,5 +2,5 @@ = opengraph 'og:url', tag_url(@tag) = opengraph 'og:type', 'website' = opengraph 'og:title', "##{@tag.name}" -= opengraph 'og:description', t('about.about_hashtag_html', hashtag: @tag.name) += opengraph 'og:description', strip_tags(t('about.about_hashtag_html', hashtag: @tag.name)) = opengraph 'twitter:card', 'summary' diff --git a/app/views/tags/show.html.haml b/app/views/tags/show.html.haml index c2202a9eb..2b46e58c7 100644 --- a/app/views/tags/show.html.haml +++ b/app/views/tags/show.html.haml @@ -2,6 +2,8 @@ = "##{@tag.name}" - content_for :header_tags do + %link{ rel: 'alternate', type: 'application/rss+xml', href: tag_url(@tag, format: 'rss') }/ + %script#initial-state{ type: 'application/json' }!= json_escape(@initial_state_json) = render 'og' diff --git a/app/workers/web/push_notification_worker.rb b/app/workers/web/push_notification_worker.rb new file mode 100644 index 000000000..4a40e5c8b --- /dev/null +++ b/app/workers/web/push_notification_worker.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class Web::PushNotificationWorker + include Sidekiq::Worker + + sidekiq_options backtrace: true + + def perform(subscription_id, notification_id) + subscription = ::Web::PushSubscription.find(subscription_id) + notification = Notification.find(notification_id) + + subscription.push(notification) unless notification.activity.nil? + rescue Webpush::InvalidSubscription, Webpush::ExpiredSubscription + subscription.destroy! + rescue ActiveRecord::RecordNotFound + true + end +end diff --git a/app/workers/web_push_notification_worker.rb b/app/workers/web_push_notification_worker.rb deleted file mode 100644 index eacea04c3..000000000 --- a/app/workers/web_push_notification_worker.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -class WebPushNotificationWorker - include Sidekiq::Worker - - sidekiq_options backtrace: true - - def perform(session_activation_id, notification_id) - session_activation = SessionActivation.find(session_activation_id) - notification = Notification.find(notification_id) - - return if session_activation.web_push_subscription.nil? || notification.activity.nil? - - session_activation.web_push_subscription.push(notification) - rescue Webpush::InvalidSubscription, Webpush::ExpiredSubscription - # Subscription expiration is not currently implemented in any browser - - session_activation.web_push_subscription.destroy! - session_activation.update!(web_push_subscription: nil) - - true - rescue ActiveRecord::RecordNotFound - true - end -end |